### `yield`์ `scope`๊ฐ ์๋ ์์กด์ฑ { #dependencies-with-yield-and-scope }
-0.121.0 ๋ฒ์ ์์ FastAPI๋ `yield`๊ฐ ์๋ ์์กด์ฑ์ ๋ํด `Depends(scope="function")` ์ง์์ ์ถ๊ฐํ์ต๋๋ค.
+0.121.0 ๋ฒ์ ์์ FastAPI๋ `Depends(scope="function")` ์ง์์ ์ถ๊ฐํ์ต๋๋ค.
`Depends(scope="function")`๋ฅผ ์ฌ์ฉํ๋ฉด, `yield` ์ดํ์ ์ข
๋ฃ ์ฝ๋๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*๊ฐ ๋๋ ์งํ(ํด๋ผ์ด์ธํธ์ ์๋ต์ด ๋ฐํ๋๊ธฐ ์ )์ ์คํ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ `Depends(scope="request")`(๊ธฐ๋ณธ๊ฐ)๋ฅผ ์ฌ์ฉํ๋ฉด, `yield` ์ดํ์ ์ข
๋ฃ ์ฝ๋๋ ์๋ต์ด ์ ์ก๋ ํ์ ์คํ๋ฉ๋๋ค.
-์์ธํ ๋ด์ฉ์ [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+์์ธํ ๋ด์ฉ์ [`yield`๊ฐ ์๋ ์์กด์ฑ - ์กฐ๊ธฐ ์ข
๋ฃ์ `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
### `yield`๊ฐ ์๋ ์์กด์ฑ๊ณผ `StreamingResponse`, ๊ธฐ์ ์ธ๋ถ์ฌํญ { #dependencies-with-yield-and-streamingresponse-technical-details }
๊ทธ๋ฌ๋ฉด ์ธ์
์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ํด์ ํ์ฌ, ๋ค๋ฅธ ์์ฒญ๋ค์ด ์ด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
-`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ํ์ํ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ `yield`๊ฐ ์๋ ์์กด์ฑ์ ๋ํ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ์ด๋ค ์ ์์ ์ด๋์ด ๋๋์ง๋ฅผ ํฌํจํด <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussion Question</a>์ ์์ฑํด ์ฃผ์ธ์.
+`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ํ์ํ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ `yield`๊ฐ ์๋ ์์กด์ฑ์ ๋ํ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ์ด๋ค ์ ์์ ์ด๋์ด ๋๋์ง๋ฅผ ํฌํจํด <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions ์ง๋ฌธ</a>์ ์์ฑํด ์ฃผ์ธ์.
`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ์ ๋ํ ์ค๋๋ ฅ ์๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์กฐ๊ธฐ ์ข
๋ฃ๋ฅผ ์ ํ์ ์ผ๋ก ํ์ฑํํ ์ ์๋ ์๋ก์ด ๋ฐฉ๋ฒ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ณ ๋ คํ๊ฒ ์ต๋๋ค.
### ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ์ `yield`๊ฐ ์๋ ์์กด์ฑ, ๊ธฐ์ ์ธ๋ถ์ฌํญ { #background-tasks-and-dependencies-with-yield-technical-details }
-FastAPI 0.106.0 ์ด์ ์๋ `yield` ์ดํ์ ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ์ต๋๋ค. `yield`๊ฐ ์๋ ์์กด์ฑ์ ์ข
๋ฃ ์ฝ๋๋ ์๋ต์ด ์ ์ก๋ *ํ์* ์คํ๋์๊ธฐ ๋๋ฌธ์, [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}๊ฐ ์ด๋ฏธ ์คํ๋ ๋ค์์ต๋๋ค.
+FastAPI 0.106.0 ์ด์ ์๋ `yield` ์ดํ์ ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ์ต๋๋ค. `yield`๊ฐ ์๋ ์์กด์ฑ์ ์ข
๋ฃ ์ฝ๋๋ ์๋ต์ด ์ ์ก๋ *ํ์* ์คํ๋์๊ธฐ ๋๋ฌธ์, [์์ธ ํธ๋ค๋ฌ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}๊ฐ ์ด๋ฏธ ์คํ๋ ๋ค์์ต๋๋ค.
์ด๋ ์ฃผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ ์์์ ์์กด์ฑ์ด "yield"ํ ๋์ผํ ๊ฐ์ฒด๋ค์ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ธฐ ์ํ ์ค๊ณ์์ต๋๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ๊ฐ ๋๋ ๋ค์ ์ข
๋ฃ ์ฝ๋๊ฐ ์คํ๋์๊ธฐ ๋๋ฌธ์
๋๋ค.
-# WSGI ํฌํจํ๊ธฐ - Flask, Django ๊ทธ ์ธ { #including-wsgi-flask-django-others }
+# WSGI ํฌํจํ๊ธฐ - Flask, Django ๋ฑ { #including-wsgi-flask-django-others }
-[รฌ\84\9cรซยธ\8c รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจ - รซยง\88รฌ\9aยดรญ\8aยธ](sub-applications.md){.internal-link target=_blank}, [รญ\94\84รซยก\9dรฌ\8b\9c รซ\92ยครญ\8eยธรฌ\97\90รฌ\84\9c](behind-a-proxy.md){.internal-link target=_blank}รฌ\97\90รฌ\84\9c รซยณยดรฌ\95\98รซ\93ยฏรฌ\9dยด WSGI รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจรซ\93ยครฌ\9d\84 รซยง\88รฌ\9aยดรญ\8aยธ ํ ์ ์์ต๋๋ค.
+[รฌ\84\9cรซยธ\8c รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 - รซยง\88รฌ\9aยดรญ\8aยธ](sub-applications.md){.internal-link target=_blank}, [รญ\94\84รซยก\9dรฌ\8b\9c รซ\92ยครฌ\97\90รฌ\84\9c](behind-a-proxy.md){.internal-link target=_blank}รฌ\97\90รฌ\84\9c รซยณยธ รชยฒ\83รฌยฒ\98รซ\9fยผ WSGI รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9d\84 รซยง\88รฌ\9aยดรญ\8aยธํ ์ ์์ต๋๋ค.
-รฌ\9dยดรซยฅยผ รฌ\9c\84รญ\95ยด `WSGIMiddleware`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด WSGI รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจ(์: Flask, Django ๋ฑ)์ ๊ฐ์ ์ ์์ต๋๋ค.
+รฌ\9dยดรซยฅยผ รฌ\9c\84รญ\95ยด `WSGIMiddleware`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด WSGI รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98(์: Flask, Django ๋ฑ)์ ๊ฐ์ ์ ์์ต๋๋ค.
## `WSGIMiddleware` ์ฌ์ฉํ๊ธฐ { #using-wsgimiddleware }
-`WSGIMiddleware`๋ฅผ ๋ถ๋ฌ์์ผ ํฉ๋๋ค.
+/// info | ์ ๋ณด
-๊ทธ๋ฐ ๋ค์, WSGI(์: Flask) ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฏธ๋ค์จ์ด๋ก ํฌ์ฅํฉ๋๋ค.
+์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด `a2wsgi`๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค. ์: `pip install a2wsgi`
-๊ทธ ํ, ํด๋น ๊ฒฝ๋ก์ ๋ง์ดํธํฉ๋๋ค.
+///
-{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
+`a2wsgi`์์ `WSGIMiddleware`๋ฅผ import ํด์ผ ํฉ๋๋ค.
+
+๊ทธ๋ฐ ๋ค์, WSGI(์: Flask) ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฏธ๋ค์จ์ด๋ก ๊ฐ์๋๋ค.
+
+๊ทธ๋ฆฌ๊ณ ํด๋น ๊ฒฝ๋ก์ ๋ง์ดํธํฉ๋๋ค.
+
+{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
+
+/// note | ์ฐธ๊ณ
+
+์ด์ ์ `fastapi.middleware.wsgi`์ `WSGIMiddleware` ์ฌ์ฉ์ ๊ถ์ฅํ์ง๋ง ์ด์ ๋ ๋ ์ด์ ๊ถ์ฅ๋์ง ์์ต๋๋ค.
+
+๋์ `a2wsgi` ํจํค์ง ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค. ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋์ผํฉ๋๋ค.
+
+๋จ, `a2wsgi` ํจํค์ง๊ฐ ์ค์น๋์ด ์๊ณ `a2wsgi`์์ `WSGIMiddleware`๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ import ํ๋์ง๋ง ํ์ธํ์ธ์.
+
+///
## ํ์ธํ๊ธฐ { #check-it }
-รฌ\9dยดรฌย \9c `/v1/` รชยฒยฝรซยก\9cรฌ\97\90 รฌ\9e\88รซ\8a\94 รซยชยจรซ\93ย รฌ\9a\94รฌยฒยญรฌ\9d\80 Flask รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจ์์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
+รฌ\9dยดรฌย \9c `/v1/` รชยฒยฝรซยก\9cรฌ\97\90 รฌ\9e\88รซ\8a\94 รซยชยจรซ\93ย รฌ\9a\94รฌยฒยญรฌ\9d\80 Flask รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง๋ **FastAPI**์ ์ํด ์ฒ๋ฆฌ๋ฉ๋๋ค.
-์คํํ๋ฉด <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>์ผ๋ก ์ด๋ํด์ Flask์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+์คํํ๊ณ <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>๋ก ์ด๋ํ๋ฉด Flask์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```txt
Hello, World from Flask!
```
-๊ทธ๋ฆฌ๊ณ ๋ค์์ผ๋ก ์ด๋ํ๋ฉด <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a> **FastAPI**์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+๊ทธ๋ฆฌ๊ณ <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a>๋ก ์ด๋ํ๋ฉด **FastAPI**์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{
* ๋ค์ ๋ด์ฉ์ผ๋ก `main.py` ํ์ผ์ ๋ง๋ญ๋๋ค:
```Python
-from typing import Union
-
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Union[str, None] = None):
+def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
โ
**Exec** form:
```Dockerfile
-# โ
Do this
+# โ
์ด๋ ๊ฒ ํ์ธ์
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
```
โ๏ธ **Shell** form:
```Dockerfile
-# โ๏ธ Don't do this
+# โ๏ธ ์ด๋ ๊ฒ ํ์ง ๋ง์ธ์
CMD fastapi run app/main.py --port 80
```
## ๋ณต์ - ํ๋ก์ธ์ค ๊ฐ์ { #replication-number-of-processes }
-**Kubernetes**, Docker Swarm Mode, Nomad ๋ฑ์ ๋ณต์กํ ์์คํ
์ผ๋ก ์ฌ๋ฌ ๋จธ์ ์ ๋ถ์ฐ๋ ์ปจํ
์ด๋๋ฅผ ๊ด๋ฆฌํ๋ <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr>๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ๊ฐ ์ปจํ
์ด๋์์(**์์ปค๋ฅผ ์ฌ์ฉํ๋ Uvicorn** ๊ฐ์) **ํ๋ก์ธ์ค ๋งค๋์ **๋ฅผ ์ฐ๋ ๋์ , **ํด๋ฌ์คํฐ ๋ ๋ฒจ**์์ **๋ณต์ ๋ฅผ ์ฒ๋ฆฌ**ํ๊ณ ์ถ์ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
+**Kubernetes**, Docker Swarm Mode, Nomad ๋ฑ์ ๋ณต์กํ ์์คํ
์ผ๋ก ์ฌ๋ฌ ๋จธ์ ์ ๋ถ์ฐ๋ ์ปจํ
์ด๋๋ฅผ ๊ด๋ฆฌํ๋ <abbr title="์ด๋ค ๋ฐฉ์์ผ๋ก ์ฐ๊ฒฐ๋์ด ํจ๊ป ๋์ํ๋๋ก ๊ตฌ์ฑ๋ ๋จธ์ ์ ๊ทธ๋ฃน">ํด๋ฌ์คํฐ</abbr>๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ๊ฐ ์ปจํ
์ด๋์์(**์์ปค๋ฅผ ์ฌ์ฉํ๋ Uvicorn** ๊ฐ์) **ํ๋ก์ธ์ค ๋งค๋์ **๋ฅผ ์ฐ๋ ๋์ , **ํด๋ฌ์คํฐ ๋ ๋ฒจ**์์ **๋ณต์ ๋ฅผ ์ฒ๋ฆฌ**ํ๊ณ ์ถ์ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
Kubernetes ๊ฐ์ ๋ถ์ฐ ์ปจํ
์ด๋ ๊ด๋ฆฌ ์์คํ
์ ๋ณดํต ๋ค์ด์ค๋ ์์ฒญ์ ๋ํ **๋ก๋ ๋ฐธ๋ฐ์ฑ**์ ์ง์ํ๋ฉด์๋, **์ปจํ
์ด๋ ๋ณต์ **๋ฅผ ์ฒ๋ฆฌํ๋ ํตํฉ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ชจ๋ **ํด๋ฌ์คํฐ ๋ ๋ฒจ**์์์.
๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ์์ปค๊ฐ ํ์ํ๋ค๋ฉด, `--workers` ์ปค๋งจ๋ ๋ผ์ธ ์ต์
์ ๊ฐ๋จํ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
-/// note Technical Details | ๊ธฐ์ ์ธ๋ถ์ฌํญ
+/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
์ด Docker ์ด๋ฏธ์ง๋ Uvicorn์ด ์ฃฝ์ ์์ปค๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฌ์์ํ๋ ๊ธฐ๋ฅ์ ์ง์ํ์ง ์๋ ์๊ธฐ์ ๋ง๋ค์ด์ก์ต๋๋ค. ๊ทธ๋์ Gunicorn๊ณผ Uvicorn์ ํจ๊ป ์ฌ์ฉํด์ผ ํ๊ณ , Gunicorn์ด Uvicorn ์์ปค ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๊ณ ์ฌ์์ํ๋๋ก ํ๊ธฐ ์ํด ์๋นํ ๋ณต์ก์ฑ์ด ์ถ๊ฐ๋์์ต๋๋ค.
* **๋น ๋ฆ**: (Starlette๊ณผ Pydantic ๋๋ถ์) **NodeJS** ๋ฐ **Go**์ ๋๋ฑํ ์ ๋๋ก ๋งค์ฐ ๋์ ์ฑ๋ฅ. [์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ ํ์ด์ฌ ํ๋ ์์ํฌ ์ค ํ๋](#performance).
* **๋น ๋ฅธ ์ฝ๋ ์์ฑ**: ์ฝ 200%์์ 300%๊น์ง ๊ธฐ๋ฅ ๊ฐ๋ฐ ์๋ ์ฆ๊ฐ. *
* **์ ์ ๋ฒ๊ทธ**: ์ฌ๋(๊ฐ๋ฐ์)์ ์ํ ์๋ฌ ์ฝ 40% ๊ฐ์. *
-* **์ง๊ด์ **: ํ๋ฅญํ ํธ์ง๊ธฐ ์ง์. ๋ชจ๋ ๊ณณ์์ <abbr title="also known as auto-complete, autocompletion, IntelliSense">์๋์์ฑ</abbr>. ์ ์ ๋๋ฒ๊น
์๊ฐ.
+* **์ง๊ด์ **: ํ๋ฅญํ ํธ์ง๊ธฐ ์ง์. ๋ชจ๋ ๊ณณ์์ <abbr title="๋ค๋ฅธ ๋ง๋ก๋: auto-complete, autocompletion, IntelliSense">์๋์์ฑ</abbr>. ์ ์ ๋๋ฒ๊น
์๊ฐ.
* **์ฌ์**: ์ฝ๊ฒ ์ฌ์ฉํ๊ณ ๋ฐฐ์ฐ๋๋ก ์ค๊ณ. ์ ์ ๋ฌธ์ ์ฝ๊ธฐ ์๊ฐ.
* **์งง์**: ์ฝ๋ ์ค๋ณต ์ต์ํ. ๊ฐ ๋งค๊ฐ๋ณ์ ์ ์ธ์ ์ฌ๋ฌ ๊ธฐ๋ฅ. ์ ์ ๋ฒ๊ทธ.
* **๊ฒฌ๊ณ ํจ**: ์ค๋น๋ ํ๋ก๋์
์ฉ ์ฝ๋๋ฅผ ์ป์ผ์ญ์์ค. ์๋ ๋ํํ ๋ฌธ์์ ํจ๊ป.
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
-์น API ๋์ ํฐ๋ฏธ๋์์ ์ฌ์ฉํ <abbr title="Command Line Interface">CLI</abbr> ์ฑ์ ๋ง๋ค๊ณ ์๋ค๋ฉด, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>๋ฅผ ํ์ธํด ๋ณด์ญ์์ค.
+์น API ๋์ ํฐ๋ฏธ๋์์ ์ฌ์ฉํ <abbr title="Command Line Interface - ์ปค๋งจ๋ ๋ผ์ธ ์ธํฐํ์ด์ค">CLI</abbr> ์ฑ์ ๋ง๋ค๊ณ ์๋ค๋ฉด, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>๋ฅผ ํ์ธํด ๋ณด์ญ์์ค.
**Typer**๋ FastAPI์ ๋์์
๋๋ค. ๊ทธ๋ฆฌ๊ณ **CLI๋ฅผ ์ํ FastAPI**๊ฐ ๋๊ธฐ ์ํด ์๊ฒผ์ต๋๋ค. โจ๏ธ ๐
๋ค์ ๋ด์ฉ์ผ๋ก `main.py` ํ์ผ์ ๋ง๋์ญ์์ค:
```Python
-from typing import Union
-
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Union[str, None] = None):
+def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ `async` / `await`์ ์ฌ์ฉํ๋ค๋ฉด, `async def`๋ฅผ ์ฌ์ฉํ์ญ์์ค:
-```Python hl_lines="9 14"
-from typing import Union
-
+```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: Union[str, None] = None):
+async def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
Pydantic ๋๋ถ์ ํ์ค Python ํ์
์ ์ฌ์ฉํด ๋ณธ๋ฌธ์ ์ ์ธํฉ๋๋ค.
-```Python hl_lines="4 9-12 25-27"
-from typing import Union
-
+```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: Union[bool, None] = None
+ is_offer: bool | None = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: Union[str, None] = None):
+def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
* ๋ฐ์ดํฐ ๊ฒ์ฆ:
* ๋ฐ์ดํฐ๊ฐ ์ ํจํ์ง ์์ ๋ ์๋์ผ๋ก ์์ฑํ๋ ๋ช
ํํ ์๋ฌ.
* ๊น์ด ์ค์ฒฉ๋ JSON ๊ฐ์ฒด์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ.
-* ์
๋ ฅ ๋ฐ์ดํฐ <abbr title="also known as: serialization, parsing, marshalling">๋ณํ</abbr>: ๋คํธ์ํฌ์์ ํ์ด์ฌ ๋ฐ์ดํฐ ๋ฐ ํ์
์ผ๋ก ์ ์ก. ์ฝ์ ์ ์๋ ๊ฒ๋ค:
+* ์
๋ ฅ ๋ฐ์ดํฐ <abbr title="๋ค๋ฅธ ๋ง๋ก๋: serialization, parsing, marshalling">๋ณํ</abbr>: ๋คํธ์ํฌ์์ ํ์ด์ฌ ๋ฐ์ดํฐ ๋ฐ ํ์
์ผ๋ก ์ ์ก. ์ฝ์ ์ ์๋ ๊ฒ๋ค:
* JSON.
* ๊ฒฝ๋ก ๋งค๊ฐ๋ณ์.
* ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์.
* ํค๋.
* ํผ(Forms).
* ํ์ผ.
-* ์ถ๋ ฅ ๋ฐ์ดํฐ <abbr title="also known as: serialization, parsing, marshalling">๋ณํ</abbr>: ํ์ด์ฌ ๋ฐ์ดํฐ ๋ฐ ํ์
์ ๋คํธ์ํฌ ๋ฐ์ดํฐ๋ก ์ ํ(JSON ํ์์ผ๋ก):
+* ์ถ๋ ฅ ๋ฐ์ดํฐ <abbr title="๋ค๋ฅธ ๋ง๋ก๋: serialization, parsing, marshalling">๋ณํ</abbr>: ํ์ด์ฌ ๋ฐ์ดํฐ ๋ฐ ํ์
์ ๋คํธ์ํฌ ๋ฐ์ดํฐ๋ก ์ ํ(JSON ํ์์ผ๋ก):
* ํ์ด์ฌ ํ์
๋ณํ (`str`, `int`, `float`, `bool`, `list`, ๋ฑ).
* `datetime` ๊ฐ์ฒด.
* `UUID` ๊ฐ์ฒด.
* ์๋ก ๋ค๋ฅธ ์ฅ์์์ **๋งค๊ฐ๋ณ์** ์ ์ธ: **ํค๋**, **์ฟ ํค**, **ํผ ํ๋** ๊ทธ๋ฆฌ๊ณ **ํ์ผ**.
* `maximum_length` ๋๋ `regex`์ฒ๋ผ **์ ํจ์ฑ ์ ์ฝ**ํ๋ ๋ฐฉ๋ฒ.
-* ๊ฐ๋ ฅํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด **<abbr title="also known as components, resources, providers, services, injectables">์์กด์ฑ ์ฃผ์
</abbr>** ์์คํ
.
+* ๊ฐ๋ ฅํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด **<abbr title="๋ค๋ฅธ ๋ง๋ก๋: components, resources, providers, services, injectables">์์กด์ฑ ์ฃผ์
</abbr>** ์์คํ
.
* **OAuth2** ์ง์์ ํฌํจํ **JWT tokens** ๋ฐ **HTTP Basic**์ ๊ฐ๋ ๋ณด์๊ณผ ์ธ์ฆ.
* (Pydantic ๋๋ถ์) **๊น์ ์ค์ฒฉ JSON ๋ชจ๋ธ**์ ์ ์ธํ๋๋ฐ ๋ ์ง๋ณดํ (ํ์ง๋ง ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ด) ๊ธฐ์ .
* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> ๋ฐ ๊ธฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ **GraphQL** ํตํฉ.
๊ธฐ๋ณธ์ ์ผ๋ก ๋จ์ผ ๊ฐ์ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ก ํด์๋๋ฏ๋ก, ๋ช
์์ ์ผ๋ก `Query`๋ฅผ ์ถ๊ฐํ ํ์ ์์ด ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋๋ค:
```Python
-q: Union[str, None] = None
+q: str | None = None
```
-๋๋ Python 3.10 ์ด์์์๋:
+๋๋ Python 3.9์์๋:
```Python
-q: str | None = None
+q: Union[str, None] = None
```
+
์๋ฅผ ๋ค์ด:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
`summary`์ `description`์ ์ถ๊ฐํ ์ ์์ต๋๋ค:
-{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
+{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
## ๋
์คํธ๋ง์ผ๋ก ๋ง๋ ์ค๋ช
{ #description-from-docstring }
-์ค๋ช
์ ๋ณดํต ๊ธธ์ด์ง๊ณ ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ์๊ธฐ ๋๋ฌธ์, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ค๋ช
์ ํจ์ <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation โ ๋ฌธ์ํ์ ์ฌ์ฉ๋๋ ํจ์ ๋ด๋ถ ์ฒซ ํํ์์ ์ฌ๋ฌ ์ค ๋ฌธ์์ด(์ด๋ค ๋ณ์์๋ ํ ๋น๋์ง ์์)">docstring</abbr>์ ์ ์ธํ ์ ์์ผ๋ฉฐ, **FastAPI**๋ ๊ทธ๊ณณ์์ ์ด๋ฅผ ์ฝ์ต๋๋ค.
+์ค๋ช
์ ๋ณดํต ๊ธธ์ด์ง๊ณ ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ์๊ธฐ ๋๋ฌธ์, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ค๋ช
์ ํจ์ <abbr title="๋ฌธ์ํ์ ์ฌ์ฉ๋๋ ํจ์ ๋ด๋ถ ์ฒซ ํํ์์ ์ฌ๋ฌ ์ค ๋ฌธ์์ด(์ด๋ค ๋ณ์์๋ ํ ๋น๋์ง ์์)">docstring</abbr>์ ์ ์ธํ ์ ์์ผ๋ฉฐ, **FastAPI**๋ ๊ทธ๊ณณ์์ ์ด๋ฅผ ์ฝ์ต๋๋ค.
๋
์คํธ๋ง์๋ <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>์ ์์ฑํ ์ ์์ผ๋ฉฐ, (๋
์คํธ๋ง์ ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๊ณ ๋ คํ์ฌ) ์ฌ๋ฐ๋ฅด๊ฒ ํด์๋๊ณ ํ์๋ฉ๋๋ค.
`response_description` ๋งค๊ฐ๋ณ์๋ก ์๋ต์ ๊ดํ ์ค๋ช
์ ๋ช
์ํ ์ ์์ต๋๋ค:
-{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
+{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info | ์ ๋ณด
## *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ง์์ค๋จํ๊ธฐ { #deprecate-a-path-operation }
-*๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์ ๊ฑฐํ์ง ์๊ณ <abbr title="obsolete, recommended not to use it โ ๊ตฌ์์ด๋ฉฐ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ๊ถ์ฅ๋จ">deprecated</abbr>๋ก ํ์ํด์ผ ํ๋ค๋ฉด, `deprecated` ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค:
+*๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์ ๊ฑฐํ์ง ์๊ณ <abbr title="๊ตฌ์์ด๋ฉฐ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ๊ถ์ฅ๋จ">deprecated</abbr>๋ก ํ์ํด์ผ ํ๋ค๋ฉด, `deprecated` ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค:
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}