mirror of https://github.com/tiangolo/fastapi.git
🌐 Update translations for ko (update-all and add-missing) (#14923)
* Update all and add missing
* 🎨 Auto format
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
82d90c51b4
commit
01e2e1088c
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
//// tab | 테스트
|
||||
|
||||
어제 제 친구가 이렇게 썼습니다: "If you spell incorrectly correctly, you have spelled it incorrectly". 이에 저는 이렇게 답했습니다: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"".
|
||||
어제 제 친구가 이렇게 썼습니다: "If you spell incorrectly correctly, you have spelled it incorrectly". 이에 저는 이렇게 답했습니다: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'".
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -256,15 +256,15 @@ works(foo="bar") # 이건 동작합니다 🎉
|
|||
|
||||
//// tab | 테스트
|
||||
|
||||
* 당신
|
||||
* 당신의
|
||||
* 여러분
|
||||
* 여러분의
|
||||
|
||||
* 예: (e.g.)
|
||||
* 등 (etc.)
|
||||
|
||||
* `int`로서의 `foo`
|
||||
* `str`로서의 `bar`
|
||||
* `list`로서의 `baz`
|
||||
* `foo`로서의 `int`
|
||||
* `bar`로서의 `str`
|
||||
* `baz`로서의 `list`
|
||||
|
||||
* 튜토리얼 - 사용자 가이드
|
||||
* 고급 사용자 가이드
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
예를 들어, 상태 코드 `404`와 Pydantic 모델 `Message`를 사용하는 다른 응답을 선언하려면 다음과 같이 작성할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
|
||||
{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -203,7 +203,7 @@
|
|||
|
||||
또한 `response_model`을 사용하는 상태 코드 `200` 응답을 선언하되, 커스텀 `example`을 포함할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
|
||||
{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *}
|
||||
|
||||
이 모든 내용은 OpenAPI에 결합되어 포함되고, API 문서에 표시됩니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
# 추가 상태 코드 { #additional-status-codes }
|
||||
|
||||
기본적으로 **FastAPI**는 응답을 `JSONResponse`를 사용하여 반환하며, *경로 작업(path operation)*에서 반환한 내용을 해당 `JSONResponse` 안에 넣어 반환합니다.
|
||||
기본적으로 **FastAPI**는 응답을 `JSONResponse`를 사용하여 반환하며, *경로 처리*에서 반환한 내용을 해당 `JSONResponse` 안에 넣어 반환합니다.
|
||||
|
||||
기본 상태 코드 또는 *경로 작업*에서 설정한 상태 코드를 사용합니다.
|
||||
기본 상태 코드 또는 *경로 처리*에서 설정한 상태 코드를 사용합니다.
|
||||
|
||||
## 추가 상태 코드 { #additional-status-codes_1 }
|
||||
|
||||
기본 상태 코드와 별도로 추가 상태 코드를 반환하려면 `JSONResponse`와 같이 `Response`를 직접 반환하고 추가 상태 코드를 직접 설정할 수 있습니다.
|
||||
|
||||
예를 들어 항목을 업데이트할 수 있는 *경로 작업*이 있고 성공 시 200 “OK”의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다.
|
||||
예를 들어 항목을 업데이트할 수 있는 *경로 처리*가 있고 성공 시 200 “OK”의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다.
|
||||
|
||||
하지만 새로운 항목을 허용하기를 원할 것입니다. 그리고 항목이 이전에 존재하지 않았다면 이를 생성하고 HTTP 상태 코드 201 "Created"를 반환합니다.
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
|
||||
|
||||
/// warning | 경고
|
||||
/// warning
|
||||
|
||||
위의 예제처럼 `Response`를 직접 반환하면 바로 반환됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Python에는 클래스의 인스턴스를 "호출 가능"하게 만드는 방법
|
|||
|
||||
이를 위해 `__call__` 메서드를 선언합니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *}
|
||||
|
||||
이 경우, **FastAPI**는 추가 매개변수와 하위 의존성을 확인하기 위해 `__call__`을 사용하게 되며,
|
||||
나중에 *경로 처리 함수*에서 매개변수에 값을 전달할 때 이를 호출하게 됩니다.
|
||||
|
|
@ -27,7 +27,7 @@ Python에는 클래스의 인스턴스를 "호출 가능"하게 만드는 방법
|
|||
|
||||
이제 `__init__`을 사용하여 의존성을 "매개변수화"할 수 있는 인스턴스의 매개변수를 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *}
|
||||
|
||||
이 경우, **FastAPI**는 `__init__`에 전혀 관여하지 않으며, 우리는 이 메서드를 코드에서 직접 사용하게 됩니다.
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Python에는 클래스의 인스턴스를 "호출 가능"하게 만드는 방법
|
|||
|
||||
다음과 같이 이 클래스의 인스턴스를 생성할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
|
||||
|
||||
이렇게 하면 `checker.fixed_content` 속성에 `"bar"`라는 값을 담아 의존성을 "매개변수화"할 수 있습니다.
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ checker(q="somequery")
|
|||
|
||||
...그리고 이때 반환되는 값을 *경로 처리 함수*의 의존성 값으로, `fixed_content_included` 매개변수에 전달합니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
# 고급 Python 타입 { #advanced-python-types }
|
||||
|
||||
Python 타입을 다룰 때 유용할 수 있는 몇 가지 추가 아이디어를 소개합니다.
|
||||
|
||||
## `Union` 또는 `Optional` 사용 { #using-union-or-optional }
|
||||
|
||||
어떤 이유로 코드에서 `|`를 사용할 수 없다면, 예를 들어 타입 어노테이션이 아니라 `response_model=` 같은 곳이라면, 파이프 문자(`|`) 대신 `typing`의 `Union`을 사용할 수 있습니다.
|
||||
|
||||
예를 들어, 어떤 값이 `str` 또는 `None`이 될 수 있다고 선언할 수 있습니다:
|
||||
|
||||
```python
|
||||
from typing import Union
|
||||
|
||||
|
||||
def say_hi(name: Union[str, None]):
|
||||
print(f"Hi {name}!")
|
||||
```
|
||||
|
||||
`typing`에는 `None`이 될 수 있음을 선언하는 축약형으로 `Optional`도 있습니다.
|
||||
|
||||
아주 개인적인 관점에서의 팁입니다:
|
||||
|
||||
- 🚨 `Optional[SomeType]` 사용은 피하세요
|
||||
- 대신 ✨ **`Union[SomeType, None]`를 사용하세요** ✨.
|
||||
|
||||
둘은 동등하며 내부적으로도 같습니다. 하지만 단어 "optional"은 값이 선택 사항이라는 인상을 주는 반면, 실제 의미는 "값이 `None`이 될 수 있다"는 뜻입니다. 값이 선택 사항이 아니라 여전히 필수인 경우에도 그렇습니다.
|
||||
|
||||
`Union[SomeType, None]`가 의미를 더 명확하게 드러낸다고 생각합니다.
|
||||
|
||||
이는 단지 단어와 명칭의 문제입니다. 하지만 이런 단어가 여러분과 팀원이 코드를 어떻게 생각하는지에 영향을 줄 수 있습니다.
|
||||
|
||||
예를 들어, 다음 함수를 보세요:
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def say_hi(name: Optional[str]):
|
||||
print(f"Hey {name}!")
|
||||
```
|
||||
|
||||
매개변수 `name`은 `Optional[str]`로 정의되어 있지만, 사실 선택적이지 않습니다. 이 매개변수 없이 함수를 호출할 수 없습니다:
|
||||
|
||||
```Python
|
||||
say_hi() # 이런, 에러가 발생합니다! 😱
|
||||
```
|
||||
|
||||
`name` 매개변수는 기본값이 없기 때문에 여전히 필수입니다(선택적이 아님). 대신, `name`에는 `None`을 전달할 수 있습니다:
|
||||
|
||||
```Python
|
||||
say_hi(name=None) # 작동합니다. None은 유효합니다 🎉
|
||||
```
|
||||
|
||||
좋은 소식은, 대부분의 경우 타입의 합집합을 정의할 때 그냥 `|`를 사용할 수 있다는 점입니다:
|
||||
|
||||
```python
|
||||
def say_hi(name: str | None):
|
||||
print(f"Hey {name}!")
|
||||
```
|
||||
|
||||
그래서 보통은 `Optional`과 `Union` 같은 이름에 대해 걱정하지 않으셔도 됩니다. 😎
|
||||
|
|
@ -32,11 +32,11 @@
|
|||
|
||||
`main.py` 파일은 다음과 같습니다:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/main.py *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/main.py *}
|
||||
|
||||
`test_main.py` 파일에는 `main.py`에 대한 테스트가 있으며, 이제 다음과 같이 보일 수 있습니다:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py *}
|
||||
|
||||
## 실행하기 { #run-it }
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ $ pytest
|
|||
|
||||
`@pytest.mark.anyio` 마커는 pytest에게 이 테스트 함수가 비동기로 호출되어야 한다고 알려줍니다:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ $ pytest
|
|||
|
||||
그 다음 앱으로 `AsyncClient`를 만들고, `await`를 사용해 비동기 요청을 보낼 수 있습니다.
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *}
|
||||
|
||||
이는 다음과 동등합니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*"
|
|||
|
||||
예를 들어, *경로 처리* `/items/`를 정의했다고 해봅시다:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *}
|
||||
|
||||
클라이언트가 `/items`로 접근하면, 기본적으로 `/items/`로 리디렉션됩니다.
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ sequenceDiagram
|
|||
|
||||
코드는 모두 `/app`만 있다고 가정하고 작성되어 있는데도 말입니다.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *}
|
||||
|
||||
그리고 프록시는 요청을 앱 서버(아마 FastAPI CLI를 통해 실행되는 Uvicorn)로 전달하기 전에, 동적으로 **경로 접두사**를 **"제거"**합니다. 그래서 애플리케이션은 여전히 `/app`에서 서비스된다고 믿게 되고, 코드 전체를 `/api/v1` 접두사를 포함하도록 수정할 필요가 없어집니다.
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ ASGI 사양은 이 사용 사례를 위해 `root_path`를 정의합니다.
|
|||
|
||||
여기서는 데모 목적을 위해 메시지에 포함하고 있습니다.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *}
|
||||
|
||||
그 다음 Uvicorn을 다음과 같이 시작하면:
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
|
|||
|
||||
또는 `--root-path` 같은 커맨드 라인 옵션(또는 동등한 방법)을 제공할 수 없는 경우, FastAPI 앱을 생성할 때 `root_path` 파라미터를 설정할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *}
|
||||
|
||||
`FastAPI`에 `root_path`를 전달하는 것은 Uvicorn이나 Hypercorn에 커맨드 라인 옵션 `--root-path`를 전달하는 것과 동일합니다.
|
||||
|
||||
|
|
@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
|
|||
|
||||
예:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *}
|
||||
|
||||
다음과 같은 OpenAPI 스키마를 생성합니다:
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ OpenAPI 사양에서 `servers` 속성은 선택 사항입니다.
|
|||
|
||||
**FastAPI**가 `root_path`를 사용한 자동 server를 포함하지 않게 하려면, `root_path_in_servers=False` 파라미터를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *}
|
||||
|
||||
그러면 OpenAPI 스키마에 포함되지 않습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
하지만 반환하는 내용이 **JSON으로 직렬화 가능**하다고 확신하는 경우, 해당 내용을 응답 클래스에 직접 전달할 수 있으며, FastAPI가 반환 내용을 `jsonable_encoder`를 통해 처리한 뒤 응답 클래스에 전달하는 오버헤드를 피할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
* `HTMLResponse`를 임포트 합니다.
|
||||
* *경로 처리 데코레이터*의 `response_class` 매개변수로 `HTMLResponse`를 전달합니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
|
||||
위의 예제와 동일하게 `HTMLResponse`를 반환하는 코드는 다음과 같을 수 있습니다:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
|
||||
{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
|
||||
|
||||
/// warning | 경고
|
||||
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
|
||||
예를 들어, 다음과 같이 작성할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
|
||||
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
|
||||
|
||||
이 예제에서, `generate_html_response()` 함수는 HTML을 `str`로 반환하는 대신 이미 `Response`를 생성하고 반환합니다.
|
||||
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
|
||||
FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함시킵니다. 또한 `media_type`에 기반하여 Content-Type 헤더를 포함하며, 텍스트 타입의 경우 문자 집합을 추가 합니다.
|
||||
|
||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
||||
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
|
||||
|
||||
### `HTMLResponse` { #htmlresponse }
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함
|
|||
|
||||
텍스트 또는 바이트를 받아 일반 텍스트 응답을 반환합니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
|
||||
|
||||
### `JSONResponse` { #jsonresponse }
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ FastAPI (실제로는 Starlette)가 자동으로 Content-Length 헤더를 포함
|
|||
|
||||
///
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -194,14 +194,14 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
`RedirectResponse`를 직접 반환할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
|
||||
|
||||
---
|
||||
|
||||
또는 `response_class` 매개변수에서 사용할 수도 있습니다:
|
||||
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
|
||||
|
||||
이 경우, *경로 처리* 함수에서 URL을 직접 반환할 수 있습니다.
|
||||
|
||||
|
|
@ -211,13 +211,13 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
`status_code` 매개변수를 `response_class` 매개변수와 함께 사용할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
|
||||
|
||||
### `StreamingResponse` { #streamingresponse }
|
||||
|
||||
비동기 제너레이터 또는 일반 제너레이터/이터레이터를 받아 응답 본문을 스트리밍 합니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
|
||||
{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
|
||||
|
||||
#### 파일과 같은 객체를 사용한 `StreamingResponse` { #using-streamingresponse-with-file-like-objects }
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
이 방식은 클라우드 스토리지, 비디오 처리 등의 다양한 라이브러리와 함께 사용할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
|
||||
{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
|
||||
|
||||
1. 이것이 제너레이터 함수입니다. `yield` 문을 포함하고 있으므로 "제너레이터 함수"입니다.
|
||||
2. `with` 블록을 사용함으로써, 제너레이터 함수가 완료된 후 파일과 같은 객체가 닫히도록 합니다. 즉, 응답 전송이 끝난 후 닫힙니다.
|
||||
|
|
@ -256,11 +256,11 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
파일 응답에는 적절한 `Content-Length`, `Last-Modified`, 및 `ETag` 헤더가 포함됩니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
|
||||
{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
|
||||
|
||||
또한 `response_class` 매개변수를 사용할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
|
||||
{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
|
||||
|
||||
이 경우, 경로 처리 함수에서 파일 경로를 직접 반환할 수 있습니다.
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
`CustomORJSONResponse`를 생성할 수 있습니다. 여기서 핵심은 `Response.render(content)` 메서드를 생성하여 내용을 `bytes`로 반환하는 것입니다:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
|
||||
{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
|
||||
|
||||
이제 다음 대신:
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ HTTP 리디렉션 응답을 반환합니다. 기본적으로 상태 코드는 30
|
|||
|
||||
아래 예제에서 **FastAPI**는 모든 *경로 처리*에서 기본적으로 `JSONResponse` 대신 `ORJSONResponse`를 사용합니다.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
|
||||
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ dataclass는 자동으로 Pydantic dataclass로 변환됩니다.
|
|||
|
||||
6. 여기서는 dataclasses 리스트인 `items`를 포함하는 딕셔너리를 반환합니다.
|
||||
|
||||
FastAPI는 여전히 데이터를 JSON으로 <abbr title="converting the data to a format that can be transmitted - 데이터를 전송 가능한 형식으로 변환하는 것">serializing</abbr>할 수 있습니다.
|
||||
FastAPI는 여전히 데이터를 JSON으로 <dfn title="데이터를 전송 가능한 형식으로 변환하는 것">직렬화</dfn>할 수 있습니다.
|
||||
|
||||
7. 여기서 `response_model`은 `Author` dataclasses 리스트에 대한 타입 애너테이션을 사용합니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
`yield`를 사용해 비동기 함수 `lifespan()`을 다음과 같이 생성합니다:
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
|
||||
|
||||
여기서는 `yield` 이전에 (가짜) 모델 함수를 머신러닝 모델이 들어 있는 딕셔너리에 넣어 모델을 로드하는 비용이 큰 *시작* 작업을 시뮬레이션합니다. 이 코드는 애플리케이션이 **요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다.
|
||||
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
먼저 주목할 점은 `yield`를 사용하여 비동기 함수를 정의하고 있다는 것입니다. 이는 `yield`를 사용하는 의존성과 매우 유사합니다.
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
|
||||
|
||||
함수의 첫 번째 부분, 즉 `yield` 이전의 코드는 애플리케이션이 시작되기 **전에** 실행됩니다.
|
||||
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
이는 함수를 "**비동기 컨텍스트 매니저**"라고 불리는 것으로 변환합니다.
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
|
||||
|
||||
파이썬에서 **컨텍스트 매니저**는 `with` 문에서 사용할 수 있는 것입니다. 예를 들어, `open()`은 컨텍스트 매니저로 사용할 수 있습니다:
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ async with lifespan(app):
|
|||
|
||||
`FastAPI` 앱의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받으므로, 새 `lifespan` 비동기 컨텍스트 매니저를 전달할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
|
||||
|
||||
## 대체 이벤트(사용 중단) { #alternative-events-deprecated }
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ async with lifespan(app):
|
|||
|
||||
애플리케이션이 시작되기 전에 실행되어야 하는 함수를 추가하려면, `"startup"` 이벤트로 선언합니다:
|
||||
|
||||
{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/events/tutorial001_py310.py hl[8] *}
|
||||
|
||||
이 경우, `startup` 이벤트 핸들러 함수는 "database"(그냥 `dict`) 항목을 일부 값으로 초기화합니다.
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ async with lifespan(app):
|
|||
|
||||
애플리케이션이 종료될 때 실행되어야 하는 함수를 추가하려면, `"shutdown"` 이벤트로 선언합니다:
|
||||
|
||||
{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
|
||||
{* ../../docs_src/events/tutorial002_py310.py hl[6] *}
|
||||
|
||||
여기서 `shutdown` 이벤트 핸들러 함수는 텍스트 한 줄 `"Application shutdown"`을 `log.txt` 파일에 기록합니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는
|
|||
|
||||
간단한 FastAPI 애플리케이션으로 시작해 보겠습니다:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
|
||||
{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
|
||||
|
||||
*path operation*에서 요청 페이로드와 응답 페이로드에 사용하는 모델을 `Item`, `ResponseMessage` 모델로 정의하고 있다는 점에 주목하세요.
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
|
|||
|
||||
예를 들어 **items** 섹션과 **users** 섹션이 있고, 이를 태그로 분리할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
|
||||
{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *}
|
||||
|
||||
### 태그로 TypeScript 클라이언트 생성하기 { #generate-a-typescript-client-with-tags }
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ FastAPI는 각 *path operation*에 대해 **유일 ID**를 사용하며, 이는
|
|||
|
||||
그 다음 이 커스텀 함수를 `generate_unique_id_function` 매개변수로 **FastAPI**에 전달할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
|
||||
{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *}
|
||||
|
||||
### 커스텀 Operation ID로 TypeScript 클라이언트 생성하기 { #generate-a-typescript-client-with-custom-operation-ids }
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ OpenAPI 전반에서는 operation ID가 **유일**하다는 것을 보장하기
|
|||
|
||||
OpenAPI JSON을 `openapi.json` 파일로 다운로드한 뒤, 아래와 같은 스크립트로 **접두사 태그를 제거**할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial004_py39.py *}
|
||||
{* ../../docs_src/generate_clients/tutorial004_py310.py *}
|
||||
|
||||
//// tab | Node.js
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 심화 사용자 안내서 - 도입부 { #advanced-user-guide }
|
||||
# 심화 사용자 안내서 { #advanced-user-guide }
|
||||
|
||||
## 추가 기능 { #additional-features }
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
## ASGI middleware 추가하기 { #adding-asgi-middlewares }
|
||||
|
||||
**FastAPI**는 Starlette를 기반으로 하고 <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> 사양을 구현하므로, 어떤 ASGI middleware든 사용할 수 있습니다.
|
||||
**FastAPI**는 Starlette를 기반으로 하고 <abbr title="Asynchronous Server Gateway Interface - 비동기 서버 게이트웨이 인터페이스">ASGI</abbr> 사양을 구현하므로, 어떤 ASGI middleware든 사용할 수 있습니다.
|
||||
|
||||
ASGI 사양을 따르기만 하면, FastAPI나 Starlette를 위해 만들어진 middleware가 아니어도 동작합니다.
|
||||
|
||||
|
|
@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
|
|||
|
||||
`http` 또는 `ws`로 들어오는 모든 요청은 대신 보안 스킴으로 리디렉션됩니다.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *}
|
||||
|
||||
## `TrustedHostMiddleware` { #trustedhostmiddleware }
|
||||
|
||||
HTTP Host Header 공격을 방어하기 위해, 들어오는 모든 요청에 올바르게 설정된 `Host` 헤더가 있어야 하도록 강제합니다.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *}
|
||||
|
||||
다음 인자들을 지원합니다:
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ HTTP Host Header 공격을 방어하기 위해, 들어오는 모든 요청에
|
|||
|
||||
이 middleware는 일반 응답과 스트리밍 응답을 모두 처리합니다.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *}
|
||||
|
||||
다음 인자들을 지원합니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# OpenAPI 콜백 { #openapi-callbacks }
|
||||
|
||||
다른 사람이 만든 *external API*(아마도 당신의 API를 *사용*할 동일한 개발자)가 요청을 트리거하도록 만드는 *경로 처리*를 가진 API를 만들 수 있습니다.
|
||||
다른 사람이 만든 *external API*(아마도 여러분의 API를 *사용*할 동일한 개발자)가 요청을 트리거하도록 만드는 *경로 처리*를 가진 API를 만들 수 있습니다.
|
||||
|
||||
당신의 API 앱이 *external API*를 호출할 때 일어나는 과정을 "callback"이라고 합니다. 외부 개발자가 작성한 소프트웨어가 당신의 API로 요청을 보낸 다음, 당신의 API가 다시 *external API*로 요청을 보내 *되돌려 호출*하기 때문입니다(아마도 같은 개발자가 만든 API일 것입니다).
|
||||
여러분의 API 앱이 *external API*를 호출할 때 일어나는 과정을 "callback"이라고 합니다. 외부 개발자가 작성한 소프트웨어가 여러분의 API로 요청을 보낸 다음, 여러분의 API가 다시 *external API*로 요청을 보내 *되돌려 호출*하기 때문입니다(아마도 같은 개발자가 만든 API일 것입니다).
|
||||
|
||||
이 경우, 그 *external API*가 어떤 형태여야 하는지 문서화하고 싶을 수 있습니다. 어떤 *경로 처리*를 가져야 하는지, 어떤 body를 기대하는지, 어떤 응답을 반환해야 하는지 등입니다.
|
||||
|
||||
|
|
@ -14,14 +14,14 @@
|
|||
|
||||
이 청구서는 `id`, `title`(선택 사항), `customer`, `total`을 갖습니다.
|
||||
|
||||
당신의 API 사용자(외부 개발자)는 POST 요청으로 당신의 API에서 청구서를 생성합니다.
|
||||
여러분의 API 사용자(외부 개발자)는 POST 요청으로 여러분의 API에서 청구서를 생성합니다.
|
||||
|
||||
그 다음 당신의 API는(가정해 보면):
|
||||
그 다음 여러분의 API는(가정해 보면):
|
||||
|
||||
* 청구서를 외부 개발자의 고객에게 전송합니다.
|
||||
* 돈을 수금합니다.
|
||||
* API 사용자(외부 개발자)의 API로 다시 알림을 보냅니다.
|
||||
* 이는 (당신의 API에서) 그 외부 개발자가 제공하는 어떤 *external API*로 POST 요청을 보내는 방식으로 수행됩니다(이것이 "callback"입니다).
|
||||
* 이는 (여러분의 API에서) 그 외부 개발자가 제공하는 어떤 *external API*로 POST 요청을 보내는 방식으로 수행됩니다(이것이 "callback"입니다).
|
||||
|
||||
## 일반적인 **FastAPI** 앱 { #the-normal-fastapi-app }
|
||||
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
## 콜백 문서화하기 { #documenting-the-callback }
|
||||
|
||||
실제 콜백 코드는 당신의 API 앱에 크게 의존합니다.
|
||||
실제 콜백 코드는 여러분의 API 앱에 크게 의존합니다.
|
||||
|
||||
그리고 앱마다 많이 달라질 수 있습니다.
|
||||
|
||||
|
|
@ -54,11 +54,11 @@ callback_url = "https://example.com/api/v1/invoices/events/"
|
|||
httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
|
||||
```
|
||||
|
||||
하지만 콜백에서 가장 중요한 부분은, 당신의 API 사용자(외부 개발자)가 콜백 요청 body로 *당신의 API*가 보낼 데이터 등에 맞춰 *external API*를 올바르게 구현하도록 보장하는 것입니다.
|
||||
하지만 콜백에서 가장 중요한 부분은, 여러분의 API 사용자(외부 개발자)가 콜백 요청 body로 *여러분의 API*가 보낼 데이터 등에 맞춰 *external API*를 올바르게 구현하도록 보장하는 것입니다.
|
||||
|
||||
그래서 다음으로 할 일은, *당신의 API*에서 보내는 콜백을 받기 위해 그 *external API*가 어떤 형태여야 하는지 문서화하는 코드를 추가하는 것입니다.
|
||||
그래서 다음으로 할 일은, *여러분의 API*에서 보내는 콜백을 받기 위해 그 *external API*가 어떤 형태여야 하는지 문서화하는 코드를 추가하는 것입니다.
|
||||
|
||||
그 문서는 당신의 API에서 `/docs`의 Swagger UI에 표시되며, 외부 개발자들이 *external API*를 어떻게 만들어야 하는지 알 수 있게 해줍니다.
|
||||
그 문서는 여러분의 API에서 `/docs`의 Swagger UI에 표시되며, 외부 개발자들이 *external API*를 어떻게 만들어야 하는지 알 수 있게 해줍니다.
|
||||
|
||||
이 예시는 콜백 자체(한 줄 코드로도 될 수 있음)를 구현하지 않고, 문서화 부분만 구현합니다.
|
||||
|
||||
|
|
@ -76,11 +76,11 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
|
|||
|
||||
하지만 **FastAPI**로 API의 자동 문서를 쉽게 생성하는 방법은 이미 알고 있습니다.
|
||||
|
||||
따라서 그와 같은 지식을 사용해 *external API*가 어떻게 생겨야 하는지 문서화할 것입니다... 즉 외부 API가 구현해야 하는 *경로 처리(들)*(당신의 API가 호출할 것들)을 만들어서 말입니다.
|
||||
따라서 그와 같은 지식을 사용해 *external API*가 어떻게 생겨야 하는지 문서화할 것입니다... 즉 외부 API가 구현해야 하는 *경로 처리(들)*(여러분의 API가 호출할 것들)을 만들어서 말입니다.
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
콜백을 문서화하는 코드를 작성할 때는, 자신이 그 *외부 개발자*라고 상상하는 것이 유용할 수 있습니다. 그리고 지금은 *당신의 API*가 아니라 *external API*를 구현하고 있다고 생각해 보세요.
|
||||
콜백을 문서화하는 코드를 작성할 때는, 자신이 그 *외부 개발자*라고 상상하는 것이 유용할 수 있습니다. 그리고 지금은 *여러분의 API*가 아니라 *external API*를 구현하고 있다고 생각해 보세요.
|
||||
|
||||
이 관점(외부 개발자의 관점)을 잠시 채택하면, 그 *external API*를 위해 파라미터, body용 Pydantic 모델, 응답 등을 어디에 두어야 하는지가 더 명확하게 느껴질 수 있습니다.
|
||||
|
||||
|
|
@ -105,12 +105,12 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
|
|||
|
||||
일반적인 *경로 처리*와의 주요 차이점은 2가지입니다:
|
||||
|
||||
* 실제 코드를 가질 필요가 없습니다. 당신의 앱은 이 코드를 절대 호출하지 않기 때문입니다. 이는 *external API*를 문서화하는 데만 사용됩니다. 따라서 함수는 그냥 `pass`만 있어도 됩니다.
|
||||
* *path*에는 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a>(자세한 내용은 아래 참고)이 포함될 수 있으며, 이를 통해 *당신의 API*로 보내진 원래 요청의 파라미터와 일부 값을 변수로 사용할 수 있습니다.
|
||||
* 실제 코드를 가질 필요가 없습니다. 여러분의 앱은 이 코드를 절대 호출하지 않기 때문입니다. 이는 *external API*를 문서화하는 데만 사용됩니다. 따라서 함수는 그냥 `pass`만 있어도 됩니다.
|
||||
* *path*에는 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a>(자세한 내용은 아래 참고)이 포함될 수 있으며, 이를 통해 *여러분의 API*로 보내진 원래 요청의 파라미터와 일부 값을 변수로 사용할 수 있습니다.
|
||||
|
||||
### 콜백 경로 표현식 { #the-callback-path-expression }
|
||||
|
||||
콜백 *path*는 *당신의 API*로 보내진 원래 요청의 일부를 포함할 수 있는 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a>을 가질 수 있습니다.
|
||||
콜백 *path*는 *여러분의 API*로 보내진 원래 요청의 일부를 포함할 수 있는 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a>을 가질 수 있습니다.
|
||||
|
||||
이 경우, 다음 `str`입니다:
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
|
|||
"{$callback_url}/invoices/{$request.body.id}"
|
||||
```
|
||||
|
||||
따라서 당신의 API 사용자(외부 개발자)가 *당신의 API*로 다음 요청을 보내고:
|
||||
따라서 여러분의 API 사용자(외부 개발자)가 *여러분의 API*로 다음 요청을 보내고:
|
||||
|
||||
```
|
||||
https://yourapi.com/invoices/?callback_url=https://www.external.org/events
|
||||
|
|
@ -134,7 +134,7 @@ JSON body가 다음과 같다면:
|
|||
}
|
||||
```
|
||||
|
||||
그러면 *당신의 API*는 청구서를 처리하고, 나중에 어느 시점에서 `callback_url`(즉 *external API*)로 콜백 요청을 보냅니다:
|
||||
그러면 *여러분의 API*는 청구서를 처리하고, 나중에 어느 시점에서 `callback_url`(즉 *external API*)로 콜백 요청을 보냅니다:
|
||||
|
||||
```
|
||||
https://www.external.org/events/invoices/2expen51ve
|
||||
|
|
@ -167,7 +167,7 @@ https://www.external.org/events/invoices/2expen51ve
|
|||
|
||||
이 시점에서, 위에서 만든 콜백 라우터 안에 *콜백 경로 처리(들)*(즉 *external developer*가 *external API*에 구현해야 하는 것들)을 준비했습니다.
|
||||
|
||||
이제 *당신의 API 경로 처리 데코레이터*에서 `callbacks` 파라미터를 사용해, 그 콜백 라우터의 `.routes` 속성(실제로는 routes/*경로 처리*의 `list`)을 전달합니다:
|
||||
이제 *여러분의 API 경로 처리 데코레이터*에서 `callbacks` 파라미터를 사용해, 그 콜백 라우터의 `.routes` 속성(실제로는 routes/*경로 처리*의 `list`)을 전달합니다:
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Webhooks는 OpenAPI 3.1.0 이상에서 사용할 수 있으며, FastAPI `0.99.0`
|
|||
|
||||
**FastAPI** 애플리케이션을 만들면, *경로 처리*를 정의하는 것과 같은 방식으로(예: `@app.webhooks.post()`), *webhooks*를 정의하는 데 사용할 수 있는 `webhooks` 속성이 있습니다.
|
||||
|
||||
{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
|
||||
{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *}
|
||||
|
||||
여러분이 정의한 webhook은 **OpenAPI** 스키마와 자동 **docs UI**에 포함됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ OpenAPI “전문가”가 아니라면, 아마 이 내용은 필요하지 않
|
|||
|
||||
각 작업마다 고유하도록 보장해야 합니다.
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *}
|
||||
|
||||
### *경로 처리 함수* 이름을 operationId로 사용하기 { #using-the-path-operation-function-name-as-the-operationid }
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ API의 함수 이름을 `operationId`로 사용하고 싶다면, 모든 API를
|
|||
|
||||
모든 *경로 처리*를 추가한 뒤에 수행해야 합니다.
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ API의 함수 이름을 `operationId`로 사용하고 싶다면, 모든 API를
|
|||
|
||||
생성된 OpenAPI 스키마(따라서 자동 문서화 시스템)에서 특정 *경로 처리*를 제외하려면, `include_in_schema` 매개변수를 `False`로 설정하세요:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *}
|
||||
|
||||
## docstring에서 고급 설명 가져오기 { #advanced-description-from-docstring }
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ OpenAPI 명세에서는 이를 <a href="https://github.com/OAI/OpenAPI-Specifica
|
|||
|
||||
예를 들어 `openapi_extra`는 [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)를 선언하는 데 도움이 될 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *}
|
||||
|
||||
자동 API 문서를 열면, 해당 특정 *경로 처리*의 하단에 확장이 표시됩니다.
|
||||
|
||||
|
|
@ -139,9 +139,9 @@ OpenAPI 명세에서는 이를 <a href="https://github.com/OAI/OpenAPI-Specifica
|
|||
|
||||
그럴 때 `openapi_extra`를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *}
|
||||
|
||||
이 예시에서는 어떤 Pydantic 모델도 선언하지 않았습니다. 사실 요청 바디는 JSON으로 <abbr title="converted from some plain format, like bytes, into Python objects - bytes 같은 일반 형식에서 Python 객체로 변환">parsed</abbr>되지도 않고, `bytes`로 직접 읽습니다. 그리고 함수 `magic_data_reader()`가 어떤 방식으로든 이를 파싱하는 역할을 담당합니다.
|
||||
이 예시에서는 어떤 Pydantic 모델도 선언하지 않았습니다. 사실 요청 바디는 JSON으로 <dfn title="bytes 같은 일반 형식에서 Python 객체로 변환">파싱</dfn>되지도 않고, `bytes`로 직접 읽습니다. 그리고 함수 `magic_data_reader()`가 어떤 방식으로든 이를 파싱하는 역할을 담당합니다.
|
||||
|
||||
그럼에도 불구하고, 요청 바디에 대해 기대하는 스키마를 선언할 수 있습니다.
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ OpenAPI 명세에서는 이를 <a href="https://github.com/OAI/OpenAPI-Specifica
|
|||
|
||||
예를 들어 이 애플리케이션에서는 Pydantic 모델에서 JSON Schema를 추출하는 FastAPI의 통합 기능도, JSON에 대한 자동 검증도 사용하지 않습니다. 실제로 요청 콘텐츠 타입을 JSON이 아니라 YAML로 선언합니다:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *}
|
||||
|
||||
그럼에도 기본 통합 기능을 사용하지 않더라도, YAML로 받고자 하는 데이터에 대한 JSON Schema를 수동으로 생성하기 위해 Pydantic 모델을 여전히 사용합니다.
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ OpenAPI 명세에서는 이를 <a href="https://github.com/OAI/OpenAPI-Specifica
|
|||
|
||||
그리고 코드에서 YAML 콘텐츠를 직접 파싱한 뒤, 다시 같은 Pydantic 모델을 사용해 YAML 콘텐츠를 검증합니다:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
그리고 이 *임시* 응답 객체에서 `status_code`를 설정할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
|
||||
{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *}
|
||||
|
||||
그리고 평소처럼 필요한 어떤 객체든 반환할 수 있습니다(`dict`, 데이터베이스 모델 등).
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
그런 다음 해당 *임시* 응답 객체에서 쿠키를 설정할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
|
||||
{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *}
|
||||
|
||||
그런 다음 일반적으로 하듯이 필요한 어떤 객체든 반환할 수 있습니다(`dict`, 데이터베이스 모델 등).
|
||||
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
그런 다음 쿠키를 설정하고 반환하면 됩니다:
|
||||
|
||||
{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ Pydantic 모델로 데이터 변환을 수행하지 않으며, 내용을 다른
|
|||
|
||||
XML 내용을 문자열에 넣고, 이를 `Response`에 넣어 반환할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
||||
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
|
||||
|
||||
## 참고 사항 { #notes }
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
그런 다음, 여러분은 해당 *임시* 응답 객체에서 헤더를 설정할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
|
||||
{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *}
|
||||
|
||||
그 후, 일반적으로 사용하듯이 필요한 객체(`dict`, 데이터베이스 모델 등)를 반환할 수 있습니다.
|
||||
|
||||
|
|
@ -20,15 +20,15 @@
|
|||
|
||||
`Response`를 직접 반환할 때에도 헤더를 추가할 수 있습니다.
|
||||
|
||||
[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요.
|
||||
[응답을 직접 반환하기](response-directly.md){.internal-link target=_blank}에서 설명한 대로 응답을 생성하고, 헤더를 추가 매개변수로 전달하세요:
|
||||
|
||||
{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
`from starlette.responses import Response`나 `from starlette.responses import JSONResponse`를 사용할 수도 있습니다.
|
||||
|
||||
**FastAPI**는 해당 *임시* 응답에서 헤더(쿠키와 상태 코드도 포함)를 추출하여, 여러분이 반환한 값을 포함하는 최종 응답에 `response_model`로 필터링된 값을 넣습니다.
|
||||
**FastAPI**는 개발자인 여러분의 편의를 위해 `starlette.responses`와 동일한 것을 `fastapi.responses`로도 제공합니다. 하지만 사용 가능한 대부분의 응답은 Starlette에서 직접 제공합니다.
|
||||
|
||||
그리고 `Response`는 헤더와 쿠키를 설정하는 데 자주 사용될 수 있으므로, **FastAPI**는 `fastapi.Response`로도 이를 제공합니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ HTTP Basic Auth에서는 애플리케이션이 사용자명과 비밀번호가
|
|||
* `HTTPBasicCredentials` 타입의 객체를 반환합니다:
|
||||
* 전송된 `username`과 `password`를 포함합니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
|
||||
{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *}
|
||||
|
||||
처음으로 URL을 열어보면(또는 문서에서 "Execute" 버튼을 클릭하면) 브라우저가 사용자명과 비밀번호를 물어봅니다:
|
||||
|
||||
|
|
@ -40,13 +40,13 @@ dependency를 사용해 사용자명과 비밀번호가 올바른지 확인하
|
|||
|
||||
그런 다음 `secrets.compare_digest()`를 사용해 `credentials.username`이 `"stanleyjobson"`이고 `credentials.password`가 `"swordfish"`인지 확실히 확인할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
|
||||
{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *}
|
||||
|
||||
이는 다음과 비슷합니다:
|
||||
|
||||
```Python
|
||||
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
|
||||
# Return some error
|
||||
# 어떤 오류를 반환
|
||||
...
|
||||
```
|
||||
|
||||
|
|
@ -104,4 +104,4 @@ Python은 두 문자열이 같지 않다는 것을 알아차리기 전까지 `st
|
|||
|
||||
자격 증명이 올바르지 않다고 판단되면, 상태 코드 401(자격 증명이 제공되지 않았을 때와 동일)을 사용하는 `HTTPException`을 반환하고 브라우저가 로그인 프롬프트를 다시 표시하도록 `WWW-Authenticate` 헤더를 추가하세요:
|
||||
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
|
||||
{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ Pydantic 모델과 같은 방식으로, 타입 어노테이션(그리고 필요
|
|||
|
||||
다양한 데이터 타입, `Field()`로 추가 검증 등 Pydantic 모델에서 사용하는 동일한 검증 기능과 도구를 모두 사용할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
|
||||
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ Pydantic 모델과 같은 방식으로, 타입 어노테이션(그리고 필요
|
|||
|
||||
이제 애플리케이션에서 새 `settings` 객체를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
|
||||
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}
|
||||
|
||||
### 서버 실행하기 { #run-the-server }
|
||||
|
||||
|
|
@ -104,11 +104,11 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
|
|||
|
||||
예를 들어 `config.py` 파일을 다음처럼 만들 수 있습니다:
|
||||
|
||||
{* ../../docs_src/settings/app01_py39/config.py *}
|
||||
{* ../../docs_src/settings/app01_py310/config.py *}
|
||||
|
||||
그리고 `main.py` 파일에서 이를 사용합니다:
|
||||
|
||||
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
|
||||
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
|
|||
|
||||
이전 예시에서 이어서, `config.py` 파일은 다음과 같을 수 있습니다:
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}
|
||||
|
||||
이제는 기본 인스턴스 `settings = Settings()`를 생성하지 않는다는 점에 유의하세요.
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
|
|||
|
||||
이제 새로운 `config.Settings()`를 반환하는 의존성을 생성합니다.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -146,13 +146,13 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
|
|||
|
||||
그 다음 *경로 처리 함수*에서 이를 의존성으로 요구하고, 필요한 어디서든 사용할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
|
||||
|
||||
### 설정과 테스트 { #settings-and-testing }
|
||||
|
||||
그 다음, `get_settings`에 대한 의존성 override를 만들어 테스트 중에 다른 설정 객체를 제공하기가 매우 쉬워집니다:
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
|
||||
|
||||
의존성 override에서는 새 `Settings` 객체를 생성할 때 `admin_email`의 새 값을 설정하고, 그 새 객체를 반환합니다.
|
||||
|
||||
|
|
@ -193,11 +193,11 @@ APP_NAME="ChimichangApp"
|
|||
|
||||
그리고 `config.py`를 다음처럼 업데이트합니다:
|
||||
|
||||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
|
||||
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
`model_config` 속성은 Pydantic 설정을 위한 것입니다. 자세한 내용은 <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>을 참고하세요.
|
||||
`model_config` 속성은 Pydantic 설정을 위한 것입니다. 자세한 내용은 <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>를 참고하세요.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -226,11 +226,11 @@ def get_settings():
|
|||
|
||||
하지만 위에 `@lru_cache` 데코레이터를 사용하고 있으므로, `Settings` 객체는 최초 호출 시 딱 한 번만 생성됩니다. ✔️
|
||||
|
||||
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
|
||||
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
|
||||
|
||||
그 다음 요청들에서 의존성으로 `get_settings()`가 다시 호출될 때마다, `get_settings()`의 내부 코드를 실행해서 새 `Settings` 객체를 만드는 대신, 첫 호출에서 반환된 동일한 객체를 계속 반환합니다.
|
||||
|
||||
#### `lru_cache` Technical Details { #lru-cache-technical-details }
|
||||
#### `lru_cache` 기술 세부사항 { #lru-cache-technical-details }
|
||||
|
||||
`@lru_cache`는 데코레이션한 함수가 매번 다시 계산하는 대신, 첫 번째에 반환된 동일한 값을 반환하도록 함수를 수정합니다(즉, 매번 함수 코드를 실행하지 않습니다).
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
먼저, 메인 최상위 **FastAPI** 애플리케이션과 그 *경로 처리*를 생성합니다:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
|
||||
|
||||
### 하위 응용프로그램 { #sub-application }
|
||||
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
이 하위 응용프로그램은 또 다른 표준 FastAPI 애플리케이션이지만, "마운트"될 애플리케이션입니다:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
|
||||
|
||||
### 하위 응용프로그램 마운트 { #mount-the-sub-application }
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
이 경우 `/subapi` 경로에 마운트됩니다:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *}
|
||||
|
||||
### 자동 API 문서 확인 { #check-the-automatic-api-docs }
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ $ pip install jinja2
|
|||
* 템플릿을 반환할 *경로 처리*에 `Request` 매개변수를 선언합니다.
|
||||
* 생성한 `templates`를 사용하여 `TemplateResponse`를 렌더링하고 반환합니다. 템플릿의 이름, 요청 객체 및 Jinja2 템플릿 내에서 사용될 키-값 쌍이 포함된 "컨텍스트" 딕셔너리도 전달합니다.
|
||||
|
||||
{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
|
||||
{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
테스트에서 `lifespan`을 실행해야 하는 경우, `with` 문과 함께 `TestClient`를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||
{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||
|
||||
|
||||
["공식 Starlette 문서 사이트에서 테스트에서 라이프스팬 실행하기."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)에 대한 자세한 내용을 더 읽을 수 있습니다.
|
||||
|
||||
더 이상 권장되지 않는 `startup` 및 `shutdown` 이벤트의 경우, 다음과 같이 `TestClient`를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
|
||||
{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
이를 위해 `with` 문에서 `TestClient`를 사용하여 WebSocket에 연결합니다:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
|
||||
{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
자세한 내용은 Starlette의 <a href="https://www.starlette.dev/testclient/#testing-websocket-sessions" class="external-link" target="_blank">testing WebSockets</a> 문서를 확인하세요.
|
||||
자세한 내용은 Starlette의 <a href="https://www.starlette.dev/testclient/#testing-websocket-sessions" class="external-link" target="_blank">WebSocket 테스트</a> 문서를 확인하세요.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
이를 위해서는 요청에 직접 접근해야 합니다.
|
||||
|
||||
{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
|
||||
{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *}
|
||||
|
||||
*경로 처리 함수* 매개변수를 `Request` 타입으로 선언하면 **FastAPI**가 해당 매개변수에 `Request`를 전달하는 것을 알게 됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ $ pip install websockets
|
|||
|
||||
그리고 백엔드와 WebSockets을 사용해 통신하려면 아마도 프런트엔드의 유틸리티를 사용할 것입니다.
|
||||
|
||||
또는 네이티브 코드로 WebSocket 백엔드와 직접 통신하는 네이티브 모바일 응용 프로그램을 가질 수도 있습니다.
|
||||
또는 네이티브 코드로 WebSocket 백엔드와 직접 통신하는 네이티브 모바일 애플리케이션을 가질 수도 있습니다.
|
||||
|
||||
혹은 WebSocket 엔드포인트와 통신할 수 있는 다른 방법이 있을 수도 있습니다.
|
||||
|
||||
|
|
@ -38,13 +38,13 @@ $ pip install websockets
|
|||
|
||||
그러나 이는 WebSockets의 서버 측에 집중하고 동작하는 예제를 제공하는 가장 간단한 방법입니다:
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *}
|
||||
|
||||
## `websocket` 생성하기 { #create-a-websocket }
|
||||
|
||||
**FastAPI** 응용 프로그램에서 `websocket`을 생성합니다:
|
||||
**FastAPI** 애플리케이션에서 `websocket`을 생성합니다:
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *}
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
|
|
@ -58,13 +58,13 @@ $ pip install websockets
|
|||
|
||||
WebSocket 경로에서 메시지를 대기(`await`)하고 전송할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *}
|
||||
|
||||
여러분은 이진 데이터, 텍스트, JSON 데이터를 받을 수 있고 전송할 수 있습니다.
|
||||
|
||||
## 시도해보기 { #try-it }
|
||||
|
||||
파일 이름이 `main.py`라고 가정하고 다음으로 응용 프로그램을 실행합니다:
|
||||
파일 이름이 `main.py`라고 가정하고 다음으로 애플리케이션을 실행합니다:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ $ fastapi dev main.py
|
|||
|
||||
<img src="/img/tutorial/websockets/image02.png">
|
||||
|
||||
그리고 WebSockets가 포함된 **FastAPI** 응용 프로그램이 응답을 돌려줄 것입니다:
|
||||
그리고 WebSockets가 포함된 **FastAPI** 애플리케이션이 응답을 돌려줄 것입니다:
|
||||
|
||||
<img src="/img/tutorial/websockets/image03.png">
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ WebSocket이기 때문에 `HTTPException`을 발생시키는 것은 적절하지
|
|||
|
||||
### 종속성을 가진 WebSockets 시도해보기 { #try-the-websockets-with-dependencies }
|
||||
|
||||
파일 이름이 `main.py`라고 가정하고 다음으로 응용 프로그램을 실행합니다:
|
||||
파일 이름이 `main.py`라고 가정하고 다음으로 애플리케이션을 실행합니다:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ $ fastapi dev main.py
|
|||
|
||||
WebSocket 연결이 닫히면, `await websocket.receive_text()`가 `WebSocketDisconnect` 예외를 발생시킵니다. 그러면 이 예제처럼 이를 잡아 처리할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
|
||||
{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *}
|
||||
|
||||
테스트해보기:
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
그리고 해당 경로에 마운트합니다.
|
||||
|
||||
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
|
||||
{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ Flask REST framework는 여러 개가 있지만, 시간을 들여 조사해 본
|
|||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
|
||||
|
||||
API 시스템에 필요한 주요 기능 중 하나는 데이터 "<abbr title="also called marshalling, conversion - 마샬링, 변환이라고도 합니다">serialization</abbr>"입니다. 이는 코드(Python)에서 데이터를 가져와 네트워크로 전송할 수 있는 형태로 변환하는 것을 의미합니다. 예를 들어 데이터베이스의 데이터를 담은 객체를 JSON 객체로 변환하거나, `datetime` 객체를 문자열로 변환하는 등의 작업입니다.
|
||||
API 시스템에 필요한 주요 기능 중 하나는 데이터 "<dfn title="마샬링, 변환이라고도 함">직렬화</dfn>"입니다. 이는 코드(Python)에서 데이터를 가져와 네트워크로 전송할 수 있는 형태로 변환하는 것을 의미합니다. 예를 들어 데이터베이스의 데이터를 담은 객체를 JSON 객체로 변환하거나, `datetime` 객체를 문자열로 변환하는 등의 작업입니다.
|
||||
|
||||
API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정 파라미터를 기준으로 데이터가 유효한지 확인하는 것입니다. 예를 들어 어떤 필드가 `int`인지, 임의의 문자열이 아닌지 확인하는 식입니다. 이는 특히 들어오는 데이터에 유용합니다.
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정
|
|||
|
||||
이런 기능들을 제공하기 위해 Marshmallow가 만들어졌습니다. 훌륭한 라이브러리이며, 저도 이전에 많이 사용했습니다.
|
||||
|
||||
하지만 Python type hints가 존재하기 전에 만들어졌습니다. 그래서 각 <abbr title="the definition of how data should be formed - 데이터가 어떻게 구성되어야 하는지에 대한 정의">schema</abbr>를 정의하려면 Marshmallow가 제공하는 특정 유틸리티와 클래스를 사용해야 합니다.
|
||||
하지만 Python type hints가 존재하기 전에 만들어졌습니다. 그래서 각 <dfn title="데이터가 어떻게 구성되어야 하는지에 대한 정의">스키마</dfn>를 정의하려면 Marshmallow가 제공하는 특정 유틸리티와 클래스를 사용해야 합니다.
|
||||
|
||||
/// check | **FastAPI**에 영감을 준 것
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정
|
|||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
|
||||
|
||||
API에 필요한 또 다른 큰 기능은 들어오는 요청에서 데이터를 <abbr title="reading and converting to Python data - 읽어서 Python 데이터로 변환하기">parsing</abbr>하는 것입니다.
|
||||
API에 필요한 또 다른 큰 기능은 들어오는 요청에서 데이터를 <dfn title="읽어서 Python 데이터로 변환하기">파싱</dfn>하는 것입니다.
|
||||
|
||||
Webargs는 Flask를 포함한 여러 framework 위에서 이를 제공하기 위해 만들어진 도구입니다.
|
||||
|
||||
|
|
@ -419,7 +419,7 @@ Marshmallow와 비교할 수 있습니다. 다만 benchmark에서 Marshmallow보
|
|||
|
||||
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
|
||||
|
||||
Starlette는 경량 <abbr title="The new standard for building asynchronous Python web applications - 비동기 Python 웹 애플리케이션을 구축하기 위한 새로운 표준">ASGI</abbr> framework/toolkit으로, 고성능 asyncio 서비스를 만들기에 이상적입니다.
|
||||
Starlette는 경량 <dfn title="비동기 Python 웹 애플리케이션을 구축하기 위한 새로운 표준">ASGI</dfn> framework/toolkit으로, 고성능 asyncio 서비스를 만들기에 이상적입니다.
|
||||
|
||||
매우 단순하고 직관적입니다. 쉽게 확장할 수 있도록 설계되었고, 모듈식 component를 갖습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ FastAPI 애플리케이션을 배포할 때 일반적인 접근 방법은 **리
|
|||
<summary>Dockerfile Preview 👀</summary>
|
||||
|
||||
```Dockerfile
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None):
|
|||
|
||||
```{ .dockerfile .annotate }
|
||||
# (1)!
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
# (2)!
|
||||
WORKDIR /code
|
||||
|
|
@ -390,7 +390,7 @@ FastAPI가 단일 파일(예: `./app` 디렉터리 없이 `main.py`만 있는
|
|||
그런 다음 `Dockerfile`에서 해당 파일을 복사하도록 경로만 맞게 변경하면 됩니다:
|
||||
|
||||
```{ .dockerfile .annotate hl_lines="10 13" }
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
|
|
@ -454,7 +454,7 @@ Traefik은 Docker, Kubernetes 등과 통합되어 있어, 이를 사용해 컨
|
|||
|
||||
## 복제 - 프로세스 개수 { #replication-number-of-processes }
|
||||
|
||||
**Kubernetes**, Docker Swarm Mode, Nomad 등의 복잡한 시스템으로 여러 머신에 분산된 컨테이너를 관리하는 <abbr title="어떤 방식으로 연결되어 함께 동작하도록 구성된 머신의 그룹">클러스터</abbr>를 사용한다면, 각 컨테이너에서(**워커를 사용하는 Uvicorn** 같은) **프로세스 매니저**를 쓰는 대신, **클러스터 레벨**에서 **복제를 처리**하고 싶을 가능성이 큽니다.
|
||||
**Kubernetes**, Docker Swarm Mode, Nomad 등의 복잡한 시스템으로 여러 머신에 분산된 컨테이너를 관리하는 <dfn title="어떤 방식으로 연결되어 함께 동작하도록 구성된 머신의 그룹">클러스터</dfn>를 사용한다면, 각 컨테이너에서(**워커를 사용하는 Uvicorn** 같은) **프로세스 매니저**를 쓰는 대신, **클러스터 레벨**에서 **복제를 처리**하고 싶을 가능성이 큽니다.
|
||||
|
||||
Kubernetes 같은 분산 컨테이너 관리 시스템은 보통 들어오는 요청에 대한 **로드 밸런싱**을 지원하면서도, **컨테이너 복제**를 처리하는 통합된 방법을 가지고 있습니다. 모두 **클러스터 레벨**에서요.
|
||||
|
||||
|
|
@ -499,7 +499,7 @@ HTTPS에 사용되는 동일한 **TLS 종료 프록시** 컴포넌트가 **로
|
|||
그런 경우에는 `--workers` 커맨드 라인 옵션을 사용해 실행할 워커 수를 설정할 수 있습니다:
|
||||
|
||||
```{ .dockerfile .annotate }
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ HTTPS는 그냥 “켜져 있거나” 아니면 “꺼져 있는” 것이라
|
|||
이제 **개발자 관점**에서 HTTPS를 생각할 때 염두에 두어야 할 여러 가지가 있습니다:
|
||||
|
||||
* HTTPS를 사용하려면, **서버**가 **제3자**가 발급한 **"인증서(certificates)"**를 **보유**해야 합니다.
|
||||
* 이 인증서는 실제로 제3자가 “생성”해 주는 것이고, 서버가 만드는 것이 아니라 제3자로부터 **발급/획득**하는 것입니다.
|
||||
* 이 인증서는 실제로 '생성'되는 것이 아니라 제3자로부터 **발급/획득**하는 것입니다.
|
||||
* 인증서에는 **유효 기간**이 있습니다.
|
||||
* 즉, **만료**됩니다.
|
||||
* 그리고 나면 제3자로부터 다시 **갱신**해서 **재발급/재획득**해야 합니다.
|
||||
|
|
@ -65,7 +65,7 @@ Let's Encrypt 이전에는 이러한 **HTTPS 인증서**가 신뢰할 수 있는
|
|||
|
||||
아마도 시작은 **도메인 이름**을 **획득**하는 것일 겁니다. 그 다음 DNS 서버(아마 같은 클라우드 제공업체)에서 이를 설정합니다.
|
||||
|
||||
대개 클라우드 서버(가상 머신) 같은 것을 사용하게 되고, 거기에는 <abbr title="That doesn't change - 변하지 않음">fixed</abbr> **공개 IP 주소**가 있습니다.
|
||||
대개 클라우드 서버(가상 머신) 같은 것을 사용하게 되고, 거기에는 <dfn title="시간이 지나도 변하지 않음. 동적이지 않음">고정</dfn> **공개 IP 주소**가 있습니다.
|
||||
|
||||
DNS 서버(들)에서 **도메인**이 서버의 **공개 IP 주소**를 가리키도록 레코드(“`A record`”)를 설정합니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ $ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid
|
|||
|
||||
이제 조금 더 자세히 살펴보겠습니다.
|
||||
|
||||
FastAPI는 <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>라고 불리는, Python 웹 프레임워크와 서버를 만들기 위한 표준을 사용합니다. FastAPI는 ASGI 웹 프레임워크입니다.
|
||||
FastAPI는 <abbr title="Asynchronous Server Gateway Interface - 비동기 서버 게이트웨이 인터페이스">ASGI</abbr>라고 불리는, Python 웹 프레임워크와 서버를 만들기 위한 표준을 사용합니다. FastAPI는 ASGI 웹 프레임워크입니다.
|
||||
|
||||
원격 서버 머신에서 **FastAPI** 애플리케이션(또는 다른 ASGI 애플리케이션)을 실행하기 위해 필요한 핵심 요소는 **Uvicorn** 같은 ASGI 서버 프로그램입니다. `fastapi` 명령에는 기본으로 이것이 포함되어 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
* 메모리
|
||||
* 시작하기 전의 이전 단계
|
||||
|
||||
지금까지 문서의 모든 튜토리얼을 참고하면서, `fastapi` 명령처럼 Uvicorn을 실행하는 **서버 프로그램**을 사용해 **단일 프로세스**로 실행해 왔을 가능성이 큽니다.
|
||||
지금까지 문서의 모든 튜토리얼을 참고하면서, `fastapi` 명령어처럼 Uvicorn을 실행하는 **서버 프로그램**을 사용해 **단일 프로세스**로 실행해 왔을 가능성이 큽니다.
|
||||
|
||||
애플리케이션을 배포할 때는 **다중 코어**를 활용하고 더 많은 요청을 처리할 수 있도록 **프로세스 복제**를 하고 싶을 가능성이 큽니다.
|
||||
|
||||
이전 장의 [배포 개념들](concepts.md){.internal-link target=_blank}에서 본 것처럼, 사용할 수 있는 전략이 여러 가지 있습니다.
|
||||
|
||||
여기서는 `fastapi` 명령을 사용하거나 `uvicorn` 명령을 직접 사용해서, **워커 프로세스**와 함께 **Uvicorn**을 사용하는 방법을 보여드리겠습니다.
|
||||
여기서는 `fastapi` 명령어를 사용하거나 `uvicorn` 명령어를 직접 사용해서, **워커 프로세스**와 함께 **Uvicorn**을 사용하는 방법을 보여드리겠습니다.
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -27,11 +27,11 @@ Docker나 Kubernetes 같은 컨테이너를 사용하고 있다면, 다음 장
|
|||
|
||||
## 여러 워커 { #multiple-workers }
|
||||
|
||||
`--workers` 커맨드라인 옵션으로 여러 워커를 시작할 수 있습니다:
|
||||
`--workers` 명령어 옵션으로 여러 워커를 시작할 수 있습니다:
|
||||
|
||||
//// tab | `fastapi`
|
||||
|
||||
`fastapi` 명령을 사용한다면:
|
||||
`fastapi` 명령어를 사용한다면:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ $ <font color="#4E9A06">fastapi</font> run --workers 4 <u style="text-decoration
|
|||
|
||||
//// tab | `uvicorn`
|
||||
|
||||
`uvicorn` 명령을 직접 사용하는 편이 좋다면:
|
||||
`uvicorn` 명령어를 직접 사용하는 편이 좋다면:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
|
|||
|
||||
## 요약 { #recap }
|
||||
|
||||
`fastapi` 또는 `uvicorn` 명령에서 `--workers` CLI 옵션을 사용해 여러 워커 프로세스를 실행하면, **멀티 코어 CPU**를 활용해 **여러 프로세스를 병렬로 실행**할 수 있습니다.
|
||||
`fastapi` 또는 `uvicorn` 명령어에서 `--workers` CLI 옵션을 사용해 여러 워커 프로세스를 실행하면, **멀티 코어 CPU**를 활용해 **여러 프로세스를 병렬로 실행**할 수 있습니다.
|
||||
|
||||
다른 배포 개념들을 직접 처리하면서 **자체 배포 시스템**을 구축하는 경우, 이러한 도구와 아이디어를 활용할 수 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fastapi[standard]>=0.112.0,<0.113.0
|
|||
|
||||
## 이용 가능한 버전들 { #available-versions }
|
||||
|
||||
사용 가능한 버전(예: 현재 최신 버전이 무엇인지 확인하기 위해)은 [Release Notes](../release-notes.md){.internal-link target=_blank}에서 확인할 수 있습니다.
|
||||
사용 가능한 버전(예: 현재 최신 버전이 무엇인지 확인하기 위해)은 [릴리스 노트](../release-notes.md){.internal-link target=_blank}에서 확인할 수 있습니다.
|
||||
|
||||
## 버전들에 대해 { #about-versions }
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ fastapi>=0.45.0,<0.46.0
|
|||
|
||||
앱에 테스트를 추가해야 합니다.
|
||||
|
||||
**FastAPI**에서는 매우 쉽습니다(Starlette 덕분에). 문서를 확인해 보세요: [Testing](../tutorial/testing.md){.internal-link target=_blank}
|
||||
**FastAPI**에서는 매우 쉽습니다(Starlette 덕분에). 문서를 확인해 보세요: [테스트](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
테스트를 갖춘 뒤에는 **FastAPI** 버전을 더 최신 버전으로 업그레이드하고, 테스트를 실행하여 모든 코드가 올바르게 동작하는지 확인하세요.
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// You could create an env var MY_NAME with
|
||||
// 환경 변수 MY_NAME을 다음과 같이 생성할 수 있습니다
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// Then you could use it with other programs, like
|
||||
// 그런 다음 다른 프로그램과 함께 사용할 수 있습니다. 예:
|
||||
$ echo "Hello $MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
|
|
@ -37,10 +37,10 @@ Hello Wade Wilson
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Create an env var MY_NAME
|
||||
// 환경 변수 MY_NAME 생성
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
// Use it with other programs, like
|
||||
// 다른 프로그램과 함께 사용하기. 예:
|
||||
$ echo "Hello $Env:MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
|
|
@ -78,20 +78,20 @@ print(f"Hello {name} from Python")
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Here we don't set the env var yet
|
||||
// 여기서는 아직 환경 변수를 설정하지 않습니다
|
||||
$ python main.py
|
||||
|
||||
// As we didn't set the env var, we get the default value
|
||||
// 환경 변수를 설정하지 않았으므로 기본값이 사용됩니다
|
||||
|
||||
Hello World from Python
|
||||
|
||||
// But if we create an environment variable first
|
||||
// 하지만 먼저 환경 변수를 생성하면
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// And then call the program again
|
||||
// 그리고 프로그램을 다시 실행하면
|
||||
$ python main.py
|
||||
|
||||
// Now it can read the environment variable
|
||||
// 이제 환경 변수를 읽을 수 있습니다
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
```
|
||||
|
|
@ -105,20 +105,20 @@ Hello Wade Wilson from Python
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Here we don't set the env var yet
|
||||
// 여기서는 아직 환경 변수를 설정하지 않습니다
|
||||
$ python main.py
|
||||
|
||||
// As we didn't set the env var, we get the default value
|
||||
// 환경 변수를 설정하지 않았으므로 기본값이 사용됩니다
|
||||
|
||||
Hello World from Python
|
||||
|
||||
// But if we create an environment variable first
|
||||
// 하지만 먼저 환경 변수를 생성하면
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
// And then call the program again
|
||||
// 그리고 프로그램을 다시 실행하면
|
||||
$ python main.py
|
||||
|
||||
// Now it can read the environment variable
|
||||
// 이제 환경 변수를 읽을 수 있습니다
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
```
|
||||
|
|
@ -136,14 +136,14 @@ Hello Wade Wilson from Python
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Create an env var MY_NAME in line for this program call
|
||||
// 이 프로그램 호출을 위해 같은 줄에서 환경 변수 MY_NAME 생성
|
||||
$ MY_NAME="Wade Wilson" python main.py
|
||||
|
||||
// Now it can read the environment variable
|
||||
// 이제 환경 변수를 읽을 수 있습니다
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
|
||||
// The env var no longer exists afterwards
|
||||
// 이후에는 해당 환경 변수가 존재하지 않습니다
|
||||
$ python main.py
|
||||
|
||||
Hello World from Python
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
### 개방형 표준을 기반으로 { #based-on-open-standards }
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a>: <abbr title="또한 다음으로도 불립니다: 엔드포인트, 라우트">path</abbr> <abbr title="HTTP 메소드(POST, GET, PUT, DELETE 등)로도 알려져 있습니다">operations</abbr>, 매개변수, 요청 본문, 보안 등의 선언을 포함하여 API를 생성합니다.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a>: <dfn title="또한 다음으로도 불림: 엔드포인트, 라우트">경로</dfn> <dfn title="HTTP 메소드(POST, GET, PUT, DELETE 등)로도 알려짐">처리</dfn>, 매개변수, 요청 본문, 보안 등의 선언을 포함하여 API를 생성합니다.
|
||||
* <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a>를 사용한 자동 데이터 모델 문서화(OpenAPI 자체가 JSON Schema를 기반으로 하기 때문입니다).
|
||||
* 단순히 떠올려서 덧붙인 레이어가 아니라, 세심한 검토를 거친 뒤 이러한 표준을 중심으로 설계되었습니다.
|
||||
* 이는 또한 다양한 언어로 자동 **클라이언트 코드 생성**을 사용할 수 있게 해줍니다.
|
||||
|
|
@ -136,7 +136,7 @@ Python 개발자 설문조사에서 <a href="https://www.jetbrains.com/research/
|
|||
|
||||
### 의존성 주입 { #dependency-injection }
|
||||
|
||||
FastAPI는 사용하기 매우 쉽지만, 매우 강력한 <abbr title='또한 다음으로도 불립니다: "컴포넌트", "자원", "서비스", "제공자"'><strong>Dependency Injection</strong></abbr> 시스템을 포함하고 있습니다.
|
||||
FastAPI는 사용하기 매우 쉽지만, 매우 강력한 <dfn title='또한 다음으로도 불림: "컴포넌트", "자원", "서비스", "제공자"'><strong>의존성 주입</strong></dfn> 시스템을 포함하고 있습니다.
|
||||
|
||||
* 의존성도 의존성을 가질 수 있어, 의존성의 계층 또는 **의존성의 "그래프"**를 생성합니다.
|
||||
* 모든 것이 프레임워크에 의해 **자동으로 처리됩니다**.
|
||||
|
|
@ -153,8 +153,8 @@ FastAPI는 사용하기 매우 쉽지만, 매우 강력한 <abbr title='또한
|
|||
|
||||
### 테스트됨 { #tested }
|
||||
|
||||
* 100% <abbr title="자동으로 테스트되는 코드의 양">test coverage</abbr>.
|
||||
* 100% <abbr title="Python 타입 어노테이션으로, 이를 통해 편집기와 외부 도구가 더 나은 지원을 제공할 수 있습니다">type annotated</abbr> 코드 베이스.
|
||||
* 100% <dfn title="자동으로 테스트되는 코드의 양">테스트 커버리지</dfn>.
|
||||
* 100% <dfn title="Python 타입 어노테이션으로, 이를 통해 편집기와 외부 도구가 더 나은 지원을 제공할 수 있습니다">타입 어노테이션</dfn> 코드 베이스.
|
||||
* 프로덕션 애플리케이션에서 사용됩니다.
|
||||
|
||||
## Starlette 기능 { #starlette-features }
|
||||
|
|
@ -190,7 +190,7 @@ FastAPI는 사용하기 매우 쉽지만, 매우 강력한 <abbr title='또한
|
|||
* **No brainfuck**:
|
||||
* 새로운 스키마 정의 마이크로 언어를 배울 필요가 없습니다.
|
||||
* Python 타입을 알고 있다면 Pydantic 사용법도 알고 있는 것입니다.
|
||||
* 여러분의 **<abbr title="Integrated Development Environment - 통합 개발 환경: 코드 편집기와 비슷합니다">IDE</abbr>/<abbr title="코드 오류를 확인하는 프로그램">linter</abbr>/뇌**와 잘 어울립니다:
|
||||
* 여러분의 **<abbr title="Integrated Development Environment - 통합 개발 환경: 코드 편집기와 비슷합니다">IDE</abbr>/<dfn title="코드 오류를 확인하는 프로그램">린터</dfn>/뇌**와 잘 어울립니다:
|
||||
* pydantic 데이터 구조는 여러분이 정의한 클래스 인스턴스일 뿐이므로, 자동 완성, 린팅, mypy, 그리고 직관까지도 검증된 데이터와 함께 제대로 작동합니다.
|
||||
* **복잡한 구조**를 검증합니다:
|
||||
* 계층적인 Pydantic 모델, Python `typing`의 `List`와 `Dict` 등을 사용합니다.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ FastAPI 버전 `0.122.0`부터는 더 적절한 HTTP 상태 코드 `401 Unauthor
|
|||
|
||||
예를 들어, 기본값인 `401 Unauthorized` 오류 대신 `403 Forbidden` 오류를 반환하는 `HTTPBearer`의 서브클래스를 만들 수 있습니다:
|
||||
|
||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
|
||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
함수는 예외를 `raise`하는 것이 아니라 예외 인스턴스를 `return`한다는 점에 유의하세요. 예외를 발생시키는(`raise`) 작업은 내부 코드의 나머지 부분에서 수행됩니다.
|
||||
함수는 예외를 `return`하는 것이지 `raise`하지 않는다는 점에 유의하세요. 예외를 발생시키는(`raise`) 작업은 내부 코드의 나머지 부분에서 수행됩니다.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
## 보안, API 및 docs에 대해서 { #about-security-apis-and-docs }
|
||||
|
||||
프로덕션에서, 문서화된 사용자 인터페이스(UI)를 숨기는 것이 API를 보호하는 방법이 *되어서는 안 됩니다*.
|
||||
프로덕션에서, 문서화된 사용자 인터페이스(UI)를 숨기는 것이 API를 보호하는 방법이 되어서는 안 됩니다.
|
||||
|
||||
이는 API에 추가적인 보안을 제공하지 않으며, *경로 처리*는 여전히 동일한 위치에서 사용 할 수 있습니다.
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ API를 보호하고 싶다면, 예를 들어 다음과 같은 더 나은 방법
|
|||
|
||||
예를 들어:
|
||||
|
||||
{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *}
|
||||
|
||||
여기서 `openapi_url` 설정을 기본값인 `"/openapi.json"`으로 선언합니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ FastAPI는 이 구성을 **JSON** 형식으로 변환하여 JavaScript와 호환
|
|||
|
||||
그러나 `syntaxHighlight`를 `False`로 설정하여 구문 강조 기능을 비활성화할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}
|
||||
|
||||
...그럼 Swagger UI에서 더 이상 구문 강조 기능이 표시되지 않습니다:
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ FastAPI는 이 구성을 **JSON** 형식으로 변환하여 JavaScript와 호환
|
|||
|
||||
동일한 방식으로 `"syntaxHighlight.theme"` 키를 사용하여 구문 강조 테마를 설정할 수 있습니다 (중간에 점이 포함된 것을 참고하십시오).
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
|
||||
|
||||
이 설정은 구문 강조 색상 테마를 변경합니다:
|
||||
|
||||
|
|
@ -42,11 +42,11 @@ FastAPI는 대부분의 사용 사례에 적합한 몇 가지 기본 구성 매
|
|||
|
||||
{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *}
|
||||
|
||||
`swagger_ui_parameters` 인수에 다른 값을 설정하여 이러한 기본값 중 일부를 재정의할 수 있습니다.
|
||||
`swagger_ui_parameters` 인수에 다른 값을 설정하여 이러한 기본값 중 어느 것이든 재정의할 수 있습니다.
|
||||
|
||||
예를 들어, `deepLinking`을 비활성화하려면 `swagger_ui_parameters`에 다음 설정을 전달할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}
|
||||
|
||||
## 기타 Swagger UI 매개변수 { #other-swagger-ui-parameters }
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ API 문서는 **Swagger UI**와 **ReDoc**을 사용하며, 각각 JavaScript와
|
|||
|
||||
## JavaScript와 CSS용 커스텀 CDN { #custom-cdn-for-javascript-and-css }
|
||||
|
||||
예를 들어 다른 <abbr title="Content Delivery Network">CDN</abbr>을 사용하고 싶다고 해봅시다. 예를 들면 `https://unpkg.com/`을 사용하려는 경우입니다.
|
||||
예를 들어 다른 <abbr title="Content Delivery Network - 콘텐츠 전송 네트워크">CDN</abbr>을 사용하고 싶다고 해봅시다. 예를 들면 `https://unpkg.com/`을 사용하려는 경우입니다.
|
||||
|
||||
이는 예를 들어 특정 국가에서 일부 URL을 제한하는 경우에 유용할 수 있습니다.
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ API 문서는 **Swagger UI**와 **ReDoc**을 사용하며, 각각 JavaScript와
|
|||
|
||||
비활성화하려면 `FastAPI` 앱을 생성할 때 해당 URL을 `None`으로 설정하세요:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *}
|
||||
|
||||
### 커스텀 문서 포함하기 { #include-the-custom-docs }
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ FastAPI 내부 함수를 재사용해 문서용 HTML 페이지를 생성하고,
|
|||
|
||||
ReDoc도 마찬가지입니다...
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를
|
|||
|
||||
이제 모든 것이 제대로 동작하는지 테스트할 수 있도록 *경로 처리*를 하나 만드세요:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *}
|
||||
|
||||
### 테스트하기 { #test-it }
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인
|
|||
* `StaticFiles`를 import합니다.
|
||||
* 특정 경로에 `StaticFiles()` 인스턴스를 "마운트(mount)"합니다.
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *}
|
||||
|
||||
### 정적 파일 테스트하기 { #test-the-static-files }
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인
|
|||
|
||||
비활성화하려면 `FastAPI` 앱을 생성할 때 해당 URL을 `None`으로 설정하세요:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *}
|
||||
|
||||
### 정적 파일을 위한 커스텀 문서 포함하기 { #include-the-custom-docs-for-static-files }
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ JavaScript와 CSS를 자체 호스팅하는 것은 예를 들어, 오프라인
|
|||
|
||||
ReDoc도 마찬가지입니다...
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ Swagger UI가 이 과정을 백그라운드에서 처리해 주지만, 이를
|
|||
|
||||
이제 모든 것이 제대로 동작하는지 테스트할 수 있도록 *경로 처리*를 하나 만드세요:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *}
|
||||
|
||||
### 정적 파일 UI 테스트하기 { #test-static-files-ui }
|
||||
|
||||
|
|
|
|||
|
|
@ -43,19 +43,19 @@
|
|||
|
||||
먼저, 평소처럼 **FastAPI** 애플리케이션을 모두 작성합니다:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *}
|
||||
|
||||
### OpenAPI 스키마 생성하기 { #generate-the-openapi-schema }
|
||||
|
||||
그다음 `custom_openapi()` 함수 안에서, 동일한 유틸리티 함수를 사용해 OpenAPI 스키마를 생성합니다:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *}
|
||||
|
||||
### OpenAPI 스키마 수정하기 { #modify-the-openapi-schema }
|
||||
|
||||
이제 OpenAPI 스키마의 `info` "object"에 커스텀 `x-logo`를 추가하여 ReDoc 확장을 더할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *}
|
||||
|
||||
### OpenAPI 스키마 캐시하기 { #cache-the-openapi-schema }
|
||||
|
||||
|
|
@ -65,13 +65,13 @@
|
|||
|
||||
스키마는 한 번만 생성되고, 이후 요청에서는 같은 캐시된 스키마가 사용됩니다.
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *}
|
||||
|
||||
### 메서드 오버라이드하기 { #override-the-method }
|
||||
|
||||
이제 `.openapi()` 메서드를 새 함수로 교체할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *}
|
||||
|
||||
### 확인하기 { #check-it }
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
다음은 Strawberry를 FastAPI와 통합하는 방법에 대한 간단한 미리보기입니다:
|
||||
|
||||
{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *}
|
||||
{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}
|
||||
|
||||
<a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry 문서</a>에서 Strawberry에 대해 더 알아볼 수 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Pydantic v1을 사용하는 오래된 FastAPI 앱이 있다면, 여기서는 이
|
|||
|
||||
## 공식 가이드 { #official-guide }
|
||||
|
||||
Pydantic에는 v1에서 v2로의 공식 <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">Migration Guide</a>가 있습니다.
|
||||
Pydantic에는 v1에서 v2로의 공식 <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">마이그레이션 가이드</a>가 있습니다.
|
||||
|
||||
여기에는 무엇이 바뀌었는지, 검증이 이제 어떻게 더 정확하고 엄격해졌는지, 가능한 주의사항 등도 포함되어 있습니다.
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ Pydantic에는 v1에서 v2로의 공식 <a href="https://docs.pydantic.dev/lates
|
|||
|
||||
## 테스트 { #tests }
|
||||
|
||||
앱에 대한 [tests](../tutorial/testing.md){.internal-link target=_blank}가 있는지 확인하고, 지속적 통합(CI)에서 테스트를 실행하세요.
|
||||
앱에 대한 [테스트](../tutorial/testing.md){.internal-link target=_blank}가 있는지 확인하고, 지속적 통합(CI)에서 테스트를 실행하세요.
|
||||
|
||||
이렇게 하면 업그레이드를 진행하면서도 모든 것이 기대한 대로 계속 동작하는지 확인할 수 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
하지만 `Item-Output`에서는 `description`이 **필수이며**, 빨간 별표가 있습니다.
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image04.png">
|
||||
<img src="/img/tutorial/separate-openapi_schemas/image04.png">
|
||||
</div>
|
||||
|
||||
**Pydantic v2**의 이 기능 덕분에 API 문서는 더 **정밀**해지고, 자동 생성된 클라이언트와 SDK가 있다면 그것들도 더 정밀해져서 더 나은 **developer experience**와 일관성을 제공할 수 있습니다. 🎉
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
|
|||
* **빠름**: (Starlette과 Pydantic 덕분에) **NodeJS** 및 **Go**와 대등할 정도로 매우 높은 성능. [사용 가능한 가장 빠른 파이썬 프레임워크 중 하나](#performance).
|
||||
* **빠른 코드 작성**: 약 200%에서 300%까지 기능 개발 속도 증가. *
|
||||
* **적은 버그**: 사람(개발자)에 의한 에러 약 40% 감소. *
|
||||
* **직관적**: 훌륭한 편집기 지원. 모든 곳에서 <abbr title="다른 말로는: auto-complete, autocompletion, IntelliSense">자동완성</abbr>. 적은 디버깅 시간.
|
||||
* **직관적**: 훌륭한 편집기 지원. <dfn title="다른 말로는: 자동 완성, 자동완성, IntelliSense">자동완성</dfn>이 모든 곳에서 동작. 적은 디버깅 시간.
|
||||
* **쉬움**: 쉽게 사용하고 배우도록 설계. 적은 문서 읽기 시간.
|
||||
* **짧음**: 코드 중복 최소화. 각 매개변수 선언의 여러 기능. 적은 버그.
|
||||
* **견고함**: 준비된 프로덕션 용 코드를 얻으십시오. 자동 대화형 문서와 함께.
|
||||
|
|
@ -368,7 +368,7 @@ item: Item
|
|||
* 데이터 검증:
|
||||
* 데이터가 유효하지 않을 때 자동으로 생성하는 명확한 에러.
|
||||
* 깊이 중첩된 JSON 객체에 대한 유효성 검사.
|
||||
* 입력 데이터 <abbr title="다른 말로는: serialization, parsing, marshalling">변환</abbr>: 네트워크에서 파이썬 데이터 및 타입으로 전송. 읽을 수 있는 것들:
|
||||
* 입력 데이터 <dfn title="다른 말로는: 직렬화, 파싱, 마샬링">변환</dfn>: 네트워크에서 파이썬 데이터 및 타입으로 전송. 읽을 수 있는 것들:
|
||||
* JSON.
|
||||
* 경로 매개변수.
|
||||
* 쿼리 매개변수.
|
||||
|
|
@ -376,7 +376,7 @@ item: Item
|
|||
* 헤더.
|
||||
* 폼(Forms).
|
||||
* 파일.
|
||||
* 출력 데이터 <abbr title="다른 말로는: serialization, parsing, marshalling">변환</abbr>: 파이썬 데이터 및 타입을 네트워크 데이터로 전환(JSON 형식으로):
|
||||
* 출력 데이터 <dfn title="다른 말로는: 직렬화, 파싱, 마샬링">변환</dfn>: 파이썬 데이터 및 타입을 네트워크 데이터로 전환(JSON 형식으로):
|
||||
* 파이썬 타입 변환 (`str`, `int`, `float`, `bool`, `list`, 등).
|
||||
* `datetime` 객체.
|
||||
* `UUID` 객체.
|
||||
|
|
@ -439,7 +439,7 @@ item: Item
|
|||
|
||||
* 서로 다른 장소에서 **매개변수** 선언: **헤더**, **쿠키**, **폼 필드** 그리고 **파일**.
|
||||
* `maximum_length` 또는 `regex`처럼 **유효성 제약**하는 방법.
|
||||
* 강력하고 사용하기 쉬운 **<abbr title="다른 말로는: components, resources, providers, services, injectables">의존성 주입</abbr>** 시스템.
|
||||
* 강력하고 사용하기 쉬운 **<dfn title="다른 말로는: 컴포넌트, 리소스, 프로바이더, 서비스, 인젝터블">의존성 주입</dfn>** 시스템.
|
||||
* **OAuth2** 지원을 포함한 **JWT tokens** 및 **HTTP Basic**을 갖는 보안과 인증.
|
||||
* (Pydantic 덕분에) **깊은 중첩 JSON 모델**을 선언하는데 더 진보한 (하지만 마찬가지로 쉬운) 기술.
|
||||
* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> 및 기타 라이브러리와의 **GraphQL** 통합.
|
||||
|
|
@ -524,7 +524,7 @@ Starlette이 사용하는:
|
|||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - `TestClient`를 사용하려면 필요.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - 기본 템플릿 설정을 사용하려면 필요.
|
||||
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - `request.form()`과 함께 form <abbr title="HTTP 요청에서 파이썬 데이터로 가는 문자열 변환">"parsing"</abbr> 지원을 원하면 필요.
|
||||
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - `request.form()`과 함께 form <dfn title="HTTP 요청에서 온 문자열을 파이썬 데이터로 변환">"파싱"</dfn> 지원을 원하면 필요.
|
||||
|
||||
FastAPI가 사용하는:
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
템플릿은 일반적으로 특정 설정과 함께 제공되지만, 유연하고 커스터마이징이 가능하게 디자인 되었습니다. 이 특성들은 여러분이 프로젝트의 요구사항에 맞춰 수정, 적용을 할 수 있게 해주고, 템플릿이 완벽한 시작점이 되게 해줍니다. 🏁
|
||||
|
||||
많은 초기 설정, 보안, 데이터베이스 및 일부 API 엔드포인트가 이미 준비되어 있으므로, 여러분은 이 템플릿을 (프로젝트를) 시작하는 데 사용할 수 있습니다.
|
||||
많은 초기 설정, 보안, 데이터베이스 및 일부 API 엔드포인트가 이미 준비되어 있으므로, 여러분은 이 템플릿을 시작하는 데 사용할 수 있습니다.
|
||||
|
||||
GitHub 저장소: <a href="https://github.com/tiangolo/full-stack-fastapi-template" class="external-link" target="_blank">Full Stack FastAPI 템플릿</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
파이썬은 선택적으로 "타입 힌트(type hints)"(“type annotations”라고도 함)를 지원합니다.
|
||||
|
||||
이러한 **"타입 힌트"** 또는 애너테이션은 변수의 <abbr title="for example: str, int, float, bool">타입</abbr>을 선언할 수 있게 해주는 특수한 구문입니다.
|
||||
이러한 **"타입 힌트"** 또는 애너테이션은 변수의 <dfn title="예: str, int, float, bool">타입</dfn>을 선언할 수 있게 해주는 특수한 구문입니다.
|
||||
|
||||
변수의 타입을 선언하면 에디터와 도구가 더 나은 지원을 제공할 수 있습니다.
|
||||
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
간단한 예제로 시작해봅시다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
{* ../../docs_src/python_types/tutorial001_py310.py *}
|
||||
|
||||
이 프로그램을 호출하면 다음이 출력됩니다:
|
||||
|
||||
|
|
@ -34,9 +34,9 @@ John Doe
|
|||
|
||||
* `first_name`과 `last_name`를 받습니다.
|
||||
* `title()`로 각각의 첫 글자를 대문자로 변환합니다.
|
||||
* 가운데에 공백을 두고 <abbr title="Puts them together, as one. With the contents of one after the other.">연결</abbr>합니다.
|
||||
* 가운데에 공백을 두고 <dfn title="서로를 하나로 합칩니다. 하나의 내용 뒤에 다른 것의 내용을 이어 붙입니다.">연결</dfn>합니다.
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
|
||||
{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *}
|
||||
|
||||
### 수정하기 { #edit-it }
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ John Doe
|
|||
|
||||
이것들이 "타입 힌트"입니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
|
||||
|
||||
이것은 다음처럼 기본값을 선언하는 것과는 다릅니다:
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ John Doe
|
|||
|
||||
이 함수를 확인해보세요. 이미 타입 힌트가 있습니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
|
||||
|
||||
에디터가 변수의 타입을 알고 있기 때문에, 자동완성만 되는 게 아니라 오류 검사도 할 수 있습니다:
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ John Doe
|
|||
|
||||
이제 고쳐야 한다는 것을 알고, `age`를 `str(age)`로 문자열로 바꿉니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
|
||||
{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *}
|
||||
|
||||
## 타입 선언 { #declaring-types }
|
||||
|
||||
|
|
@ -135,29 +135,32 @@ John Doe
|
|||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *}
|
||||
|
||||
### 타입 매개변수가 있는 Generic(제네릭) 타입 { #generic-types-with-type-parameters }
|
||||
### `typing` 모듈 { #typing-module }
|
||||
|
||||
`dict`, `list`, `set`, `tuple`처럼 다른 값을 담을 수 있는 데이터 구조가 있습니다. 그리고 내부 값에도 각자의 타입이 있을 수 있습니다.
|
||||
몇 가지 추가적인 사용 사례에서는 표준 라이브러리의 `typing` 모듈에서 무언가를 import해야 할 수 있습니다. 예를 들어 어떤 값이 "아무 타입"일 수 있다고 선언하려면, `typing`의 `Any`를 사용할 수 있습니다:
|
||||
|
||||
이렇게 내부 타입을 가지는 타입을 "**generic**" 타입이라고 부릅니다. 그리고 내부 타입까지 포함해 선언할 수도 있습니다.
|
||||
```python
|
||||
from typing import Any
|
||||
|
||||
이런 타입과 내부 타입을 선언하려면 표준 파이썬 모듈 `typing`을 사용할 수 있습니다. 이 모듈은 이러한 타입 힌트를 지원하기 위해 존재합니다.
|
||||
|
||||
#### 더 최신 버전의 Python { #newer-versions-of-python }
|
||||
def some_function(data: Any):
|
||||
print(data)
|
||||
```
|
||||
|
||||
`typing`을 사용하는 문법은 Python 3.6부터 최신 버전까지, Python 3.9, Python 3.10 등을 포함한 모든 버전과 **호환**됩니다.
|
||||
### Generic(제네릭) 타입 { #generic-types }
|
||||
|
||||
파이썬이 발전함에 따라 **더 최신 버전**에서는 이러한 타입 애너테이션 지원이 개선되며, 많은 경우 타입 애너테이션을 선언하기 위해 `typing` 모듈을 import해서 사용할 필요조차 없게 됩니다.
|
||||
일부 타입은 대괄호 안에 "타입 매개변수"를 받아 내부 타입을 정의할 수 있습니다. 예를 들어 "문자열의 리스트"는 `list[str]`로 선언합니다.
|
||||
|
||||
프로젝트에서 더 최신 버전의 파이썬을 선택할 수 있다면, 그 추가적인 단순함을 활용할 수 있습니다.
|
||||
이렇게 타입 매개변수를 받을 수 있는 타입을 **Generic types** 또는 **Generics**라고 부릅니다.
|
||||
|
||||
이 문서 전체에는 각 파이썬 버전과 호환되는 예제가 있습니다(차이가 있을 때).
|
||||
대괄호와 내부 타입을 사용해 동일한 내장 타입들을 제네릭으로 사용할 수 있습니다:
|
||||
|
||||
예를 들어 "**Python 3.6+**"는 Python 3.6 이상(3.7, 3.8, 3.9, 3.10 등 포함)과 호환된다는 뜻입니다. 그리고 "**Python 3.9+**"는 Python 3.9 이상(3.10 등 포함)과 호환된다는 뜻입니다.
|
||||
|
||||
**최신 버전의 Python**을 사용할 수 있다면, 최신 버전용 예제를 사용하세요. 예를 들어 "**Python 3.10+**"처럼, 가장 **좋고 가장 단순한 문법**을 갖게 됩니다.
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
#### List { #list }
|
||||
|
||||
|
|
@ -169,7 +172,7 @@ John Doe
|
|||
|
||||
`list`는 내부 타입을 포함하는 타입이므로, 그 타입들을 대괄호 안에 넣습니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -195,7 +198,7 @@ John Doe
|
|||
|
||||
`tuple`과 `set`도 동일하게 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *}
|
||||
|
||||
이는 다음을 의미합니다:
|
||||
|
||||
|
|
@ -210,7 +213,7 @@ John Doe
|
|||
|
||||
두 번째 타입 매개변수는 `dict`의 값을 위한 것입니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *}
|
||||
|
||||
이는 다음을 의미합니다:
|
||||
|
||||
|
|
@ -222,44 +225,20 @@ John Doe
|
|||
|
||||
변수가 **여러 타입 중 어떤 것이든** 될 수 있다고 선언할 수 있습니다. 예를 들어 `int` 또는 `str`입니다.
|
||||
|
||||
Python 3.6 이상(3.10 포함)에서는 `typing`의 `Union` 타입을 사용하고, 대괄호 안에 허용할 수 있는 타입들을 넣을 수 있습니다.
|
||||
이를 정의하려면 두 타입을 <dfn title='“비트 단위 OR 연산자”라고도 하지만, 여기서는 그 의미와 관련이 없습니다'>세로 막대(`|`)</dfn>로 구분해 사용합니다.
|
||||
|
||||
Python 3.10에는 가능한 타입들을 <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>세로 막대(`|`)</abbr>로 구분해 넣을 수 있는 **새 문법**도 있습니다.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
이는 두 타입 집합의 합집합(union) 안의 어느 것이든 될 수 있다는 뜻이므로 "유니온"이라고 부릅니다.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
두 경우 모두 이는 `item`이 `int` 또는 `str`일 수 있다는 뜻입니다.
|
||||
이는 `item`이 `int` 또는 `str`일 수 있다는 뜻입니다.
|
||||
|
||||
#### `None`일 수도 있음 { #possibly-none }
|
||||
|
||||
값이 `str` 같은 타입일 수도 있지만, `None`일 수도 있다고 선언할 수 있습니다.
|
||||
|
||||
Python 3.6 이상(3.10 포함)에서는 `typing` 모듈에서 `Optional`을 import해서 사용하여 선언할 수 있습니다.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009_py39.py!}
|
||||
```
|
||||
|
||||
그냥 `str` 대신 `Optional[str]`을 사용하면, 값이 항상 `str`이라고 가정하고 있지만 실제로는 `None`일 수도 있는 상황에서 에디터가 오류를 감지하도록 도와줍니다.
|
||||
|
||||
`Optional[Something]`은 사실 `Union[Something, None]`의 축약이며, 서로 동등합니다.
|
||||
|
||||
또한 이는 Python 3.10에서 `Something | None`을 사용할 수 있다는 의미이기도 합니다:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
|
|
@ -268,96 +247,7 @@ Python 3.6 이상(3.10 포함)에서는 `typing` 모듈에서 `Optional`을 impo
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ alternative
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009b_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### `Union` 또는 `Optional` 사용하기 { #using-union-or-optional }
|
||||
|
||||
Python 3.10 미만 버전을 사용한다면, 아주 **주관적인** 관점에서의 팁입니다:
|
||||
|
||||
* 🚨 `Optional[SomeType]` 사용을 피하세요
|
||||
* 대신 ✨ **`Union[SomeType, None]`을 사용하세요** ✨.
|
||||
|
||||
둘은 동등하고 내부적으로는 같은 것이지만, `Optional`이라는 단어가 값이 선택 사항인 것처럼 보일 수 있기 때문에 `Optional` 대신 `Union`을 권장합니다. 실제 의미는 값이 선택 사항이라는 뜻이 아니라, "값이 `None`일 수 있다"는 뜻이기 때문입니다. 선택 사항이 아니고 여전히 필수인 경우에도요.
|
||||
|
||||
`Union[SomeType, None]`이 의미를 더 명확하게 드러낸다고 생각합니다.
|
||||
|
||||
이건 단지 단어와 이름의 문제입니다. 하지만 그런 단어들이 여러분과 팀원이 코드에 대해 생각하는 방식에 영향을 줄 수 있습니다.
|
||||
|
||||
예로, 이 함수를 봅시다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
|
||||
|
||||
매개변수 `name`은 `Optional[str]`로 정의되어 있지만, **선택 사항이 아닙니다**. 매개변수 없이 함수를 호출할 수 없습니다:
|
||||
|
||||
```Python
|
||||
say_hi() # Oh, no, this throws an error! 😱
|
||||
```
|
||||
|
||||
기본값이 없기 때문에 `name` 매개변수는 **여전히 필수입니다**(*optional*이 아님). 그럼에도 `name`은 값으로 `None`을 허용합니다:
|
||||
|
||||
```Python
|
||||
say_hi(name=None) # This works, None is valid 🎉
|
||||
```
|
||||
|
||||
좋은 소식은 Python 3.10을 사용하면, 타입의 유니온을 정의하기 위해 간단히 `|`를 사용할 수 있어서 이런 걱정을 할 필요가 없다는 점입니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
|
||||
|
||||
그러면 `Optional`이나 `Union` 같은 이름에 대해 걱정할 필요도 없습니다. 😎
|
||||
|
||||
#### Generic(제네릭) 타입 { #generic-types }
|
||||
|
||||
대괄호 안에 타입 매개변수를 받는 이러한 타입들은 **Generic types** 또는 **Generics**라고 부릅니다. 예를 들면:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
대괄호와 내부 타입을 사용해, 동일한 내장 타입들을 제네릭으로 사용할 수 있습니다:
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
그리고 이전 파이썬 버전과 마찬가지로 `typing` 모듈의 다음도 사용할 수 있습니다:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...그 밖의 것들.
|
||||
|
||||
Python 3.10에서는 제네릭 `Union`과 `Optional`을 사용하는 대안으로, 타입 유니온을 선언하기 위해 <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>세로 막대(`|`)</abbr>를 사용할 수 있는데, 훨씬 더 좋고 단순합니다.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
대괄호와 내부 타입을 사용해, 동일한 내장 타입들을 제네릭으로 사용할 수 있습니다:
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
그리고 `typing` 모듈의 제네릭들:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...그 밖의 것들.
|
||||
|
||||
////
|
||||
그냥 `str` 대신 `str | None`을 사용하면, 값이 항상 `str`이라고 가정하고 있지만 실제로는 `None`일 수도 있는 상황에서 에디터가 오류를 감지하도록 도와줍니다.
|
||||
|
||||
### 타입으로서의 클래스 { #classes-as-types }
|
||||
|
||||
|
|
@ -365,11 +255,11 @@ Python 3.10에서는 제네릭 `Union`과 `Optional`을 사용하는 대안으
|
|||
|
||||
이름을 가진 `Person` 클래스가 있다고 해봅시다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
|
||||
{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *}
|
||||
|
||||
그러면 `Person` 타입의 변수를 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
|
||||
{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *}
|
||||
|
||||
그리고 다시, 에디터의 모든 지원을 받을 수 있습니다:
|
||||
|
||||
|
|
@ -405,19 +295,13 @@ Pydantic 공식 문서의 예시:
|
|||
|
||||
이 모든 것은 [자습서 - 사용자 안내서](tutorial/index.md){.internal-link target=_blank}에서 실제로 많이 보게 될 것입니다.
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
Pydantic은 기본값 없이 `Optional` 또는 `Union[Something, None]`을 사용할 때 특별한 동작이 있습니다. 이에 대해서는 Pydantic 문서의 <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required Optional fields</a>에서 더 읽을 수 있습니다.
|
||||
|
||||
///
|
||||
|
||||
## 메타데이터 애너테이션이 있는 타입 힌트 { #type-hints-with-metadata-annotations }
|
||||
|
||||
파이썬에는 `Annotated`를 사용해 이러한 타입 힌트에 **추가 <abbr title="Data about the data, in this case, information about the type, e.g. a description.">메타데이터</abbr>**를 넣을 수 있는 기능도 있습니다.
|
||||
파이썬에는 `Annotated`를 사용해 이러한 타입 힌트에 **추가 <dfn title="데이터에 대한 데이터, 여기서는 타입에 대한 정보(예: 설명)">메타데이터</dfn>**를 넣을 수 있는 기능도 있습니다.
|
||||
|
||||
Python 3.9부터 `Annotated`는 표준 라이브러리의 일부이므로, `typing`에서 import할 수 있습니다.
|
||||
`Annotated`는 `typing`에서 import할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
|
||||
{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *}
|
||||
|
||||
파이썬 자체는 이 `Annotated`로 아무것도 하지 않습니다. 그리고 에디터와 다른 도구들에게는 타입이 여전히 `str`입니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# 리소스 { #resources }
|
||||
|
||||
추가 리소스, 외부 링크 등. ✈️
|
||||
추가 리소스, 외부 링크, 그리고 더 많은 자료. ✈️
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
/// details | 🌐 AI와 사람이 함께한 번역
|
||||
|
||||
이 번역은 사람의 안내를 받아 AI가 만들었습니다. 🤝
|
||||
|
||||
원문의 의미를 오해하거나 부자연스러워 보이는 등 오류가 있을 수 있습니다. 🤖
|
||||
|
||||
[AI LLM을 더 잘 안내하는 데 도움을 주세요](https://fastapi.tiangolo.com/ko/contributing/#translations).
|
||||
|
||||
[영문 버전](ENGLISH_VERSION_URL)
|
||||
|
||||
///
|
||||
|
|
@ -15,7 +15,7 @@ FastAPI에서는 응답을 반환한 *후에* 실행할 백그라운드 작업
|
|||
|
||||
먼저 `BackgroundTasks`를 임포트하고, `BackgroundTasks` 타입 선언으로 *경로 처리 함수*에 매개변수를 정의합니다:
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *}
|
||||
|
||||
**FastAPI**가 `BackgroundTasks` 타입의 객체를 생성하고 해당 매개변수로 전달합니다.
|
||||
|
||||
|
|
@ -31,13 +31,13 @@ FastAPI에서는 응답을 반환한 *후에* 실행할 백그라운드 작업
|
|||
|
||||
그리고 쓰기 작업은 `async`와 `await`를 사용하지 않으므로, 일반 `def`로 함수를 정의합니다:
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *}
|
||||
|
||||
## 백그라운드 작업 추가 { #add-the-background-task }
|
||||
|
||||
*경로 처리 함수* 내부에서 `.add_task()` 메서드로 작업 함수를 *백그라운드 작업* 객체에 전달합니다:
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *}
|
||||
|
||||
`.add_task()`는 다음 인자를 받습니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -58,17 +58,17 @@ from app.routers import items
|
|||
|
||||
```bash
|
||||
.
|
||||
├── app # "app" is a Python package
|
||||
│ ├── __init__.py # this file makes "app" a "Python package"
|
||||
│ ├── main.py # "main" module, e.g. import app.main
|
||||
│ ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
|
||||
│ └── routers # "routers" is a "Python subpackage"
|
||||
│ │ ├── __init__.py # makes "routers" a "Python subpackage"
|
||||
│ │ ├── items.py # "items" submodule, e.g. import app.routers.items
|
||||
│ │ └── users.py # "users" submodule, e.g. import app.routers.users
|
||||
│ └── internal # "internal" is a "Python subpackage"
|
||||
│ ├── __init__.py # makes "internal" a "Python subpackage"
|
||||
│ └── admin.py # "admin" submodule, e.g. import app.internal.admin
|
||||
├── app # 'app'은 Python 패키지입니다
|
||||
│ ├── __init__.py # 이 파일로 'app'이 'Python 패키지'가 됩니다
|
||||
│ ├── main.py # 'main' 모듈, 예: import app.main
|
||||
│ ├── dependencies.py # 'dependencies' 모듈, 예: import app.dependencies
|
||||
│ └── routers # 'routers'는 'Python 하위 패키지'입니다
|
||||
│ │ ├── __init__.py # 이 파일로 'routers'가 'Python 하위 패키지'가 됩니다
|
||||
│ │ ├── items.py # 'items' 서브모듈, 예: import app.routers.items
|
||||
│ │ └── users.py # 'users' 서브모듈, 예: import app.routers.users
|
||||
│ └── internal # 'internal'은 'Python 하위 패키지'입니다
|
||||
│ ├── __init__.py # 이 파일로 'internal'이 'Python 하위 패키지'가 됩니다
|
||||
│ └── admin.py # 'admin' 서브모듈, 예: import app.internal.admin
|
||||
```
|
||||
|
||||
## `APIRouter` { #apirouter }
|
||||
|
|
@ -85,7 +85,7 @@ from app.routers import items
|
|||
|
||||
`FastAPI` 클래스와 동일한 방식으로 import하고 "instance"를 생성합니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
|
||||
### `APIRouter`로 *path operations* 만들기 { #path-operations-with-apirouter }
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ from app.routers import items
|
|||
|
||||
`FastAPI` 클래스를 사용할 때와 동일한 방식으로 사용합니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
||||
|
||||
`APIRouter`는 "미니 `FastAPI`" 클래스라고 생각할 수 있습니다.
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ from app.routers import items
|
|||
|
||||
이제 간단한 dependency를 사용해 커스텀 `X-Token` 헤더를 읽어 보겠습니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ from app.routers import items
|
|||
|
||||
따라서 각 *path operation*마다 매번 모두 추가하는 대신, `APIRouter`에 한 번에 추가할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
||||
|
||||
각 *path operation*의 경로는 다음처럼 `/`로 시작해야 하므로:
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ async def read_item(item_id: str):
|
|||
|
||||
그래서 dependencies에 대해 `..`를 사용하는 상대 import를 사용합니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *}
|
||||
|
||||
#### 상대 import가 동작하는 방식 { #how-relative-imports-work }
|
||||
|
||||
|
|
@ -279,7 +279,7 @@ from ...dependencies import get_token_header
|
|||
|
||||
하지만 특정 *path operation*에만 적용될 _추가_ `tags`를 더할 수도 있고, 그 *path operation* 전용의 추가 `responses`도 넣을 수 있습니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -305,13 +305,13 @@ from ...dependencies import get_token_header
|
|||
|
||||
또한 각 `APIRouter`의 dependencies와 결합될 [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}도 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
|
||||
|
||||
### `APIRouter` import하기 { #import-the-apirouter }
|
||||
|
||||
이제 `APIRouter`가 있는 다른 submodule들을 import합니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *}
|
||||
|
||||
`app/routers/users.py`와 `app/routers/items.py` 파일은 같은 Python package `app`에 속한 submodule들이므로, 점 하나 `.`를 사용해 "상대 import"로 가져올 수 있습니다.
|
||||
|
||||
|
|
@ -374,13 +374,13 @@ from .routers.users import router
|
|||
|
||||
따라서 같은 파일에서 둘 다 사용할 수 있도록 submodule들을 직접 import합니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *}
|
||||
|
||||
### `users`와 `items`용 `APIRouter` 포함하기 { #include-the-apirouters-for-users-and-items }
|
||||
|
||||
이제 submodule `users`와 `items`의 `router`를 포함해 봅시다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -394,7 +394,7 @@ from .routers.users import router
|
|||
|
||||
그 router의 모든 route가 애플리케이션의 일부로 포함됩니다.
|
||||
|
||||
/// note Technical Details | 기술 세부사항
|
||||
/// note | 기술 세부사항
|
||||
|
||||
내부적으로는 `APIRouter`에 선언된 각 *path operation*마다 *path operation*을 실제로 생성합니다.
|
||||
|
||||
|
|
@ -420,13 +420,13 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다.
|
|||
|
||||
이 예시에서는 매우 단순하게 만들겠습니다. 하지만 조직 내 다른 프로젝트와 공유되기 때문에, 이를 수정할 수 없어 `prefix`, `dependencies`, `tags` 등을 `APIRouter`에 직접 추가할 수 없다고 해봅시다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
하지만 `APIRouter`를 포함할 때 커스텀 `prefix`를 지정해 모든 *path operations*가 `/admin`으로 시작하게 하고, 이 프로젝트에서 이미 가진 `dependencies`로 보호하고, `tags`와 `responses`도 포함하고 싶습니다.
|
||||
|
||||
원래 `APIRouter`를 수정하지 않고도 `app.include_router()`에 파라미터를 전달해서 이를 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *}
|
||||
|
||||
이렇게 하면 원래 `APIRouter`는 수정되지 않으므로, 조직 내 다른 프로젝트에서도 동일한 `app/internal/admin.py` 파일을 계속 공유할 수 있습니다.
|
||||
|
||||
|
|
@ -447,11 +447,11 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다.
|
|||
|
||||
여기서는 가능하다는 것을 보여주기 위해... 그냥 해봅니다 🤷:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *}
|
||||
|
||||
그리고 `app.include_router()`로 추가한 다른 모든 *path operations*와 함께 올바르게 동작합니다.
|
||||
|
||||
/// info | 정보
|
||||
/// info | 매우 기술적인 세부사항
|
||||
|
||||
**참고**: 이는 매우 기술적인 세부사항이라 아마 **그냥 건너뛰어도 됩니다**.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@
|
|||
|
||||
/// warning | 경고
|
||||
|
||||
별도 키가 전달된 `Field` 또한 여러분의 어플리케이션의 OpenAPI 스키마에 나타날 것입니다.
|
||||
이런 키가 OpenAPI 명세서, [the OpenAPI validator](https://validator.swagger.io/)같은 몇몇 OpenAPI 도구들에 포함되지 못할 수 있으며, 여러분이 생성한 스키마와 호환되지 않을 수 있습니다.
|
||||
별도 키가 전달된 `Field` 또한 여러분의 애플리케이션의 OpenAPI 스키마에 나타날 것입니다.
|
||||
이런 키가 OpenAPI 명세서의 일부가 아닐 수도 있으므로, [OpenAPI validator](https://validator.swagger.io/) 같은 몇몇 OpenAPI 도구들은 여러분이 생성한 스키마와 호환되지 않을 수 있습니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
|
|||
|
|
@ -106,13 +106,6 @@
|
|||
q: str | None = None
|
||||
```
|
||||
|
||||
또는 Python 3.9에서는:
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
|
||||
예를 들어:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ images: list[Image]
|
|||
|
||||
이를 아래처럼:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *}
|
||||
|
||||
## 어디서나 편집기 지원 { #editor-support-everywhere }
|
||||
|
||||
|
|
@ -194,7 +194,7 @@ Pydantic 모델 대신 `dict`로 직접 작업한다면 이런 종류의 편집
|
|||
|
||||
이 경우, `int` 키와 `float` 값을 가진 한 어떤 `dict`든 받아들입니다:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
* 매개변수 `item`에 포함된 수신 데이터를 제공합니다.
|
||||
* 함수 내에서 매개변수를 `Item` 타입으로 선언했기 때문에, 모든 어트리뷰트와 그에 대한 타입에 대한 편집기 지원(완성 등)을 또한 받을 수 있습니다.
|
||||
* 여러분의 모델을 위한 <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> 정의를 생성합니다. 여러분의 프로젝트에 적합하다면 여러분이 사용하고 싶은 곳 어디에서나 사용할 수 있습니다.
|
||||
* 이러한 스키마는, 생성된 OpenAPI 스키마 일부가 될 것이며, 자동 문서화 <abbr title="User Interfaces – 사용자 인터페이스">UIs</abbr>에 사용됩니다.
|
||||
* 이러한 스키마는, 생성된 OpenAPI 스키마 일부가 될 것이며, 자동 문서화 <abbr title="User Interfaces - 사용자 인터페이스">UIs</abbr>에 사용됩니다.
|
||||
|
||||
## 자동 문서화 { #automatic-docs }
|
||||
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
|
||||
**본문**, **경로** 그리고 **쿼리** 매개변수 모두 동시에 선언할 수도 있습니다.
|
||||
|
||||
**FastAPI**는 각각을 인지하고 데이터를 옳바른 위치에 가져올 것입니다.
|
||||
**FastAPI**는 각각을 인지하고 데이터를 올바른 위치에 가져올 것입니다.
|
||||
|
||||
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
|
||||
|
||||
|
|
@ -153,9 +153,9 @@
|
|||
|
||||
/// note | 참고
|
||||
|
||||
FastAPI는 `q`의 값이 필요없음을 알게 될 것입니다. 기본 값이 `= None`이기 때문입니다.
|
||||
FastAPI는 `q`의 값이 필요없음을 기본 값 `= None` 때문에 알게 됩니다.
|
||||
|
||||
Python 3.10+의 `str | None` 또는 Python 3.9+의 `Union[str, None]`에 있는 `Union`은 FastAPI가 `q` 값이 필수가 아님을 판단하기 위해 사용하지 않습니다. 기본 값이 `= None`이기 때문에 필수가 아님을 알게 됩니다.
|
||||
`str | None`은 FastAPI가 값이 필수인지 아닌지를 판단하기 위해 사용하지 않습니다. 기본 값이 `= None`이므로 필수가 아님을 알게 됩니다.
|
||||
|
||||
하지만 타입 어노테이션을 추가하면 편집기가 더 나은 지원을 제공하고 오류를 감지할 수 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
일부 특별한 사용 사례(흔하지는 않겠지만)에서는 수신하려는 쿠키를 **제한**할 수 있습니다.
|
||||
|
||||
이제 API는 자신의 <abbr title="This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪">cookie consent</abbr>를 제어할 수 있는 권한을 갖게 되었습니다. 🤪🍪
|
||||
이제 API는 자신의 <dfn title="혹시라도 오해할까 봐 하는 농담입니다. 쿠키 동의와는 아무 관련이 없지만, 이제 API도 불쌍한 쿠키를 거절할 수 있다는 점이 웃기네요. 쿠키 하나 드세요. 🍪">쿠키 동의</dfn>를 제어할 수 있는 권한을 갖게 되었습니다. 🤪🍪
|
||||
|
||||
Pydantic의 모델 구성을 사용하여 추가(`extra`) 필드를 금지(`forbid`)할 수 있습니다:
|
||||
|
||||
|
|
@ -54,9 +54,9 @@ Pydantic의 모델 구성을 사용하여 추가(`extra`) 필드를 금지(`forb
|
|||
|
||||
클라이언트가 **추가 쿠키**를 보내려고 시도하면, **오류** 응답을 받게 됩니다.
|
||||
|
||||
동의를 얻기 위해 애쓰는 불쌍한 쿠키 배너(팝업)들, <abbr title="This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕">API가 거부</abbr>하는데도. 🍪
|
||||
동의를 얻기 위해 애쓰는 불쌍한 쿠키 배너(팝업)들, <dfn title="이것도 농담입니다. 신경 쓰지 마세요. 쿠키와 함께 커피 한 잔 하세요. ☕">API가 거부</dfn>하는데도. 🍪
|
||||
|
||||
예를 들어, 클라이언트가 `good-list-please` 값으로 `santa_tracker` 쿠키를 보내려고 하면 클라이언트는 `santa_tracker` <abbr title="Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">쿠키가 허용되지 않는다</abbr>는 **오류** 응답을 받게 됩니다:
|
||||
예를 들어, 클라이언트가 `good-list-please` 값으로 `santa_tracker` 쿠키를 보내려고 하면 클라이언트는 `santa_tracker` <dfn title="산타는 쿠키가 부족한 것을 못마땅해합니다. 🎅 좋아요, 이제 더 이상 쿠키 농담은 하지 않겠습니다.">쿠키가 허용되지 않는다</dfn>는 **오류** 응답을 받게 됩니다:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -73,4 +73,4 @@ Pydantic의 모델 구성을 사용하여 추가(`extra`) 필드를 금지(`forb
|
|||
|
||||
## 요약 { #summary }
|
||||
|
||||
**Pydantic 모델**을 사용하여 **FastAPI**에서 <abbr title="Have a last cookie before you go. 🍪">**쿠키**</abbr>를 선언할 수 있습니다. 😎
|
||||
**Pydantic 모델**을 사용하여 **FastAPI**에서 <dfn title="가시기 전에 마지막 쿠키 하나 드세요. 🍪">**쿠키**</dfn>를 선언할 수 있습니다. 😎
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
|
||||
///
|
||||
|
||||
/// info | 정보
|
||||
/// info
|
||||
|
||||
쿠키를 선언하기 위해서는 `Cookie`를 사용해야 합니다. 그렇지 않으면 해당 매개변수를 쿼리 매개변수로 해석하기 때문입니다.
|
||||
|
||||
///
|
||||
|
||||
/// info | 정보
|
||||
/// info
|
||||
|
||||
**브라우저는 쿠키를** 내부적으로 특별한 방식으로 처리하기 때문에, **JavaScript**가 쉽게 쿠키를 다루도록 허용하지 않는다는 점을 염두에 두세요.
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
* 특정 HTTP 메서드(`POST`, `PUT`) 또는 와일드카드 `"*"`를 사용한 모든 메서드.
|
||||
* 특정 HTTP 헤더 또는 와일드카드 `"*"`를 사용한 모든 헤더.
|
||||
|
||||
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
|
||||
{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *}
|
||||
|
||||
|
||||
`CORSMiddleware` 구현에서 사용하는 기본 매개변수는 기본적으로 제한적이므로, 브라우저가 Cross-Domain 컨텍스트에서 특정 출처, 메서드 또는 헤더를 사용할 수 있도록 하려면 이를 명시적으로 활성화해야 합니다.
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
|
||||
## 더 많은 정보 { #more-info }
|
||||
|
||||
<abbr title="Cross-Origin Resource Sharing – 교차-출처 리소스 공유">CORS</abbr>에 대한 더 많은 정보는 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS 문서</a>를 참고하세요.
|
||||
<abbr title="Cross-Origin Resource Sharing - 교차-출처 리소스 공유">CORS</abbr>에 대한 더 많은 정보는 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS 문서</a>를 참고하세요.
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
FastAPI 애플리케이션에서 `uvicorn`을 직접 임포트하여 실행합니다:
|
||||
|
||||
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
|
||||
{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
|
||||
|
||||
### `__name__ == "__main__"` 에 대하여 { #about-name-main }
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ FastAPI가 실제로 확인하는 것은 그것이 "호출 가능(callable)"(함
|
|||
|
||||
위 코드에서 `CommonQueryParams`를 두 번 작성하는 방식에 주목하세요:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
|
@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ FastAPI는 여기에서 선언된 매개변수들을 추출하고, 실제로 이
|
|||
|
||||
이 경우 첫 번째 `CommonQueryParams`는 다음에서:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, ...
|
||||
|
|
@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ commons: CommonQueryParams ...
|
|||
|
||||
실제로는 이렇게만 작성해도 됩니다:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
|
|
@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams)
|
|||
|
||||
하지만 `CommonQueryParams`를 두 번 작성하는 코드 반복이 있다는 것을 볼 수 있습니다:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
|
@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
|||
|
||||
다음처럼 작성하는 대신:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
|
@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
|||
|
||||
...이렇게 작성합니다:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends()]
|
||||
|
|
@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ Annotated 미사용
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
# 경로 작동 데코레이터에서의 의존성 { #dependencies-in-path-operation-decorators }
|
||||
# 경로 처리 데코레이터에서의 의존성 { #dependencies-in-path-operation-decorators }
|
||||
|
||||
몇몇 경우에는, *경로 작동 함수* 안에서 의존성의 반환 값이 필요하지 않습니다.
|
||||
몇몇 경우에는, *경로 처리 함수* 안에서 의존성의 반환 값이 필요하지 않습니다.
|
||||
|
||||
또는 의존성이 값을 반환하지 않습니다.
|
||||
|
||||
그러나 여전히 실행/해결될 필요가 있습니다.
|
||||
|
||||
그런 경우에, `Depends`를 사용하여 *경로 작동 함수*의 매개변수로 선언하는 것보다 *경로 작동 데코레이터*에 `dependencies`의 `list`를 추가할 수 있습니다.
|
||||
그런 경우에, `Depends`를 사용하여 *경로 처리 함수*의 매개변수로 선언하는 대신 *경로 처리 데코레이터*에 `dependencies`의 `list`를 추가할 수 있습니다.
|
||||
|
||||
## *경로 작동 데코레이터*에 `dependencies` 추가하기 { #add-dependencies-to-the-path-operation-decorator }
|
||||
## *경로 처리 데코레이터*에 `dependencies` 추가하기 { #add-dependencies-to-the-path-operation-decorator }
|
||||
|
||||
*경로 작동 데코레이터*는 `dependencies`라는 선택적인 인자를 받습니다.
|
||||
*경로 처리 데코레이터*는 선택적인 인자 `dependencies`를 받습니다.
|
||||
|
||||
`Depends()`로 된 `list`이어야합니다:
|
||||
`Depends()`로 된 `list`이어야 합니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *}
|
||||
|
||||
이러한 의존성들은 기존 의존성들과 같은 방식으로 실행/해결됩니다. 그러나 값은 (무엇이든 반환한다면) *경로 작동 함수*에 제공되지 않습니다.
|
||||
이러한 의존성들은 기존 의존성들과 같은 방식으로 실행/해결됩니다. 그러나 값은 (무엇이든 반환한다면) *경로 처리 함수*에 제공되지 않습니다.
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
일부 편집기에서는 사용되지 않는 함수 매개변수를 검사하고 오류로 표시합니다.
|
||||
|
||||
*경로 작동 데코레이터*에서 이러한 `dependencies`를 사용하면 편집기/도구 오류를 피하면서도 실행되도록 할 수 있습니다.
|
||||
*경로 처리 데코레이터*에서 이러한 `dependencies`를 사용하면 편집기/도구 오류를 피하면서도 실행되도록 할 수 있습니다.
|
||||
|
||||
또한 코드에서 사용되지 않는 매개변수를 보고 불필요하다고 생각할 수 있는 새로운 개발자의 혼란을 방지하는데 도움이 될 수 있습니다.
|
||||
|
||||
|
|
@ -44,13 +44,13 @@
|
|||
|
||||
(헤더같은) 요청 요구사항이나 하위-의존성을 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *}
|
||||
|
||||
### 오류 발생시키기 { #raise-exceptions }
|
||||
|
||||
다음 의존성은 기존 의존성과 동일하게 예외를 `raise`할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *}
|
||||
|
||||
### 값 반환하기 { #return-values }
|
||||
|
||||
|
|
@ -58,12 +58,12 @@
|
|||
|
||||
그래서 이미 다른 곳에서 사용된 (값을 반환하는) 일반적인 의존성을 재사용할 수 있고, 비록 값은 사용되지 않지만 의존성은 실행될 것입니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *}
|
||||
|
||||
## *경로 작동* 모음에 대한 의존성 { #dependencies-for-a-group-of-path-operations }
|
||||
## *경로 처리* 모음에 대한 의존성 { #dependencies-for-a-group-of-path-operations }
|
||||
|
||||
나중에 여러 파일을 가지고 있을 수 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 작동* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다.
|
||||
나중에 여러 파일을 가지고 있을 수 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 처리* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다.
|
||||
|
||||
## 전역 의존성 { #global-dependencies }
|
||||
|
||||
다음으로 각 *경로 작동*에 적용되도록 `FastAPI` 애플리케이션 전체에 의존성을 추가하는 법을 볼 것입니다.
|
||||
다음으로 각 *경로 처리*에 적용되도록 `FastAPI` 애플리케이션 전체에 의존성을 추가하는 법을 볼 것입니다.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# `yield`를 사용하는 의존성 { #dependencies-with-yield }
|
||||
|
||||
FastAPI는 <abbr title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc. – 때로는 "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code" 등으로도 불립니다'>작업 완료 후 추가 단계를 수행하는</abbr> 의존성을 지원합니다.
|
||||
FastAPI는 <dfn title='때로는 "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code" 등으로도 불립니다'>작업 완료 후 추가 단계</dfn>를 수행하는 의존성을 지원합니다.
|
||||
|
||||
이를 구현하려면 `return` 대신 `yield`를 사용하고, 추가로 실행할 단계 (코드)를 그 뒤에 작성하세요.
|
||||
|
||||
|
|
@ -29,15 +29,15 @@ FastAPI는 <abbr title='sometimes also called "exit code", "cleanup code", "tear
|
|||
|
||||
응답을 생성하기 전에는 `yield`문을 포함하여 그 이전의 코드만이 실행됩니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *}
|
||||
|
||||
yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *}
|
||||
|
||||
`yield`문 다음의 코드는 응답을 생성한 후 실행됩니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
마찬가지로, `finally`를 사용하여 예외 발생 여부와 관계 없이 종료 단계까 실행되도록 할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *}
|
||||
|
||||
## `yield`를 사용하는 하위 의존성 { #sub-dependencies-with-yield }
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
예를 들어, `dependency_c`는 `dependency_b`에 의존할 수 있고, `dependency_b`는 `dependency_a`에 의존할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *}
|
||||
|
||||
이들 모두는 `yield`를 사용할 수 있습니다.
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
그리고, `dependency_b`는 종료 코드를 위해 `dependency_a`의 값 (여기서는 `dep_a`로 명명) 이 사용 가능해야 합니다.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *}
|
||||
|
||||
같은 방식으로, `yield`를 사용하는 의존성과 `return`을 사용하는 의존성을 함께 사용할 수 있으며, 이들 중 일부가 다른 것들에 의존할 수 있습니다.
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
///
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
|
||||
{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
|
||||
|
||||
예외를 잡고 그에 기반해 사용자 정의 응답을 생성하려면, [사용자 정의 예외 처리기](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}를 생성하세요.
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
`yield`를 사용하는 의존성에서 `except`를 사용하여 예외를 포착하고 예외를 다시 발생시키지 않거나 (또는 새 예외를 발생시키지 않으면), FastAPI는 일반적인 Python에서와 마찬가지로 예외가 있었다는 것을 알아차릴 수 없습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
|
||||
{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *}
|
||||
|
||||
이 경우, `HTTPException`이나 유사한 예외를 발생시키지 않기 때문에 클라이언트는 마땅히 *HTTP 500 Internal Server Error* 응답을 보게 되지만, 서버에는 어떤 오류였는지에 대한 **로그**나 다른 표시가 **전혀 남지 않게 됩니다**. 😱
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ yield된 값은 *경로 처리* 및 다른 의존성들에 주입되는 값 입
|
|||
|
||||
`raise`를 사용하여 동일한 예외를 다시 발생시킬 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
|
||||
{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *}
|
||||
|
||||
이제 클라이언트는 동일한 *HTTP 500 Internal Server Error* 응답을 받게 되지만, 서버 로그에는 사용자 정의 `InternalError`가 기록됩니다. 😎
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ participant tasks as Background tasks
|
|||
|
||||
하지만 *경로 처리 함수*에서 반환한 뒤에는 더 이상 해당 의존성이 필요 없다는 것을 알고 있다면, `Depends(scope="function")`을 사용하여 FastAPI에 *경로 처리 함수*가 반환된 후, 하지만 **응답이 전송되기 전에** 의존성을 종료(닫기)해야 한다고 알려줄 수 있습니다.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *}
|
||||
|
||||
`Depends()`는 다음이 될 수 있는 `scope` 매개변수를 받습니다:
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ Python에서는 다음을 통해 컨텍스트 관리자를 생성할 수 있습
|
|||
**FastAPI**의 `yield`가 있는 의존성 내에서
|
||||
`with` 또는 `async with`문을 사용하여 이들을 활용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
|
||||
{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
몇몇 유형의 애플리케이션에서는 애플리케이션 전체에 의존성을 추가하고 싶을 수 있습니다.
|
||||
|
||||
[*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}와 유사한 방법으로 `FastAPI` 애플리케케이션에 그것들을 추가할 수 있습니다.
|
||||
[*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}와 유사한 방법으로 `FastAPI` 애플리케이션에 그것들을 추가할 수 있습니다.
|
||||
|
||||
그런 경우에, 애플리케이션의 모든 *경로 처리*에 적용될 것입니다:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
|
||||
|
||||
그리고 [*경로 처리 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 섹션의 모든 아이디어는 여전히 적용되지만, 이 경우에는 앱의 모든 *경로 처리*에 적용됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# 의존성 { #dependencies }
|
||||
|
||||
**FastAPI**는 아주 강력하지만 직관적인 **<abbr title="also known as components, resources, providers, services, injectables">의존성 주입</abbr>** 시스템을 가지고 있습니다.
|
||||
**FastAPI**는 아주 강력하지만 직관적인 **<dfn title="컴포넌트, 리소스, 제공자, 서비스, 인젝터블로도 알려져 있음">의존성 주입</dfn>** 시스템을 가지고 있습니다.
|
||||
|
||||
이는 사용하기 아주 쉽게 설계했으며, 어느 개발자나 다른 컴포넌트와 **FastAPI**를 쉽게 통합할 수 있도록 만들었습니다.
|
||||
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
* 선택적인 쿼리 매개변수 `q`, `str`을 자료형으로 가집니다.
|
||||
* 선택적인 쿼리 매개변수 `skip`, `int`를 자료형으로 가지며 기본 값은 `0`입니다.
|
||||
* 선택적인 쿼리 매개변수 `limit` that is an `int`, and by default is `100`.
|
||||
* 선택적인 쿼리 매개변수 `limit`, `int`를 자료형으로 가지며 기본 값은 `100`입니다.
|
||||
|
||||
그 후 위의 값을 포함한 `dict` 자료형으로 반환할 뿐입니다.
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ FastAPI는 0.95.0 버전부터 `Annotated`에 대한 지원을 (그리고 이를
|
|||
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *}
|
||||
|
||||
비록 `Body`, `Query` 등을 사용하는 것과 같은 방식으로 여러분의 함수의 매개변수에 있는 `Depends`를 사용하지만, `Depends`는 약간 다르게 작동합니다.
|
||||
비록 `Depends`를 함수의 매개변수에서 `Body`, `Query` 등을 사용하는 것과 같은 방식으로 사용하지만, `Depends`는 약간 다르게 작동합니다.
|
||||
|
||||
`Depends`에 단일 매개변수만 전달했습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query
|
|||
|
||||
같은 *경로 처리*에 대해 의존성 중 하나가 여러 번 선언되는 경우(예: 여러 의존성이 공통 하위 의존성을 갖는 경우), **FastAPI**는 그 하위 의존성을 요청당 한 번만 호출해야 한다는 것을 알고 있습니다.
|
||||
|
||||
그리고 같은 요청에 대해 동일한 의존성을 여러 번 호출하는 대신, 반환값을 <abbr title="계산/생성된 값을 저장해 두었다가, 다시 계산하지 않고 재사용하기 위한 유틸리티/시스템.">"cache"</abbr>에 저장하고, 그 요청에서 해당 값이 필요한 모든 "dependants"에 전달합니다.
|
||||
그리고 같은 요청에 대해 동일한 의존성을 여러 번 호출하는 대신, 반환값을 <dfn title="계산/생성된 값을 저장해 두었다가, 다시 계산하지 않고 재사용하기 위한 유틸리티/시스템.">"캐시"</dfn>에 저장하고, 그 요청에서 해당 값이 필요한 모든 "dependants"에 전달합니다.
|
||||
|
||||
고급 시나리오로, 같은 요청에서 "cached" 값을 쓰는 대신 매 단계마다(아마도 여러 번) 의존성이 호출되어야 한다는 것을 알고 있다면, `Depends`를 사용할 때 `use_cache=False` 파라미터를 설정할 수 있습니다:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||
|
|
@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
|
|||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 비 Annotated
|
||||
//// tab | Python 3.10+ 비 Annotated
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ JSON 호환 가능 데이터만 수신하는 `fake_db` 데이터베이스가 존
|
|||
|
||||
예를 들면, `datetime` 객체는 JSON과 호환되지 않으므로 이 데이터베이스는 이를 받지 않습니다.
|
||||
|
||||
따라서 `datetime` 객체는 <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO format</a>의 데이터를 포함하는 `str`로 변환되어야 합니다.
|
||||
따라서 `datetime` 객체는 <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO 형식</a>의 데이터를 포함하는 `str`로 변환되어야 합니다.
|
||||
|
||||
같은 방식으로 이 데이터베이스는 Pydantic 모델(속성이 있는 객체)을 받지 않고, `dict`만을 받습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
* **출력 모델**은 비밀번호를 가지면 안 됩니다.
|
||||
* **데이터베이스 모델**은 아마도 해시 처리된 비밀번호를 가질 필요가 있을 것입니다.
|
||||
|
||||
/// danger | 위험
|
||||
/// danger
|
||||
|
||||
절대 사용자의 비밀번호를 평문으로 저장하지 마세요. 항상 이후에 검증 가능한 "안전한 해시(secure hash)"로 저장하세요.
|
||||
|
||||
만약 이게 무엇인지 모르겠다면, [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}에서 "password hash"가 무엇인지 배울 수 있습니다.
|
||||
만약 이게 무엇인지 모르겠다면, [보안 장](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}에서 "password hash"가 무엇인지 배울 수 있습니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ UserInDB(
|
|||
)
|
||||
```
|
||||
|
||||
/// warning | 경고
|
||||
/// warning
|
||||
|
||||
추가적으로 제공된 함수 `fake_password_hasher`와 `fake_save_user`는 데이터 흐름을 시연하기 위한 예제일 뿐이며, 실제 보안을 제공하지 않습니다.
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ OpenAPI에서는 이를 `anyOf`로 정의합니다.
|
|||
|
||||
이를 위해 표준 Python 타입 힌트인 <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>을 사용할 수 있습니다:
|
||||
|
||||
/// note | 참고
|
||||
/// note
|
||||
|
||||
<a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a>을 정의할 때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야 합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]`에서 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다.
|
||||
|
||||
|
|
@ -190,9 +190,9 @@ some_variable: PlaneItem | CarItem
|
|||
|
||||
마찬가지로, 객체 리스트 형태의 응답을 선언할 수도 있습니다.
|
||||
|
||||
이를 위해 표준 Python의 `typing.List`를 사용하세요(또는 Python 3.9 이상에서는 단순히 `list`를 사용할 수 있습니다):
|
||||
이를 위해 표준 Python의 `list`를 사용하세요:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
|
||||
{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *}
|
||||
|
||||
## 임의의 `dict` 응답 { #response-with-arbitrary-dict }
|
||||
|
||||
|
|
@ -200,9 +200,9 @@ Pydantic 모델을 사용하지 않고, 키와 값의 타입만 선언하여 평
|
|||
|
||||
이는 Pydantic 모델에 필요한 유효한 필드/속성 이름을 사전에 알 수 없는 경우에 유용합니다.
|
||||
|
||||
이 경우, `typing.Dict`를 사용할 수 있습니다(또는 Python 3.9 이상에서는 단순히 `dict`를 사용할 수 있습니다):
|
||||
이 경우, `dict`를 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
|
||||
{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *}
|
||||
|
||||
## 요약 { #recap }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
가장 단순한 FastAPI 파일은 다음과 같이 보일 것입니다:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py *}
|
||||
|
||||
위 코드를 `main.py`에 복사합니다.
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
|||
|
||||
#### OpenAPI와 JSON 스키마 { #openapi-and-json-schema }
|
||||
|
||||
OpenAPI는 당신의 API에 대한 API 스키마를 정의합니다. 또한 이 스키마는 JSON 데이터 스키마의 표준인 **JSON 스키마**를 사용하여 당신의 API가 보내고 받는 데이터의 정의(또는 "스키마")를 포함합니다.
|
||||
OpenAPI는 여러분의 API에 대한 API 스키마를 정의합니다. 또한 이 스키마는 JSON 데이터 스키마의 표준인 **JSON 스키마**를 사용하여 여러분의 API가 보내고 받는 데이터의 정의(또는 "스키마")를 포함합니다.
|
||||
|
||||
#### `openapi.json` 확인 { #check-the-openapi-json }
|
||||
|
||||
|
|
@ -183,9 +183,9 @@ Deploying to FastAPI Cloud...
|
|||
|
||||
### 1 단계: `FastAPI` 임포트 { #step-1-import-fastapi }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *}
|
||||
|
||||
`FastAPI`는 당신의 API를 위한 모든 기능을 제공하는 파이썬 클래스입니다.
|
||||
`FastAPI`는 여러분의 API를 위한 모든 기능을 제공하는 파이썬 클래스입니다.
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
|
|
@ -197,11 +197,11 @@ Deploying to FastAPI Cloud...
|
|||
|
||||
### 2 단계: `FastAPI` "인스턴스" 생성 { #step-2-create-a-fastapi-instance }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *}
|
||||
|
||||
여기에서 `app` 변수는 `FastAPI` 클래스의 "인스턴스"가 됩니다.
|
||||
|
||||
이것은 당신의 모든 API를 생성하기 위한 상호작용의 주요 지점이 될 것입니다.
|
||||
이것은 여러분의 모든 API를 생성하기 위한 상호작용의 주요 지점이 될 것입니다.
|
||||
|
||||
### 3 단계: *경로 처리* 생성 { #step-3-create-a-path-operation }
|
||||
|
||||
|
|
@ -266,12 +266,12 @@ API를 설계할 때 일반적으로 특정 행동을 수행하기 위해 특정
|
|||
|
||||
#### *경로 처리 데코레이터* 정의 { #define-a-path-operation-decorator }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *}
|
||||
|
||||
`@app.get("/")`은 **FastAPI**에게 바로 아래에 있는 함수가 다음으로 이동하는 요청을 처리한다는 것을 알려줍니다:
|
||||
|
||||
* 경로 `/`
|
||||
* <abbr title="an HTTP GET method"><code>get</code> operation</abbr> 사용
|
||||
* <dfn title="HTTP GET 메소드"><code>get</code> 작동</dfn> 사용
|
||||
|
||||
/// info | `@decorator` 정보
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ API를 설계할 때 일반적으로 특정 행동을 수행하기 위해 특정
|
|||
* **작동**: 은 `get`입니다.
|
||||
* **함수**: 는 "데코레이터" 아래에 있는 함수입니다 (`@app.get("/")` 아래).
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *}
|
||||
|
||||
이것은 파이썬 함수입니다.
|
||||
|
||||
|
|
@ -332,7 +332,7 @@ URL "`/`"에 대한 `GET` 작동을 사용하는 요청을 받을 때마다 **Fa
|
|||
|
||||
`async def`을 이용하는 대신 일반 함수로 정의할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ URL "`/`"에 대한 `GET` 작동을 사용하는 요청을 받을 때마다 **Fa
|
|||
|
||||
### 5 단계: 콘텐츠 반환 { #step-5-return-the-content }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *}
|
||||
|
||||
`dict`, `list`, 단일값을 가진 `str`, `int` 등을 반환할 수 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ API를 사용하는 클라이언트에 오류를 알려야 하는 상황은 많
|
|||
|
||||
### `HTTPException` 가져오기 { #import-httpexception }
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *}
|
||||
|
||||
### 코드에서 `HTTPException` 발생시키기 { #raise-an-httpexception-in-your-code }
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ Python 예외이므로 `return` 하는 것이 아니라 `raise` 합니다.
|
|||
|
||||
이 예시에서는, 클라이언트가 존재하지 않는 ID로 항목을 요청하면 상태 코드 `404`로 예외를 발생시킵니다:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
|
||||
|
||||
### 결과 응답 { #the-resulting-response }
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ HTTP 오류에 커스텀 헤더를 추가할 수 있으면 유용한 상황이
|
|||
|
||||
하지만 고급 시나리오에서 필요하다면 커스텀 헤더를 추가할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
|
||||
|
||||
## 커스텀 예외 핸들러 설치하기 { #install-custom-exception-handlers }
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ HTTP 오류에 커스텀 헤더를 추가할 수 있으면 유용한 상황이
|
|||
|
||||
`@app.exception_handler()`로 커스텀 예외 핸들러를 추가할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
|
||||
{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *}
|
||||
|
||||
여기서 `/unicorns/yolo`를 요청하면, *경로 처리*가 `UnicornException`을 `raise`합니다.
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ HTTP 오류에 커스텀 헤더를 추가할 수 있으면 유용한 상황이
|
|||
|
||||
예외 핸들러는 `Request`와 예외를 받습니다.
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *}
|
||||
|
||||
이제 `/items/foo`로 이동하면, 다음과 같은 기본 JSON 오류 대신:
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
|
|||
|
||||
예를 들어, 이런 오류들에 대해 JSON 대신 일반 텍스트 응답을 반환하고 싶을 수 있습니다:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
|
|
@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
|
|||
|
||||
앱을 개발하는 동안 body를 로그로 남기고 디버그하거나, 사용자에게 반환하는 등으로 사용할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
|
||||
|
||||
이제 다음처럼 유효하지 않은 item을 보내보세요:
|
||||
|
||||
|
|
@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
|
|||
|
||||
예외를 사용하면서 **FastAPI**의 동일한 기본 예외 핸들러도 함께 사용하고 싶다면, `fastapi.exception_handlers`에서 기본 예외 핸들러를 가져와 재사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
|
||||
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
|
||||
|
||||
이 예시에서는 매우 표현력 있는 메시지로 오류를 출력만 하고 있지만, 요지는 이해하셨을 겁니다. 예외를 사용한 뒤 기본 예외 핸들러를 그대로 재사용할 수 있습니다.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
관련 있는 **헤더 매개변수** 그룹이 있는 경우, **Pydantic 모델**을 생성하여 선언할 수 있습니다.
|
||||
|
||||
이를 통해 **여러 위치**에서 **모델을 재사용** 할 수 있고 모든 매개변수에 대한 유효성 검사 및 메타데이터를 한 번에 선언할 수도 있습니다. 😎
|
||||
이를 통해 **여러 위치**에서 **모델을 재사용할** 수 있고 모든 매개변수에 대한 유효성 검사 및 메타데이터를 한 번에 선언할 수도 있습니다. 😎
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ Pydantic의 모델 구성을 사용하여 추가(`extra`) 필드를 금지(`forb
|
|||
|
||||
클라이언트가 **추가 헤더**를 보내려고 시도하면, **오류** 응답을 받게 됩니다.
|
||||
|
||||
예를 들어, 클라이언트가 `plumbus` 값으로 `tool` 헤더를 보내려고 하면, 클라이언트는 헤더 매개변수 `tool`이 허용 되지 않는다는 **오류** 응답을 받게 됩니다:
|
||||
예를 들어, 클라이언트가 `plumbus` 값으로 `tool` 헤더를 보내려고 하면, 클라이언트는 헤더 매개변수 `tool`이 허용되지 않는다는 **오류** 응답을 받게 됩니다:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ OpenAPI 명세 및 자동화된 API 문서 UI에 사용되는 다음 필드를
|
|||
|
||||
다음과 같이 설정할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
|
||||
{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie
|
|||
|
||||
예:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
|
||||
{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *}
|
||||
|
||||
## 태그에 대한 메타데이터 { #metadata-for-tags }
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie
|
|||
|
||||
태그에 대한 메타데이터를 생성하고 이를 `openapi_tags` 매개변수로 전달하세요:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
|
||||
{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *}
|
||||
|
||||
설명 안에 마크다운을 사용할 수 있다는 점에 유의하세요. 예를 들어 "login"은 굵게(**login**) 표시되고, "fancy"는 기울임꼴(_fancy_)로 표시됩니다.
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie
|
|||
|
||||
`tags` 매개변수를 *경로 처리* (및 `APIRouter`)와 함께 사용하여 이를 서로 다른 태그에 할당하세요:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
|
||||
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ OpenAPI 3.1.0 및 FastAPI 0.99.0부터 `license_info`에 `url` 대신 `identifie
|
|||
|
||||
예를 들어, 이를 `/api/v1/openapi.json`에서 제공하도록 설정하려면:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
|
||||
|
||||
OpenAPI 스키마를 완전히 비활성화하려면 `openapi_url=None`으로 설정할 수 있으며, 이를 사용하여 문서화 사용자 인터페이스도 비활성화됩니다.
|
||||
|
||||
|
|
@ -117,4 +117,4 @@ OpenAPI 스키마를 완전히 비활성화하려면 `openapi_url=None`으로
|
|||
|
||||
예를 들어, Swagger UI를 `/documentation`에서 제공하고 ReDoc을 비활성화하려면:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
`yield`를 사용하는 의존성이 있다면, exit 코드는 미들웨어 *후에* 실행됩니다.
|
||||
|
||||
백그라운드 작업(뒤에서 보게 될 [Background Tasks](background-tasks.md){.internal-link target=_blank} 섹션에서 다룹니다)이 있다면, 모든 미들웨어 *후에* 실행됩니다.
|
||||
백그라운드 작업(뒤에서 보게 될 [백그라운드 작업](background-tasks.md){.internal-link target=_blank} 섹션에서 다룹니다)이 있다면, 모든 미들웨어 *후에* 실행됩니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
* 그런 다음 해당 *경로 처리*가 생성한 `response`를 반환합니다.
|
||||
* 그런 다음 반환하기 전에 `response`를 추가로 수정할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
예를 들어, 요청을 처리하고 응답을 생성하는 데 걸린 시간을 초 단위로 담는 사용자 정의 헤더 `X-Process-Time`을 추가할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -92,4 +92,4 @@ app.add_middleware(MiddlewareB)
|
|||
|
||||
다른 미들웨어에 대한 더 많은 정보는 나중에 [숙련된 사용자 안내서: 향상된 미들웨어](../advanced/middleware.md){.internal-link target=_blank}에서 확인할 수 있습니다.
|
||||
|
||||
다음 섹션에서 미들웨어로 <abbr title="Cross-Origin Resource Sharing">CORS</abbr>를 처리하는 방법을 보게 될 것입니다.
|
||||
다음 섹션에서 미들웨어로 <abbr title="Cross-Origin Resource Sharing - 교차 출처 리소스 공유">CORS</abbr>를 처리하는 방법을 보게 될 것입니다.
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
**FastAPI**는 일반 문자열과 동일한 방식으로 이를 지원합니다:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *}
|
||||
|
||||
## 요약과 설명 { #summary-and-description }
|
||||
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
## 독스트링으로 만든 설명 { #description-from-docstring }
|
||||
|
||||
설명은 보통 길어지고 여러 줄에 걸쳐있기 때문에, *경로 처리* 설명을 함수 <abbr title="문서화에 사용되는 함수 내부 첫 표현식의 여러 줄 문자열(어떤 변수에도 할당되지 않음)">docstring</abbr>에 선언할 수 있으며, **FastAPI**는 그곳에서 이를 읽습니다.
|
||||
설명은 보통 길어지고 여러 줄에 걸쳐있기 때문에, *경로 처리* 설명을 함수 <dfn title="문서화에 사용되는 함수 내부 첫 표현식의 여러 줄 문자열(어떤 변수에도 할당되지 않음)">독스트링</dfn>에 선언할 수 있으며, **FastAPI**는 그곳에서 이를 읽습니다.
|
||||
|
||||
독스트링에는 <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>을 작성할 수 있으며, (독스트링의 들여쓰기를 고려하여) 올바르게 해석되고 표시됩니다.
|
||||
|
||||
|
|
@ -90,9 +90,9 @@ OpenAPI는 각 *경로 처리*가 응답에 관한 설명을 요구할 것을
|
|||
|
||||
## *경로 처리* 지원중단하기 { #deprecate-a-path-operation }
|
||||
|
||||
*경로 처리*를 제거하지 않고 <abbr title="구식이며 사용하지 않는 것이 권장됨">deprecated</abbr>로 표시해야 한다면, `deprecated` 매개변수를 전달하면 됩니다:
|
||||
*경로 처리*를 제거하지 않고 <dfn title="구식이며 사용하지 않는 것이 권장됨">지원중단</dfn>으로 표시해야 한다면, `deprecated` 매개변수를 전달하면 됩니다:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
|
||||
|
||||
대화형 문서에서 지원중단으로 명확하게 표시됩니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,11 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
|
||||
따라서 함수를 다음과 같이 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *}
|
||||
|
||||
하지만 `Annotated`를 사용하면 이 문제가 없다는 점을 기억하세요. `Query()`나 `Path()`에 함수 매개변수 기본값을 사용하지 않기 때문에, 순서는 중요하지 않습니다.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *}
|
||||
|
||||
## 필요한 대로 매개변수 정렬하기, 트릭 { #order-the-parameters-as-you-need-tricks }
|
||||
|
||||
|
|
@ -83,13 +83,13 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
|
||||
파이썬은 `*`으로 아무것도 하지 않지만, 뒤따르는 모든 매개변수는 키워드 인자(키-값 쌍)로 호출되어야 함을 알게 됩니다. 이는 <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>로도 알려져 있습니다. 기본값이 없더라도 마찬가지입니다.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
|
||||
|
||||
### `Annotated`를 쓰면 더 좋습니다 { #better-with-annotated }
|
||||
|
||||
`Annotated`를 사용하면 함수 매개변수 기본값을 사용하지 않기 때문에 이 문제가 발생하지 않으며, 아마 `*`도 사용할 필요가 없다는 점을 기억하세요.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *}
|
||||
|
||||
## 숫자 검증: 크거나 같음 { #number-validations-greater-than-or-equal }
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
|
||||
여기서 `ge=1`인 경우, `item_id`는 `1`보다 "`g`reater than or `e`qual"(크거나 같은) 정수형 숫자여야 합니다.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *}
|
||||
|
||||
## 숫자 검증: 크거나 및 작거나 같음 { #number-validations-greater-than-and-less-than-or-equal }
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
* `gt`: `g`reater `t`han
|
||||
* `le`: `l`ess than or `e`qual
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *}
|
||||
|
||||
## 숫자 검증: 부동소수, 크거나 및 작거나 { #number-validations-floats-greater-than-and-less-than }
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
|
||||
<abbr title="less than"><code>lt</code></abbr> 역시 마찬가지입니다.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
|
||||
|
||||
## 요약 { #recap }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
파이썬의 포맷 문자열 리터럴에서 사용되는 문법을 이용하여 경로 "매개변수" 또는 "변수"를 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
|
||||
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
|
||||
|
||||
경로 매개변수 `item_id`의 값은 함수의 `item_id` 인자로 전달됩니다.
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
파이썬 표준 타입 어노테이션을 사용하여 함수에 있는 경로 매개변수의 타입을 선언할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
|
||||
|
||||
위의 예시에서, `item_id`는 `int`로 선언되었습니다.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
///
|
||||
|
||||
## 데이터 <abbr title="다음으로도 알려져 있습니다: 직렬화, 파싱, 마샬링">변환</abbr> { #data-conversion }
|
||||
## 데이터 <dfn title="다음으로도 알려져 있습니다: 직렬화, 파싱, 마샬링">변환</dfn> { #data-conversion }
|
||||
|
||||
이 예제를 실행하고 <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>을 열면, 다음 응답을 볼 수 있습니다:
|
||||
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
함수가 받은(반환도 하는) 값은 문자열 `"3"`이 아니라 파이썬 `int` 형인 `3`입니다.
|
||||
|
||||
즉, 타입 선언을 하면 **FastAPI**는 자동으로 요청을 <abbr title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">"파싱"</abbr>합니다.
|
||||
즉, 타입 선언을 하면 **FastAPI**는 자동으로 요청을 <dfn title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">"파싱"</dfn>합니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -116,21 +116,21 @@
|
|||
|
||||
사용자 ID를 이용해 특정 사용자의 정보를 가져오는 경로 `/users/{user_id}`도 있습니다.
|
||||
|
||||
*경로 처리*는 순차적으로 평가되기 때문에 `/users/{user_id}` 이전에 `/users/me`에 대한 경로가 먼저 선언되었는지 확인해야 합니다:
|
||||
*경로 처리*는 순차적으로 평가되기 때문에 `/users/me`에 대한 경로가 `/users/{user_id}` 이전에 먼저 선언되었는지 확인해야 합니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
|
||||
|
||||
그렇지 않으면 `/users/{user_id}`에 대한 경로가 `/users/me`에도 매칭되어, 매개변수 `user_id`에 `"me"` 값이 들어왔다고 "생각하게" 됩니다.
|
||||
|
||||
마찬가지로, 경로 처리를 재정의할 수는 없습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
|
||||
|
||||
경로가 먼저 매칭되기 때문에 첫 번째 것이 항상 사용됩니다.
|
||||
|
||||
## 사전정의 값 { #predefined-values }
|
||||
|
||||
만약 *경로 매개변수*를 받는 *경로 처리*가 있지만, 가능한 유효한 *경로 매개변수* 값들을 미리 정의하고 싶다면 파이썬 표준 <abbr title="열거형(Enumeration)">`Enum`</abbr>을 사용할 수 있습니다.
|
||||
만약 *경로 매개변수*를 받는 *경로 처리*가 있지만, 가능한 유효한 *경로 매개변수* 값들을 미리 정의하고 싶다면 파이썬 표준 <abbr title="열거형">`Enum`</abbr>을 사용할 수 있습니다.
|
||||
|
||||
### `Enum` 클래스 생성 { #create-an-enum-class }
|
||||
|
||||
|
|
@ -140,11 +140,11 @@
|
|||
|
||||
가능한 값들에 해당하는 고정된 값의 클래스 어트리뷰트들을 만듭니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
혹시 궁금하다면, "AlexNet", "ResNet", 그리고 "LeNet"은 그저 머신 러닝 <abbr title="기술적으로는 딥 러닝 모델 아키텍처">모델</abbr>들의 이름입니다.
|
||||
혹시 궁금하다면, "AlexNet", "ResNet", 그리고 "LeNet"은 그저 머신 러닝 <dfn title="기술적으로는 딥 러닝 모델 아키텍처">모델</dfn>들의 이름입니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
|
||||
생성한 열거형 클래스(`ModelName`)를 사용하는 타입 어노테이션으로 *경로 매개변수*를 만듭니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
|
||||
|
||||
### 문서 확인 { #check-the-docs }
|
||||
|
||||
|
|
@ -168,13 +168,13 @@
|
|||
|
||||
생성한 열거형 `ModelName`의 *열거형 멤버*와 비교할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
|
||||
|
||||
#### *열거형 값* 가져오기 { #get-the-enumeration-value }
|
||||
|
||||
`model_name.value` 또는 일반적으로 `your_enum_member.value`를 이용하여 실제 값(위 예시의 경우 `str`)을 가져올 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -188,7 +188,7 @@
|
|||
|
||||
클라이언트에 반환하기 전에 해당 값(이 경우 문자열)으로 변환됩니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
|
||||
|
||||
클라이언트는 아래와 같은 JSON 응답을 얻게 됩니다:
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ Starlette의 옵션을 직접 이용하여 다음과 같은 URL을 사용함으
|
|||
|
||||
따라서 다음과 같이 사용할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ Starlette의 옵션을 직접 이용하여 다음과 같은 URL을 사용함으
|
|||
**FastAPI**를 이용하면 짧고 직관적인 표준 파이썬 타입 선언을 사용하여 다음을 얻을 수 있습니다:
|
||||
|
||||
* 편집기 지원: 오류 검사, 자동완성 등
|
||||
* 데이터 "<abbr title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">parsing</abbr>"
|
||||
* 데이터 "<dfn title="HTTP 요청에서 전달되는 문자열을 파이썬 데이터로 변환">파싱</dfn>"
|
||||
* 데이터 검증
|
||||
* API 주석(Annotation)과 자동 문서
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
**FastAPI**를 사용하면 매개변수에 대한 추가 정보 및 검증을 선언할 수 있습니다.
|
||||
|
||||
이 응용 프로그램을 예로 들어보겠습니다:
|
||||
이 애플리케이션을 예로 들어보겠습니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
|
||||
|
||||
|
|
@ -41,46 +41,22 @@ FastAPI는 0.95.0 버전에서 `Annotated` 지원을 추가했고(그리고 이
|
|||
|
||||
## `q` 매개변수의 타입에 `Annotated` 사용하기 { #use-annotated-in-the-type-for-the-q-parameter }
|
||||
|
||||
이전에 [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}에서 `Annotated`를 사용해 매개변수에 메타데이터를 추가할 수 있다고 말씀드린 것을 기억하시나요?
|
||||
이전에 [Python 타입 소개](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}에서 `Annotated`를 사용해 매개변수에 메타데이터를 추가할 수 있다고 말씀드린 것을 기억하시나요?
|
||||
|
||||
이제 FastAPI에서 사용할 차례입니다. 🚀
|
||||
|
||||
다음과 같은 타입 어노테이션이 있었습니다:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
여기서 `Annotated`로 감싸서 다음과 같이 만듭니다:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
q: Annotated[str | None] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
q: Annotated[Union[str, None]] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
두 버전 모두 같은 의미로, `q`는 `str` 또는 `None`이 될 수 있는 매개변수이며 기본값은 `None`입니다.
|
||||
|
||||
이제 재미있는 부분으로 넘어가 봅시다. 🎉
|
||||
|
|
@ -109,7 +85,7 @@ q: Annotated[Union[str, None]] = None
|
|||
|
||||
## 대안(이전 방식): 기본값으로 `Query` 사용 { #alternative-old-query-as-the-default-value }
|
||||
|
||||
이전 FastAPI 버전(<abbr title="before 2023-03">0.95.0</abbr> 이전)에서는 `Annotated`에 넣는 대신, 매개변수의 기본값으로 `Query`를 사용해야 했습니다. 주변에서 이 방식을 사용하는 코드를 볼 가능성이 높기 때문에 설명해 드리겠습니다.
|
||||
이전 FastAPI 버전(<dfn title="2023-03 이전">0.95.0</dfn> 이전)에서는 `Annotated`에 넣는 대신, 매개변수의 기본값으로 `Query`를 사용해야 했습니다. 주변에서 이 방식을 사용하는 코드를 볼 가능성이 높기 때문에 설명해 드리겠습니다.
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -192,7 +168,7 @@ FastAPI 없이도 **다른 곳에서** 같은 함수를 **호출**할 수 있고
|
|||
|
||||
## 정규식 추가 { #add-regular-expressions }
|
||||
|
||||
매개변수와 일치해야 하는 <abbr title="문자열에 대한 검색 패턴을 정의하는 문자들의 순열인 정규 표현식(regular expression), regex 또는 regexp입니다.">정규 표현식</abbr> `pattern`을 정의할 수 있습니다:
|
||||
매개변수와 일치해야 하는 <dfn title="정규 표현식(regex 또는 regexp)은 문자열에 대한 검색 패턴을 정의하는 문자 시퀀스입니다.">정규 표현식</dfn> `pattern`을 정의할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
|
||||
|
||||
|
|
@ -212,7 +188,7 @@ FastAPI 없이도 **다른 곳에서** 같은 함수를 **호출**할 수 있고
|
|||
|
||||
`q` 쿼리 매개변수에 `min_length`를 `3`으로 설정하고, 기본값을 `"fixedquery"`로 선언하고 싶다고 해봅시다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None
|
|||
|
||||
따라서 `Query`를 사용하면서 값을 필수로 선언해야 할 때는, 기본값을 선언하지 않으면 됩니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *}
|
||||
|
||||
### 필수지만 `None` 가능 { #required-can-be-none }
|
||||
|
||||
|
|
@ -293,7 +269,7 @@ http://localhost:8000/items/?q=foo&q=bar
|
|||
|
||||
제공된 값이 없으면 기본 `list` 값을 정의할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *}
|
||||
|
||||
다음으로 이동하면:
|
||||
|
||||
|
|
@ -316,7 +292,7 @@ http://localhost:8000/items/
|
|||
|
||||
`list[str]` 대신 `list`를 직접 사용할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -372,7 +348,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
|
|||
|
||||
이제는 더 이상 이 매개변수를 마음에 들어하지 않는다고 가정해 봅시다.
|
||||
|
||||
이 매개변수를 사용하는 클라이언트가 있기 때문에 한동안은 남겨둬야 하지만, 문서에서 <abbr title="obsolete, recommended not to use it – 구식이며, 사용하지 않는 것을 추천">deprecated</abbr>로 명확하게 보여주고 싶습니다.
|
||||
이 매개변수를 사용하는 클라이언트가 있기 때문에 한동안은 남겨둬야 하지만, 문서에서 <dfn title="구식이며, 사용하지 않기를 권장함">사용 중단됨</dfn>으로 명확하게 보여주고 싶습니다.
|
||||
|
||||
그렇다면 `deprecated=True` 매개변수를 `Query`로 전달합니다:
|
||||
|
||||
|
|
@ -402,7 +378,7 @@ Pydantic에는 <a href="https://docs.pydantic.dev/latest/concepts/validators/#fi
|
|||
|
||||
///
|
||||
|
||||
예를 들어, 이 커스텀 validator는 <abbr title="ISBN means International Standard Book Number – 국제 표준 도서 번호">ISBN</abbr> 도서 번호의 경우 아이템 ID가 `isbn-`으로 시작하고, <abbr title="IMDB (Internet Movie Database) is a website with information about movies – 영화에 대한 정보를 제공하는 웹사이트">IMDB</abbr> 영화 URL ID의 경우 `imdb-`로 시작하는지 확인합니다:
|
||||
예를 들어, 이 커스텀 validator는 <abbr title="International Standard Book Number - 국제 표준 도서 번호">ISBN</abbr> 도서 번호의 경우 아이템 ID가 `isbn-`으로 시작하고, <abbr title="Internet Movie Database - 인터넷 영화 데이터베이스: 영화에 대한 정보를 제공하는 웹사이트">IMDB</abbr> 영화 URL ID의 경우 `imdb-`로 시작하는지 확인합니다:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
|
||||
|
||||
|
|
@ -436,9 +412,9 @@ Pydantic에는 <a href="https://docs.pydantic.dev/latest/concepts/validators/#fi
|
|||
|
||||
#### 임의의 항목 { #a-random-item }
|
||||
|
||||
`data.items()`를 사용하면 각 딕셔너리 항목의 키와 값을 담은 튜플로 구성된 <abbr title="리스트, 세트 등처럼 for 루프로 순회할 수 있는 것">iterable object</abbr>를 얻습니다.
|
||||
`data.items()`를 사용하면 각 딕셔너리 항목의 키와 값을 담은 튜플로 구성된 <dfn title="리스트, 세트 등처럼 for 루프로 순회할 수 있는 것">이터러블 객체</dfn>를 얻습니다.
|
||||
|
||||
이 iterable object를 `list(data.items())`로 적절한 `list`로 변환합니다.
|
||||
이 이터러블 객체를 `list(data.items())`로 적절한 `list`로 변환합니다.
|
||||
|
||||
그 다음 `random.choice()`로 리스트에서 **무작위 값**을 얻어 `(id, name)` 형태의 튜플을 얻습니다. 예를 들어 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` 같은 값이 될 것입니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
경로 매개변수의 일부가 아닌 다른 함수 매개변수를 선언하면 "쿼리" 매개변수로 자동 해석합니다.
|
||||
|
||||
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
|
||||
|
||||
쿼리는 URL에서 `?` 후에 나오고 `&`으로 구분되는 키-값 쌍의 집합입니다.
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ URL의 일부이므로 "자연스럽게" 문자열입니다.
|
|||
경로 매개변수에 적용된 동일한 프로세스가 쿼리 매개변수에도 적용됩니다:
|
||||
|
||||
* (당연히) 편집기 지원
|
||||
* 데이터 <abbr title="converting the string that comes from an HTTP request into Python data">"파싱"</abbr>
|
||||
* 데이터 <dfn title="HTTP 요청에서 온 문자열을 Python 데이터로 변환하는 것">"파싱"</dfn>
|
||||
* 데이터 검증
|
||||
* 자동 문서화
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ http://127.0.0.1:8000/items/foo?short=yes
|
|||
|
||||
그러나 쿼리 매개변수를 필수로 만들려면 단순히 기본값을 선언하지 않으면 됩니다:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
|
||||
{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
|
||||
|
||||
여기 쿼리 매개변수 `needy`는 `str`형인 필수 쿼리 매개변수입니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ $ pip install python-multipart
|
|||
|
||||
`fastapi` 에서 `File` 과 `UploadFile` 을 임포트 합니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## `File` 매개변수 정의 { #define-file-parameters }
|
||||
|
||||
`Body` 및 `Form` 과 동일한 방식으로 파일의 매개변수를 생성합니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
/// info | 정보
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ File의 본문을 선언할 때, 매개변수가 쿼리 매개변수 또는 본
|
|||
|
||||
`File` 매개변수를 `UploadFile` 타입으로 정의합니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *}
|
||||
|
||||
`UploadFile` 을 사용하는 것은 `bytes` 과 비교해 다음과 같은 장점이 있습니다:
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ HTML의 폼들(`<form></form>`)이 서버에 데이터를 전송하는 방식은
|
|||
|
||||
하지만 파일이 포함된 경우, `multipart/form-data`로 인코딩됩니다. `File`을 사용하였다면, **FastAPI**는 본문의 적합한 부분에서 파일을 가져와야 한다는 것을 인지합니다.
|
||||
|
||||
인코딩과 폼 필드에 대해 더 알고싶다면, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>를 참고하기 바랍니다.
|
||||
인코딩과 폼 필드에 대해 더 알고싶다면, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - 모질라 개발자 네트워크">MDN</abbr> web docs for <code>POST</code></a>를 참고하기 바랍니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ HTML의 폼들(`<form></form>`)이 서버에 데이터를 전송하는 방식은
|
|||
|
||||
추가 메타데이터를 설정하기 위해 예를 들어 `UploadFile`과 함께 `File()`을 사용할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
|
||||
{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *}
|
||||
|
||||
## 다중 파일 업로드 { #multiple-file-uploads }
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ HTML의 폼들(`<form></form>`)이 서버에 데이터를 전송하는 방식은
|
|||
|
||||
이 기능을 사용하기 위해 , `bytes` 의 `List` 또는 `UploadFile` 를 선언하기 바랍니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
|
||||
{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *}
|
||||
|
||||
선언한대로, `bytes` 의 `list` 또는 `UploadFile` 들을 전송받을 것입니다.
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ HTML의 폼들(`<form></form>`)이 서버에 데이터를 전송하는 방식은
|
|||
|
||||
이전과 같은 방식으로 `UploadFile`에 대해서도 `File()`을 사용해 추가 매개변수를 설정할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
|
||||
{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *}
|
||||
|
||||
## 요약 { #recap }
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ $ pip install python-multipart
|
|||
|
||||
**폼 필드**로 받고 싶은 필드를 **Pydantic 모델**로 선언한 다음, 매개변수를 `Form`으로 선언하면 됩니다:
|
||||
|
||||
{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
|
||||
{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *}
|
||||
|
||||
**FastAPI**는 요청에서 받은 **폼 데이터**에서 **각 필드**에 대한 데이터를 **추출**하고 정의한 Pydantic 모델을 줍니다.
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ $ pip install python-multipart
|
|||
|
||||
Pydantic의 모델 구성을 사용하여 `extra` 필드를 `forbid`할 수 있습니다:
|
||||
|
||||
{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *}
|
||||
|
||||
클라이언트가 추가 데이터를 보내려고 하면 **오류** 응답을 받게 됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ $ pip install python-multipart
|
|||
|
||||
## `File` 및 `Form` 임포트 { #import-file-and-form }
|
||||
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## `File` 및 `Form` 매개변수 정의 { #define-file-and-form-parameters }
|
||||
|
||||
`Body` 및 `Query`와 동일한 방식으로 파일과 폼의 매개변수를 생성합니다:
|
||||
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *}
|
||||
|
||||
파일과 폼 필드는 폼 데이터로 업로드되며, 파일과 폼 필드를 받게 됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,17 +18,17 @@ $ pip install python-multipart
|
|||
|
||||
`fastapi`에서 `Form`을 임포트합니다:
|
||||
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## `Form` 매개변수 정의하기 { #define-form-parameters }
|
||||
|
||||
`Body` 또는 `Query`와 동일한 방식으로 폼 매개변수를 만듭니다:
|
||||
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
예를 들어, OAuth2 사양을 사용할 수 있는 방법 중 하나("패스워드 플로우"라고 함)로 `username`과 `password`를 폼 필드로 보내야 합니다.
|
||||
|
||||
<abbr title="specification">spec</abbr>에서는 필드 이름이 `username` 및 `password`로 정확하게 명명되어야 하고, JSON이 아닌 폼 필드로 전송해야 합니다.
|
||||
<dfn title="사양">사양</dfn>에서는 필드 이름이 `username` 및 `password`로 정확하게 명명되어야 하고, JSON이 아닌 폼 필드로 전송해야 합니다.
|
||||
|
||||
`Form`을 사용하면 유효성 검사, 예제, 별칭(예: `username` 대신 `user-name`) 등을 포함하여 `Body`(및 `Query`, `Path`, `Cookie`)와 동일한 구성을 선언할 수 있습니다.
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ HTML 폼(`<form></form>`)이 데이터를 서버로 보내는 방식은 일반
|
|||
|
||||
그러나 폼에 파일이 포함된 경우, `multipart/form-data`로 인코딩합니다. 다음 장에서 파일 처리에 대해 읽을 겁니다.
|
||||
|
||||
이러한 인코딩 및 폼 필드에 대해 더 읽고 싶다면, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><code>POST</code>에 대한 <abbr title="Mozilla Developer Network">MDN</abbr> 웹 문서를 참조하세요</a>.
|
||||
이러한 인코딩 및 폼 필드에 대해 더 읽고 싶다면, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - Mozilla 개발자 네트워크">MDN</abbr> 웹 문서를 참조하세요 <code>POST</code>에 대한</a>.
|
||||
|
||||
///
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래
|
|||
|
||||
가장 흔한 경우는 [고급 문서에서 나중에 설명하는 대로 Response를 직접 반환하는 것](../advanced/response-directly.md){.internal-link target=_blank}입니다.
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
|
||||
{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
|
||||
|
||||
이 간단한 경우는 반환 타입 어노테이션이 `Response` 클래스(또는 그 서브클래스)이기 때문에 FastAPI에서 자동으로 처리됩니다.
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래
|
|||
|
||||
타입 어노테이션에 `Response`의 서브클래스를 사용할 수도 있습니다:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
|
||||
{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *}
|
||||
|
||||
이는 `RedirectResponse`가 `Response`의 서브클래스이기 때문에 동작하며, FastAPI가 이 간단한 경우를 자동으로 처리합니다.
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래
|
|||
|
||||
하지만 유효한 Pydantic 타입이 아닌 다른 임의의 객체(예: 데이터베이스 객체)를 반환하고, 함수에서 그렇게 어노테이션하면, FastAPI는 그 타입 어노테이션으로부터 Pydantic 응답 모델을 만들려고 시도하다가 실패합니다.
|
||||
|
||||
또한, 유효한 Pydantic 타입이 아닌 타입이 하나 이상 포함된 여러 타입 간의 <abbr title='여러 타입 간 union은 "이 타입들 중 아무거나"를 의미합니다.'>union</abbr>이 있는 경우에도 동일합니다. 예를 들어, 아래는 실패합니다 💥:
|
||||
또한, 유효한 Pydantic 타입이 아닌 타입이 하나 이상 포함된 여러 타입 간의 <dfn title="여러 타입 간의 union은 '이 타입들 중 아무거나'를 의미합니다.">union</dfn>이 있는 경우에도 동일합니다. 예를 들어, 아래는 실패합니다 💥:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* `@app.delete()`
|
||||
* 등
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
|
||||
|
||||
/// note | 참고
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ FastAPI는 이를 알고 있으며, 응답 본문이 없다고 명시하는 Open
|
|||
|
||||
/// note | 참고
|
||||
|
||||
만약 HTTP 상태 코드가 무엇인지 이미 알고 있다면, 다음 섹션으로 넘어가세요.
|
||||
만약 HTTP 상태 코드가 무엇인지 이미 알고 있다면, 다음 섡션으로 넘어가세요.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ HTTP에서는 응답의 일부로 3자리 숫자 상태 코드를 보냅니다.
|
|||
|
||||
/// tip | 팁
|
||||
|
||||
각 상태 코드와 어떤 코드가 어떤 용도인지 더 알고 싶다면 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr>의 HTTP 상태 코드에 관한 문서</a>를 확인하세요.
|
||||
각 상태 코드와 어떤 코드가 어떤 용도인지 더 알고 싶다면 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - 모질라 개발자 네트워크">MDN</abbr>의 HTTP 상태 코드에 관한 문서</a>를 확인하세요.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ HTTP에서는 응답의 일부로 3자리 숫자 상태 코드를 보냅니다.
|
|||
|
||||
이전 예시를 다시 확인해보겠습니다:
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
|
||||
|
||||
`201` 은 "생성됨"을 위한 상태 코드입니다.
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ HTTP에서는 응답의 일부로 3자리 숫자 상태 코드를 보냅니다.
|
|||
|
||||
`fastapi.status` 의 편의 변수를 사용할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
|
||||
|
||||
이것들은 단지 편의를 위한 것으로, 동일한 숫자를 갖고 있지만, 이를 통해 편집기의 자동완성 기능으로 찾을 수 있습니다:
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Pydantic 모델과 같이 `Field()`를 사용할 때 추가적인 `examples`를
|
|||
|
||||
이와 같이 하면 예제들은 그 본문 데이터의 내부 **JSON 스키마**의 일부가 될 것입니다.
|
||||
|
||||
그럼에도 불구하고, 지금 <abbr title="2023-08-26">이 문서를 작성하는 시간</abbr>에, 문서 UI를 보여주는 역할을 맡은 Swagger UI는 **JSON 스키마** 속 데이터를 위한 여러 예제의 표현을 지원하지 않습니다. 하지만 해결 방안을 밑에서 읽어보세요.
|
||||
그럼에도 불구하고, 지금 <dfn title="2023-08-26">이 문서를 작성하는 시간</dfn>에, 문서 UI를 보여주는 역할을 맡은 Swagger UI는 **JSON 스키마** 속 데이터를 위한 여러 예제의 표현을 지원하지 않습니다. 하지만 해결 방안을 밑에서 읽어보세요.
|
||||
|
||||
### OpenAPI-특화 `examples` { #openapi-specific-examples }
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
예제를 파일 `main.py`에 복사하세요:
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py *}
|
||||
|
||||
## 실행하기 { #run-it }
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ OAuth2는 backend 또는 API가 사용자를 인증하는 서버와 독립적일
|
|||
|
||||
`OAuth2PasswordBearer` 클래스의 인스턴스를 만들 때 `tokenUrl` 파라미터를 전달합니다. 이 파라미터에는 클라이언트(사용자의 브라우저에서 실행되는 frontend)가 token을 받기 위해 `username`과 `password`를 보낼 URL이 들어 있습니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ oauth2_scheme(some, parameters)
|
|||
|
||||
이제 `Depends`로 `oauth2_scheme`를 의존성에 전달할 수 있습니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
|
||||
|
||||
이 의존성은 `str`을 제공하고, 그 값은 *경로 처리 함수*의 파라미터 `token`에 할당됩니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
이전 장에서 (의존성 주입 시스템을 기반으로 한) 보안 시스템은 *경로 처리 함수*에 `str`로 `token`을 제공했습니다:
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
|
||||
|
||||
하지만 이는 여전히 그다지 유용하지 않습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# 패스워드(해싱 포함)를 사용하는 OAuth2, JWT 토큰을 사용하는 Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
|
||||
|
||||
모든 보안 흐름을 구성했으므로, 이제 <abbr title="JSON Web Tokens">JWT</abbr> 토큰과 안전한 패스워드 해싱을 사용해 애플리케이션을 실제로 안전하게 만들겠습니다.
|
||||
모든 보안 흐름을 구성했으므로, 이제 <abbr title="JSON 웹 토큰">JWT</abbr> 토큰과 안전한 패스워드 해싱을 사용해 애플리케이션을 실제로 안전하게 만들겠습니다.
|
||||
|
||||
이 코드는 실제로 애플리케이션에서 사용할 수 있으며, 패스워드 해시를 데이터베이스에 저장하는 등의 작업에 활용할 수 있습니다.
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ $ pip install pyjwt
|
|||
|
||||
</div>
|
||||
|
||||
/// info
|
||||
/// info | 정보
|
||||
|
||||
RSA나 ECDSA 같은 전자 서명 알고리즘을 사용할 계획이라면, cryptography 라이브러리 의존성인 `pyjwt[crypto]`를 설치해야 합니다.
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ $ pip install "pwdlib[argon2]"
|
|||
|
||||
</div>
|
||||
|
||||
/// tip
|
||||
/// tip | 팁
|
||||
|
||||
`pwdlib`를 사용하면 **Django**, **Flask** 보안 플러그인 또는 다른 여러 도구로 생성한 패스워드를 읽을 수 있도록 설정할 수도 있습니다.
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ $ pip install "pwdlib[argon2]"
|
|||
|
||||
권장 설정으로 PasswordHash 인스턴스를 생성합니다. 이는 패스워드를 해싱하고 검증하는 데 사용됩니다.
|
||||
|
||||
/// tip
|
||||
/// tip | 팁
|
||||
|
||||
pwdlib는 bcrypt 해싱 알고리즘도 지원하지만 레거시 알고리즘은 포함하지 않습니다. 오래된 해시로 작업해야 한다면 passlib 라이브러리를 사용하는 것을 권장합니다.
|
||||
|
||||
|
|
@ -116,9 +116,13 @@ pwdlib는 bcrypt 해싱 알고리즘도 지원하지만 레거시 알고리즘
|
|||
|
||||
그리고 사용자를 인증하고 반환하는 또 다른 함수도 생성합니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *}
|
||||
|
||||
/// note
|
||||
`authenticate_user`가 데이터베이스에 존재하지 않는 사용자이름으로 호출되더라도, 여전히 `verify_password`를 더미 해시에 대해 실행합니다.
|
||||
|
||||
이렇게 하면 사용자이름이 유효하든 아니든 엔드포인트가 응답하는 데 걸리는 시간이 대략 동일해져, 기존 사용자이름을 열거하는 데 악용될 수 있는 **타이밍 공격**을 방지합니다.
|
||||
|
||||
/// note | 참고
|
||||
|
||||
새로운 (가짜) 데이터베이스 `fake_users_db`를 확인하면, 이제 해시 처리된 패스워드가 어떻게 생겼는지 볼 수 있습니다: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`.
|
||||
|
||||
|
|
@ -152,7 +156,7 @@ JWT 토큰을 서명하는 데 사용될 알고리즘을 위한 변수 `ALGORITH
|
|||
|
||||
새 액세스 토큰을 생성하기 위한 유틸리티 함수를 생성합니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *}
|
||||
|
||||
## 의존성 업데이트 { #update-the-dependencies }
|
||||
|
||||
|
|
@ -162,7 +166,7 @@ JWT 토큰을 서명하는 데 사용될 알고리즘을 위한 변수 `ALGORITH
|
|||
|
||||
토큰이 유효하지 않다면 즉시 HTTP 오류를 반환합니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *}
|
||||
|
||||
## `/token` *경로 처리* 업데이트 { #update-the-token-path-operation }
|
||||
|
||||
|
|
@ -170,7 +174,7 @@ JWT 토큰을 서명하는 데 사용될 알고리즘을 위한 변수 `ALGORITH
|
|||
|
||||
실제 JWT 액세스 토큰을 생성하여 반환합니다.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *}
|
||||
|
||||
### JWT "주체(subject)" `sub`에 대한 기술 세부사항 { #technical-details-about-the-jwt-subject-sub }
|
||||
|
||||
|
|
@ -209,7 +213,7 @@ JWT는 사용자를 식별하고 사용자가 API에서 직접 작업을 수행
|
|||
Username: `johndoe`
|
||||
Password: `secret`
|
||||
|
||||
/// check
|
||||
/// check | 확인
|
||||
|
||||
코드 어디에도 평문 패스워드 "`secret`"은 없고, 해시된 버전만 있다는 점에 유의하십시오.
|
||||
|
||||
|
|
@ -234,7 +238,7 @@ Password: `secret`
|
|||
|
||||
<img src="/img/tutorial/security/image10.png">
|
||||
|
||||
/// note
|
||||
/// note | 참고
|
||||
|
||||
`Bearer `로 시작하는 값을 가진 `Authorization` 헤더에 주목하십시오.
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ UserInDB(
|
|||
|
||||
/// tip | 팁
|
||||
|
||||
다음 장에서는 패스워드 해싱 및 <abbr title="JSON Web Tokens">JWT</abbr> 토큰을 사용하여 실제 보안 구현을 볼 수 있습니다.
|
||||
다음 장에서는 패스워드 해싱 및 <abbr title="JSON Web Tokens - JSON 웹 토큰">JWT</abbr> 토큰을 사용하여 실제 보안 구현을 볼 수 있습니다.
|
||||
|
||||
하지만 지금은 필요한 세부 정보에 집중하겠습니다.
|
||||
|
||||
|
|
@ -286,4 +286,4 @@ UserInDB(
|
|||
|
||||
유일한 오점은 아직 실제로 "안전"하지 않다는 것입니다.
|
||||
|
||||
다음 장에서는 안전한 패스워드 해싱 라이브러리와 <abbr title="JSON Web Tokens">JWT</abbr> 토큰을 사용하는 방법을 살펴보겠습니다.
|
||||
다음 장에서는 안전한 패스워드 해싱 라이브러리와 <abbr title="JSON Web Tokens - JSON 웹 토큰">JWT</abbr> 토큰을 사용하는 방법을 살펴보겠습니다.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/// tip | 팁
|
||||
|
||||
다른 SQL 또는 NoSQL 데이터베이스 라이브러리를 사용할 수도 있습니다 (일부는 <abbr title="Object Relational Mapper: a fancy term for a library where some classes represent SQL tables and instances represent rows in those tables">"ORMs"</abbr>이라고도 불립니다), FastAPI는 특정 라이브러리의 사용을 강요하지 않습니다. 😎
|
||||
다른 SQL 또는 NoSQL 데이터베이스 라이브러리를 사용할 수도 있습니다 (일부는 <abbr title="Object Relational Mapper - 객체-관계 매퍼: 일부 클래스는 SQL 테이블을, 인스턴스는 해당 테이블의 행을 나타내는 라이브러리를 가리키는 용어">"ORMs"</abbr>이라고도 불립니다), FastAPI는 특정 라이브러리의 사용을 강요하지 않습니다. 😎
|
||||
|
||||
///
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* `StaticFiles`를 임포트합니다.
|
||||
* 특정 경로에 `StaticFiles()` 인스턴스를 "마운트"합니다.
|
||||
|
||||
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *}
|
||||
|
||||
/// note | 기술 세부사항
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a> 덕분에 **FastAPI** 애플리케이션을 테스트하는 일은 쉽고 즐거운 일이 되었습니다.
|
||||
|
||||
Starlette는 <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>를 기반으로 하며, 이는 Requests를 기반으로 설계되었기 때문에 매우 친숙하고 직관적입니다.
|
||||
이는 <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>를 기반으로 하며, 이는 Requests를 기반으로 설계되었기 때문에 매우 친숙하고 직관적입니다.
|
||||
|
||||
이를 사용하면 **FastAPI**에서 <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a>를 직접 사용할 수 있습니다.
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ $ pip install httpx
|
|||
|
||||
표준적인 파이썬 표현식으로 확인이 필요한 곳에 간단한 `assert` 문장을 작성하세요(역시 표준적인 `pytest` 관례입니다).
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
|
||||
{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}
|
||||
|
||||
/// tip | 팁
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ $ pip install httpx
|
|||
|
||||
///
|
||||
|
||||
/// note Technical Details | 기술 세부사항
|
||||
/// note | 기술 세부사항
|
||||
|
||||
`from starlette.testclient import TestClient` 역시 사용할 수 있습니다.
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서
|
|||
`main.py` 파일 안에 **FastAPI** app 을 만들었습니다:
|
||||
|
||||
|
||||
{* ../../docs_src/app_testing/app_a_py39/main.py *}
|
||||
{* ../../docs_src/app_testing/app_a_py310/main.py *}
|
||||
|
||||
### 테스트 파일 { #testing-file }
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서
|
|||
|
||||
파일들이 동일한 패키지에 위치해 있으므로, 상대 임포트를 사용하여 `main` 모듈(`main.py`)에서 `app` 객체를 임포트 해올 수 있습니다.
|
||||
|
||||
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
|
||||
{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
|
||||
|
||||
|
||||
...그리고 이전에 작성했던 것과 같은 테스트 코드를 작성할 수 있습니다.
|
||||
|
|
@ -115,7 +115,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서
|
|||
|
||||
이제 **FastAPI** 앱이 있는 `main.py` 파일에 몇 가지 다른 **경로 처리**가 추가된 경우를 생각해봅시다.
|
||||
|
||||
단일 오류를 반환할 수 있는 `GET` 작업이 있습니다.
|
||||
오류를 반환할 수 있는 `GET` 작업이 있습니다.
|
||||
|
||||
여러 다른 오류를 반환할 수 있는 `POST` 작업이 있습니다.
|
||||
|
||||
|
|
|
|||
|
|
@ -37,15 +37,15 @@ Python 설치까지 포함해 **모든 것을 관리해주는 도구**를 도입
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Go to the home directory
|
||||
// 홈 디렉터리로 이동
|
||||
$ cd
|
||||
// Create a directory for all your code projects
|
||||
// 모든 코드 프로젝트를 위한 디렉터리 생성
|
||||
$ mkdir code
|
||||
// Enter into that code directory
|
||||
// 그 code 디렉터리로 이동
|
||||
$ cd code
|
||||
// Create a directory for this project
|
||||
// 이 프로젝트를 위한 디렉터리 생성
|
||||
$ mkdir awesome-project
|
||||
// Enter into that project directory
|
||||
// 그 프로젝트 디렉터리로 이동
|
||||
$ cd awesome-project
|
||||
```
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ $ cd awesome-project
|
|||
|
||||
## 가상 환경 생성 { #create-a-virtual-environment }
|
||||
|
||||
Python 프로젝트를 **처음 시작할 때**, **<abbr title="다른 옵션도 있지만, 이것은 간단한 가이드라인입니다">프로젝트 내부</abbr>**에 가상 환경을 생성하세요.
|
||||
Python 프로젝트를 **처음 시작할 때**, 가상 환경을 **<dfn title="다른 옵션도 있지만, 이것은 간단한 가이드라인입니다">프로젝트 내부</dfn>**에 생성하세요.
|
||||
|
||||
/// tip
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ $ source .venv/Scripts/activate
|
|||
|
||||
해당 환경에 **새 패키지**를 설치할 때마다, 환경을 다시 **활성화**하세요.
|
||||
|
||||
이렇게 하면 해당 패키지가 설치한 **터미널(<abbr title="command line interface">CLI</abbr>) 프로그램**을 사용할 때, 전역으로 설치되어 있을 수도 있는(아마 필요한 버전과는 다른 버전인) 다른 프로그램이 아니라 가상 환경에 있는 것을 사용하게 됩니다.
|
||||
이렇게 하면 해당 패키지가 설치한 **터미널(<abbr title="command line interface - 명령줄 인터페이스">CLI</abbr>) 프로그램**을 사용할 때, 전역으로 설치되어 있을 수도 있는(아마 필요한 버전과는 다른 버전인) 다른 프로그램이 아니라 가상 환경에 있는 것을 사용하게 됩니다.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ Python을 설치하면 컴퓨터에 몇몇 파일이 들어 있는 디렉터리
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Don't run this now, it's just an example 🤓
|
||||
// 지금은 실행하지 마세요, 예시일 뿐입니다 🤓
|
||||
$ pip install "fastapi[standard]"
|
||||
---> 100%
|
||||
```
|
||||
|
|
@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban
|
|||
|
||||
$ python main.py
|
||||
|
||||
// Error importing sirius, it's not installed 😱
|
||||
// sirius 임포트 오류, 설치되어 있지 않습니다 😱
|
||||
Traceback (most recent call last):
|
||||
File "main.py", line 1, in <module>
|
||||
import sirius
|
||||
|
|
@ -826,13 +826,13 @@ Traceback (most recent call last):
|
|||
```console
|
||||
$ cd ~/code/prisoner-of-azkaban
|
||||
|
||||
// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎
|
||||
// 비활성화를 위해 이전 디렉터리에 있을 필요는 없습니다. 어디서든, 다른 프로젝트로 이동한 뒤에도 할 수 있습니다 😎
|
||||
$ deactivate
|
||||
|
||||
// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀
|
||||
// prisoner-of-azkaban/.venv의 가상 환경을 활성화하세요 🚀
|
||||
$ source .venv/bin/activate
|
||||
|
||||
// Now when you run python, it will find the package sirius installed in this virtual environment ✨
|
||||
// 이제 python을 실행하면, 이 가상 환경에 설치된 sirius 패키지를 찾습니다 ✨
|
||||
$ python main.py
|
||||
|
||||
I solemnly swear 🐺
|
||||
|
|
|
|||
Loading…
Reference in New Issue