* ๋ฒ์ญ์์ ๋ฌธ์ ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.
* ํ์ํ๋ค๋ฉด ์ธ์ด๋ณ ํ๋กฌํํธ, ์ผ๋ฐ ํ๋กฌํํธ, ๋๋ ์์ด ๋ฌธ์๋ฅผ ๊ฐ์ ํฉ๋๋ค.
* ๊ทธ๋ฐ ๋ค์ ๋ฒ์ญ์์ ๋จ์ ์๋ ๋ฌธ์ ๋ฅผ ์๋์ผ๋ก ์์ ํด ์ข์ ๋ฒ์ญ์ด ๋๊ฒ ํฉ๋๋ค.
-* ์ข์ ๋ฒ์ญ์ ๋ ์ํ์์ ๋ค์ ๋ฒ์ญํฉ๋๋ค. ์ด์์ ์ธ ๊ฒฐ๊ณผ๋ LLM์ด ๋ ์ด์ ๋ฒ์ญ์ ๋ณ๊ฒฝ์ ๋ง๋ค์ง ์๋ ๊ฒ์
๋๋ค. ์ด๋ ์ผ๋ฐ ํ๋กฌํํธ์ ์ธ์ด๋ณ ํ๋กฌํํธ๊ฐ ๊ฐ๋ฅํ ํ ์ต์ ์ด๋ผ๋ ๋ป์
๋๋ค(๋๋๋ก ๋ช ๊ฐ์ง seemingly random ๋ณ๊ฒฝ์ ํ ์ ์๋๋ฐ, ๊ทธ ์ด์ ๋ <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM์ ๊ฒฐ์ ๋ก ์ ์๊ณ ๋ฆฌ์ฆ์ด ์๋๊ธฐ ๋๋ฌธ</a>์
๋๋ค).
+* ์ข์ ๋ฒ์ญ์ ๋ ์ํ์์ ๋ค์ ๋ฒ์ญํฉ๋๋ค. ์ด์์ ์ธ ๊ฒฐ๊ณผ๋ LLM์ด ๋ ์ด์ ๋ฒ์ญ์ ๋ณ๊ฒฝ์ ๋ง๋ค์ง ์๋ ๊ฒ์
๋๋ค. ์ด๋ ์ผ๋ฐ ํ๋กฌํํธ์ ์ธ์ด๋ณ ํ๋กฌํํธ๊ฐ ๊ฐ๋ฅํ ํ ์ต์ ์ด๋ผ๋ ๋ป์
๋๋ค(๋๋๋ก ๋ช ๊ฐ์ง seemingly random ๋ณ๊ฒฝ์ ํ ์ ์๋๋ฐ, ๊ทธ ์ด์ ๋ [LLM์ ๊ฒฐ์ ๋ก ์ ์๊ณ ๋ฆฌ์ฆ์ด ์๋๊ธฐ ๋๋ฌธ](https://doublespeak.chat/#/handbook#deterministic-output)์
๋๋ค).
ํ
์คํธ:
๋งํฌ ํ
์คํธ๋ ๋ฒ์ญ๋์ด์ผ ํ๊ณ , ๋งํฌ ์ฃผ์๋ ๋ณ๊ฒฝ๋์ง ์์์ผ ํฉ๋๋ค:
* [์์ ์ ๋ชฉ์ผ๋ก ๊ฐ๋ ๋งํฌ](#code-snippets)
-* [๋ด๋ถ ๋งํฌ](index.md#installation){.internal-link target=_blank}
-* <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">์ธ๋ถ ๋งํฌ</a>
-* <a href="https://fastapi.tiangolo.com/css/styles.css" class="external-link" target="_blank">์คํ์ผ๋ก ๊ฐ๋ ๋งํฌ</a>
-* <a href="https://fastapi.tiangolo.com/js/logic.js" class="external-link" target="_blank">์คํฌ๋ฆฝํธ๋ก ๊ฐ๋ ๋งํฌ</a>
-* <a href="https://fastapi.tiangolo.com/img/foo.jpg" class="external-link" target="_blank">์ด๋ฏธ์ง๋ก ๊ฐ๋ ๋งํฌ</a>
+* [๋ด๋ถ ๋งํฌ](index.md#installation)
+* [์ธ๋ถ ๋งํฌ](https://sqlmodel.tiangolo.com/)
+* [์คํ์ผ๋ก ๊ฐ๋ ๋งํฌ](https://fastapi.tiangolo.com/css/styles.css)
+* [์คํฌ๋ฆฝํธ๋ก ๊ฐ๋ ๋งํฌ](https://fastapi.tiangolo.com/js/logic.js)
+* [์ด๋ฏธ์ง๋ก ๊ฐ๋ ๋งํฌ](https://fastapi.tiangolo.com/img/foo.jpg)
๋งํฌ ํ
์คํธ๋ ๋ฒ์ญ๋์ด์ผ ํ๊ณ , ๋งํฌ ์ฃผ์๋ ๋ฒ์ญ ํ์ด์ง๋ฅผ ๊ฐ๋ฆฌ์ผ์ผ ํฉ๋๋ค:
-* <a href="https://fastapi.tiangolo.com/ko/" class="external-link" target="_blank">FastAPI ๋งํฌ</a>
+* [FastAPI ๋งํฌ](https://fastapi.tiangolo.com/ko/)
////
* ์ฌ๋ฌ๋ถ
* ์ฌ๋ฌ๋ถ์
-* ์: (e.g.)
-* ๋ฑ (etc.)
+* ์:
+* ๋ฑ
* `foo`๋ก์์ `int`
* `bar`๋ก์์ `str`
์๋ต์ ์ ํํ ๋ฌด์์ ํฌํจํ ์ ์๋์ง ๋ณด๋ ค๋ฉด, OpenAPI ์ฌ์์ ๋ค์ ์น์
์ ํ์ธํ์ธ์:
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">OpenAPI Responses Object</a>: `Response Object`๋ฅผ ํฌํจํฉ๋๋ค.
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">OpenAPI Response Object</a>: `responses` ํ๋ผ๋ฏธํฐ ์์ ๊ฐ ์๋ต์ ์ด๊ฒ์ ์ด๋ค ํญ๋ชฉ์ด๋ ์ง์ ํฌํจํ ์ ์์ต๋๋ค. `description`, `headers`, `content`(์ฌ๊ธฐ์์ ์๋ก ๋ค๋ฅธ ๋ฏธ๋์ด ํ์
๊ณผ JSON Schema๋ฅผ ์ ์ธํฉ๋๋ค), `links` ๋ฑ์ ํฌํจํ ์ ์์ต๋๋ค.
+* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object): `Response Object`๋ฅผ ํฌํจํฉ๋๋ค.
+* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object): `responses` ํ๋ผ๋ฏธํฐ ์์ ๊ฐ ์๋ต์ ์ด๊ฒ์ ์ด๋ค ํญ๋ชฉ์ด๋ ์ง์ ํฌํจํ ์ ์์ต๋๋ค. `description`, `headers`, `content`(์ฌ๊ธฐ์์ ์๋ก ๋ค๋ฅธ ๋ฏธ๋์ด ํ์
๊ณผ JSON Schema๋ฅผ ์ ์ธํฉ๋๋ค), `links` ๋ฑ์ ํฌํจํ ์ ์์ต๋๋ค.
์ถ๊ฐ ์ํ ์ฝ๋์ ์๋ต์ ์ง์ ๋ฐํํ๋ ๊ฒฝ์ฐ, FastAPI๋ ๋ฐํํ ๋ด์ฉ์ ๋ฏธ๋ฆฌ ์ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ OpenAPI ์คํค๋ง(API ๋ฌธ์)์ ํฌํจ๋์ง ์์ต๋๋ค.
-ํ์ง๋ง ๋ค์์ ์ฌ์ฉํ์ฌ ์ฝ๋์ ์ด๋ฅผ ๋ฌธ์ํํ ์ ์์ต๋๋ค: [์ถ๊ฐ ์๋ต](additional-responses.md){.internal-link target=_blank}.
+ํ์ง๋ง ๋ค์์ ์ฌ์ฉํ์ฌ ์ฝ๋์ ์ด๋ฅผ ๋ฌธ์ํํ ์ ์์ต๋๋ค: [์ถ๊ฐ ์๋ต](additional-responses.md).
๊ทธ๋ฌ๋ฉด ์ธ์
์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ํด์ ํ์ฌ, ๋ค๋ฅธ ์์ฒญ๋ค์ด ์ด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
-`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ํ์ํ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ `yield`๊ฐ ์๋ ์์กด์ฑ์ ๋ํ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ์ด๋ค ์ ์์ ์ด๋์ด ๋๋์ง๋ฅผ ํฌํจํด <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions ์ง๋ฌธ</a>์ ์์ฑํด ์ฃผ์ธ์.
+`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ํ์ํ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ `yield`๊ฐ ์๋ ์์กด์ฑ์ ๋ํ ์กฐ๊ธฐ ์ข
๋ฃ๊ฐ ์ด๋ค ์ ์์ ์ด๋์ด ๋๋์ง๋ฅผ ํฌํจํด [GitHub Discussions ์ง๋ฌธ](https://github.com/fastapi/fastapi/discussions/new?category=questions)์ ์์ฑํด ์ฃผ์ธ์.
`yield`๊ฐ ์๋ ์์กด์ฑ์์ ์กฐ๊ธฐ ์ข
๋ฃ์ ๋ํ ์ค๋๋ ฅ ์๋ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋ค๋ฉด, ์กฐ๊ธฐ ์ข
๋ฃ๋ฅผ ์ ํ์ ์ผ๋ก ํ์ฑํํ ์ ์๋ ์๋ก์ด ๋ฐฉ๋ฒ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ณ ๋ คํ๊ฒ ์ต๋๋ค.
### ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ์ `yield`๊ฐ ์๋ ์์กด์ฑ, ๊ธฐ์ ์ธ๋ถ์ฌํญ { #background-tasks-and-dependencies-with-yield-technical-details }
-FastAPI 0.106.0 ์ด์ ์๋ `yield` ์ดํ์ ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ์ต๋๋ค. `yield`๊ฐ ์๋ ์์กด์ฑ์ ์ข
๋ฃ ์ฝ๋๋ ์๋ต์ด ์ ์ก๋ *ํ์* ์คํ๋์๊ธฐ ๋๋ฌธ์, [์์ธ ํธ๋ค๋ฌ](../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)๊ฐ ์ด๋ฏธ ์คํ๋ ๋ค์์ต๋๋ค.
์ด๋ ์ฃผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ ์์์ ์์กด์ฑ์ด "yield"ํ ๋์ผํ ๊ฐ์ฒด๋ค์ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ธฐ ์ํ ์ค๊ณ์์ต๋๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ํ์คํฌ๊ฐ ๋๋ ๋ค์ ์ข
๋ฃ ์ฝ๋๊ฐ ์คํ๋์๊ธฐ ๋๋ฌธ์
๋๋ค.
`TestClient`๋ ํ์ค pytest๋ฅผ ์ฌ์ฉํ์ฌ, ์ผ๋ฐ `def` ํ
์คํธ ํจ์ ์์์ ๋น๋๊ธฐ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ํธ์ถํ๋๋ก ๋ด๋ถ์์ ๋ง๋ฒ ๊ฐ์ ์ฒ๋ฆฌ๋ฅผ ํฉ๋๋ค. ํ์ง๋ง ๋น๋๊ธฐ ํจ์ ์์์ ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๊ทธ ๋ง๋ฒ์ ๋ ์ด์ ๋์ํ์ง ์์ต๋๋ค. ํ
์คํธ๋ฅผ ๋น๋๊ธฐ๋ก ์คํํ๋ฉด, ํ
์คํธ ํจ์ ์์์ `TestClient`๋ฅผ ๋ ์ด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-`TestClient`๋ <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ๋คํํ HTTPX๋ฅผ ์ง์ ์ฌ์ฉํด API๋ฅผ ํ
์คํธํ ์ ์์ต๋๋ค.
+`TestClient`๋ [HTTPX](https://www.python-httpx.org)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ๋คํํ HTTPX๋ฅผ ์ง์ ์ฌ์ฉํด API๋ฅผ ํ
์คํธํ ์ ์์ต๋๋ค.
## ์์ { #example }
-๊ฐ๋จํ ์์๋ก, [๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
](../tutorial/bigger-applications.md){.internal-link target=_blank}๊ณผ [ํ
์คํธ](../tutorial/testing.md){.internal-link target=_blank}์์ ์ค๋ช
ํ ๊ฒ๊ณผ ๋น์ทํ ํ์ผ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
+๊ฐ๋จํ ์์๋ก, [๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
](../tutorial/bigger-applications.md)๊ณผ [ํ
์คํธ](../tutorial/testing.md)์์ ์ค๋ช
ํ ๊ฒ๊ณผ ๋น์ทํ ํ์ผ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
```
.
/// warning | ๊ฒฝ๊ณ
-์ ํ๋ฆฌ์ผ์ด์
์ด lifespan ์ด๋ฒคํธ์ ์์กดํ๋ค๋ฉด, `AsyncClient`๋ ์ด๋ฌํ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ง ์์ต๋๋ค. ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋๋ก ํ๋ ค๋ฉด <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>์ `LifespanManager`๋ฅผ ์ฌ์ฉํ์ธ์.
+์ ํ๋ฆฌ์ผ์ด์
์ด lifespan ์ด๋ฒคํธ์ ์์กดํ๋ค๋ฉด, `AsyncClient`๋ ์ด๋ฌํ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ง ์์ต๋๋ค. ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋๋ก ํ๋ ค๋ฉด [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage)์ `LifespanManager`๋ฅผ ์ฌ์ฉํ์ธ์.
///
/// tip | ํ
-ํ
์คํธ์ ๋น๋๊ธฐ ํจ์ ํธ์ถ์ ํตํฉํ ๋(์: <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB์ MotorClient</a>๋ฅผ ์ฌ์ฉํ ๋) `RuntimeError: Task attached to a different loop`๋ฅผ ๋ง์ฃผ์น๋ค๋ฉด, ์ด๋ฒคํธ ๋ฃจํ๊ฐ ํ์ํ ๊ฐ์ฒด๋ async ํจ์ ์์์๋ง ์ธ์คํด์คํํด์ผ ํ๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์. ์๋ฅผ ๋ค์ด `@app.on_event("startup")` ์ฝ๋ฐฑ์์ ์ธ์คํด์คํํ ์ ์์ต๋๋ค.
+ํ
์คํธ์ ๋น๋๊ธฐ ํจ์ ํธ์ถ์ ํตํฉํ ๋(์: [MongoDB์ MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop)๋ฅผ ์ฌ์ฉํ ๋) `RuntimeError: Task attached to a different loop`๋ฅผ ๋ง์ฃผ์น๋ค๋ฉด, ์ด๋ฒคํธ ๋ฃจํ๊ฐ ํ์ํ ๊ฐ์ฒด๋ async ํจ์ ์์์๋ง ์ธ์คํด์คํํด์ผ ํ๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์. ์๋ฅผ ๋ค์ด `@app.on_event("startup")` ์ฝ๋ฐฑ์์ ์ธ์คํด์คํํ ์ ์์ต๋๋ค.
///
ํ๋ก์ ํค๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
+* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For)
+* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto)
+* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host)
///
/// tip | ํ
-HTTPS์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด ๊ฐ์ด๋ [HTTPS์ ๋ํ์ฌ](../deployment/https.md){.internal-link target=_blank}๋ฅผ ํ์ธํ์ธ์.
+HTTPS์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด ๊ฐ์ด๋ [HTTPS์ ๋ํ์ฌ](../deployment/https.md)๋ฅผ ํ์ธํ์ธ์.
///
```JSON hl_lines="4-8"
{
"openapi": "3.1.0",
- // More stuff here
+ // ์ฌ๊ธฐ์ ๋ค๋ฅธ ๋ด์ฉ์ด ๋ ์์ต๋๋ค
"servers": [
{
"url": "/api/v1"
}
],
"paths": {
- // More stuff here
+ // ์ฌ๊ธฐ์ ๋ค๋ฅธ ๋ด์ฉ์ด ๋ ์์ต๋๋ค
}
}
```
์๋ฒ(Uvicorn)๋ ๊ทธ `root_path`๋ฅผ ์ฑ์ ์ ๋ฌํ๋ ๊ฒ ์ธ์๋ ๋ค๋ฅธ ์ฉ๋๋ก ์ฌ์ฉํ์ง ์๋๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
-ํ์ง๋ง ๋ธ๋ผ์ฐ์ ๋ก <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>์ ์ ์ํ๋ฉด ์ ์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+ํ์ง๋ง ๋ธ๋ผ์ฐ์ ๋ก [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app)์ ์ ์ํ๋ฉด ์ ์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{
## Traefik์ผ๋ก ๋ก์ปฌ ํ
์คํธํ๊ธฐ { #testing-locally-with-traefik }
-<a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>์ ์ฌ์ฉํ๋ฉด, ๊ฒฝ๋ก ์ ๋์ฌ๊ฐ ์ ๊ฑฐ๋๋ ๊ตฌ์ฑ์ ๋ก์ปฌ์์ ์ฝ๊ฒ ์คํํ ์ ์์ต๋๋ค.
+[Traefik](https://docs.traefik.io/)์ ์ฌ์ฉํ๋ฉด, ๊ฒฝ๋ก ์ ๋์ฌ๊ฐ ์ ๊ฑฐ๋๋ ๊ตฌ์ฑ์ ๋ก์ปฌ์์ ์ฝ๊ฒ ์คํํ ์ ์์ต๋๋ค.
-<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Traefik ๋ค์ด๋ก๋</a>๋ ๋จ์ผ ๋ฐ์ด๋๋ฆฌ์ด๋ฉฐ, ์์ถ ํ์ผ์ ํ๊ณ ํฐ๋ฏธ๋์์ ๋ฐ๋ก ์คํํ ์ ์์ต๋๋ค.
+[Traefik ๋ค์ด๋ก๋](https://github.com/containous/traefik/releases)๋ ๋จ์ผ ๋ฐ์ด๋๋ฆฌ์ด๋ฉฐ, ์์ถ ํ์ผ์ ํ๊ณ ํฐ๋ฏธ๋์์ ๋ฐ๋ก ์คํํ ์ ์์ต๋๋ค.
๊ทธ ๋ค์ ๋ค์ ๋ด์ฉ์ ๊ฐ์ง `traefik.toml` ํ์ผ์ ์์ฑํ์ธ์:
### ์๋ต ํ์ธํ๊ธฐ { #check-the-responses }
-์ด์ Uvicorn์ ํฌํธ๋ก ๋ URL์ธ <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>๋ก ์ ์ํ๋ฉด ์ ์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+์ด์ Uvicorn์ ํฌํธ๋ก ๋ URL์ธ [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app)๋ก ์ ์ํ๋ฉด ์ ์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{
///
-์ด์ Traefik์ ํฌํธ๊ฐ ํฌํจ๋๊ณ ๊ฒฝ๋ก ์ ๋์ฌ๊ฐ ํฌํจ๋ URL <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>์ ์ฌ์ธ์.
+์ด์ Traefik์ ํฌํธ๊ฐ ํฌํจ๋๊ณ ๊ฒฝ๋ก ์ ๋์ฌ๊ฐ ํฌํจ๋ URL [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)์ ์ฌ์ธ์.
๋์ผํ ์๋ต์ ์ป์ต๋๋ค:
์ฑ์ ์ ๊ทผํ๋ "๊ณต์" ๋ฐฉ๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ ์ํ ๊ฒฝ๋ก ์ ๋์ฌ๋ฅผ ๊ฐ์ง ํ๋ก์๋ฅผ ํตํด์์
๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ํ๋ ๋๋ก, URL์ ๊ฒฝ๋ก ์ ๋์ฌ๊ฐ ์๋ ์ํ์์ Uvicorn์ด ์ง์ ์ ๊ณตํ๋ docs UI๋ฅผ ์๋ํ๋ฉด, ํ๋ก์๋ฅผ ํตํด ์ ๊ทผ๋๋ค๊ณ ๊ฐ์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋์ํ์ง ์์ต๋๋ค.
-<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>์์ ํ์ธํ ์ ์์ต๋๋ค:
+[http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)์์ ํ์ธํ ์ ์์ต๋๋ค:
<img src="/img/tutorial/behind-a-proxy/image01.png">
ํ์ง๋ง ํ๋ก์(ํฌํธ `9999`)๋ฅผ ์ฌ์ฉํด "๊ณต์" URL์ธ `/api/v1/docs`์์ docs UI์ ์ ๊ทผํ๋ฉด, ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํฉ๋๋ค! ๐
-<a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>์์ ํ์ธํ ์ ์์ต๋๋ค:
+[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs)์์ ํ์ธํ ์ ์์ต๋๋ค:
<img src="/img/tutorial/behind-a-proxy/image02.png">
```JSON hl_lines="5-7"
{
"openapi": "3.1.0",
- // More stuff here
+ // ์ฌ๊ธฐ์ ๋ค๋ฅธ ๋ด์ฉ์ด ๋ ์์ต๋๋ค
"servers": [
{
"url": "/api/v1"
}
],
"paths": {
- // More stuff here
+ // ์ฌ๊ธฐ์ ๋ค๋ฅธ ๋ด์ฉ์ด ๋ ์์ต๋๋ค
}
}
```
///
-<a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>์ docs UI์์๋ ๋ค์์ฒ๋ผ ๋ณด์
๋๋ค:
+[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs)์ docs UI์์๋ ๋ค์์ฒ๋ผ ๋ณด์
๋๋ค:
<img src="/img/tutorial/behind-a-proxy/image03.png">
## ์๋ธ ์ ํ๋ฆฌ์ผ์ด์
๋ง์ดํธํ๊ธฐ { #mounting-a-sub-application }
-ํ๋ก์์์ `root_path`๋ฅผ ์ฌ์ฉํ๋ฉด์๋, [์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- ๋ง์ดํธ](sub-applications.md){.internal-link target=_blank}์ ์ค๋ช
๋ ๊ฒ์ฒ๋ผ ์๋ธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง์ดํธํด์ผ ํ๋ค๋ฉด, ๊ธฐ๋ํ๋ ๋๋ก ์ผ๋ฐ์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
+ํ๋ก์์์ `root_path`๋ฅผ ์ฌ์ฉํ๋ฉด์๋, [์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- ๋ง์ดํธ](sub-applications.md)์ ์ค๋ช
๋ ๊ฒ์ฒ๋ผ ์๋ธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง์ดํธํด์ผ ํ๋ค๋ฉด, ๊ธฐ๋ํ๋ ๋๋ก ์ผ๋ฐ์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
FastAPI๊ฐ ๋ด๋ถ์ ์ผ๋ก `root_path`๋ฅผ ๋๋ํ๊ฒ ์ฌ์ฉํ๋ฏ๋ก, ๊ทธ๋ฅ ๋์ํฉ๋๋ค. โจ
# ์ฌ์ฉ์ ์ ์ ์๋ต - HTML, Stream, ํ์ผ, ๊ธฐํ { #custom-response-html-stream-file-others }
-๊ธฐ๋ณธ์ ์ผ๋ก, **FastAPI** ์๋ต์ `JSONResponse`๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐํํฉ๋๋ค.
+๊ธฐ๋ณธ์ ์ผ๋ก **FastAPI**๋ JSON ์๋ต์ ๋ฐํํฉ๋๋ค.
-์ด๋ฅผ ์ฌ์ ์ ํ๋ ค๋ฉด [์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ์ฒ๋ผ `Response`๋ฅผ ์ง์ ๋ฐํํ๋ฉด ๋ฉ๋๋ค.
+[์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ `Response`๋ฅผ ์ง์ ๋ฐํํ์ฌ ์ด๋ฅผ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
-๊ทธ๋ฌ๋ `Response` (๋๋ `JSONResponse`์ ๊ฐ์ ํ์ ํด๋์ค)๋ฅผ ์ง์ ๋ฐํํ๋ฉด, ๋ฐ์ดํฐ๊ฐ ์๋์ผ๋ก ๋ณํ๋์ง ์์ผ๋ฉฐ (์ฌ์ง์ด `response_model`์ ์ ์ธํ๋๋ผ๋), ๋ฌธ์ํ๊ฐ ์๋์ผ๋ก ์์ฑ๋์ง ์์ต๋๋ค(์๋ฅผ ๋ค์ด, ์์ฑ๋ OpenAPI์ ์ผ๋ถ๋ก HTTP ํค๋ `Content-Type`์ ํน์ "๋ฏธ๋์ด ํ์
"์ ํฌํจํ๋ ๊ฒฝ์ฐ).
+๊ทธ๋ฌ๋ `Response`๋ฅผ ์ง์ ๋ฐํํ๋ฉด(๋๋ `JSONResponse`์ ๊ฐ์ ํ์ ํด๋์ค๋ฅผ ๋ฐํํ๋ฉด) ๋ฐ์ดํฐ๊ฐ ์๋์ผ๋ก ๋ณํ๋์ง ์์ผ๋ฉฐ(๋น๋ก `response_model`์ ์ ์ธํ๋ค ํ๋๋ผ๋), ๋ฌธ์๋ ์๋์ผ๋ก ์์ฑ๋์ง ์์ต๋๋ค(์๋ฅผ ๋ค์ด, ์์ฑ๋ OpenAPI์ ์ผ๋ถ๋ก HTTP ํค๋ `Content-Type`์ ํน์ "๋ฏธ๋์ด ํ์
"์ ํฌํจํ๋ ๊ฒ ๋ฑ).
-รญ\95\98รฌยง\80รซยง\8c *รชยฒยฝรซยก\9c รฌยฒ\98รซยฆยฌ รซ\8dยฐรฌยฝ\94รซย \88รฌ\9dยดรญ\84ยฐ*รฌ\97\90รฌ\84\9c `response_class` รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95\98รฌ\97ยฌ รฌ\9b\90รญ\95\98รซ\8a\94 `Response`(รฌ\98\88: รซยชยจรซ\93ย `Response` รญ\95\98รฌ\9c\84 รญ\81ยดรซ\9e\98รฌ\8aยค)๋ฅผ ์ ์ธํ ์๋ ์์ต๋๋ค.
+รญ\95\98รฌยง\80รซยง\8c *รชยฒยฝรซยก\9c รฌยฒ\98รซยฆยฌ รซ\8dยฐรฌยฝ\94รซย \88รฌ\9dยดรญ\84ยฐ*รฌ\97\90รฌ\84\9c `response_class` รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95\98รฌ\97ยฌ รฌ\82ยฌรฌ\9aยฉรญ\95ย `Response`(รฌ\98\88: รฌ\96ยดรซ\96ยค `Response` รญ\95\98รฌ\9c\84 รญ\81ยดรซ\9e\98รฌ\8aยครซ\93ย )๋ฅผ ์ ์ธํ ์๋ ์์ต๋๋ค.
-*๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์์ ๋ฐํํ๋ ๋ด์ฉ์ ํด๋น `Response`์์ ํฌํจ๋ฉ๋๋ค.
-
-๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ๊ทธ `Response`๊ฐ `JSONResponse`์ `UJSONResponse`์ ๊ฒฝ์ฐ ์ฒ๋ผ JSON ๋ฏธ๋์ด ํ์
(`application/json`)์ ๊ฐ์ง๊ณ ์๋ค๋ฉด, *๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์์ ์ ์ธํ Pydantic์ `response_model`์ ์ฌ์ฉํด ์๋์ผ๋ก ๋ณํ(๋ฐ ํํฐ๋ง) ๋ฉ๋๋ค.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์์ ๋ฐํํ๋ ๋ด์ฉ์ ํด๋น `Response` ์์ ๋ด๊น๋๋ค.
/// note | ์ฐธ๊ณ
///
-## `ORJSONResponse` ์ฌ์ฉํ๊ธฐ { #use-orjsonresponse }
-
-์๋ฅผ ๋ค์ด, ์ฑ๋ฅ์ ๊ทน๋ํํ๋ ค๋ ๊ฒฝ์ฐ, <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>์ ์ค์นํ์ฌ ์ฌ์ฉํ๊ณ ์๋ต์ `ORJSONResponse`๋ก ์ค์ ํ ์ ์์ต๋๋ค.
-
-์ฌ์ฉํ๊ณ ์ ํ๋ `Response` ํด๋์ค(ํ์ ํด๋์ค)๋ฅผ ์ํฌํธํ ํ, *๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์์ ์ ์ธํ์ธ์.
-
-๋๊ท๋ชจ ์๋ต์ ๊ฒฝ์ฐ, ๋์
๋๋ฆฌ๋ฅผ ๋ฐํํ๋ ๊ฒ๋ณด๋ค `Response`๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ํจ์ฌ ๋น ๋ฆ
๋๋ค.
-
-์ด์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก, FastAPI๊ฐ ๋ด๋ถ์ ๋ชจ๋ ํญ๋ชฉ์ ๊ฒ์ฌํ๊ณ JSON์ผ๋ก ์ง๋ ฌํํ ์ ์๋์ง ํ์ธํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๋ ์ฌ์ฉ์ ์๋ด์์์ ์ค๋ช
๋ [JSON ํธํ ๊ฐ๋ฅ ์ธ์ฝ๋](../tutorial/encoder.md){.internal-link target=_blank}๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ๋์ผํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ๊ณผ ๊ฐ์ **์์์ ๊ฐ์ฒด**๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
-
-ํ์ง๋ง ๋ฐํํ๋ ๋ด์ฉ์ด **JSON์ผ๋ก ์ง๋ ฌํ ๊ฐ๋ฅ**ํ๋ค๊ณ ํ์ ํ๋ ๊ฒฝ์ฐ, ํด๋น ๋ด์ฉ์ ์๋ต ํด๋์ค์ ์ง์ ์ ๋ฌํ ์ ์์ผ๋ฉฐ, FastAPI๊ฐ ๋ฐํ ๋ด์ฉ์ `jsonable_encoder`๋ฅผ ํตํด ์ฒ๋ฆฌํ ๋ค ์๋ต ํด๋์ค์ ์ ๋ฌํ๋ ์ค๋ฒํค๋๋ฅผ ํผํ ์ ์์ต๋๋ค.
+## JSON ์๋ต { #json-responses }
-{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
+๊ธฐ๋ณธ์ ์ผ๋ก FastAPI๋ JSON ์๋ต์ ๋ฐํํฉ๋๋ค.
-/// info | ์ ๋ณด
-
-`response_class` ๋งค๊ฐ๋ณ์๋ ์๋ต์ "๋ฏธ๋์ด ํ์
"์ ์ ์ํ๋ ๋ฐ์๋ ์ฌ์ฉ๋ฉ๋๋ค.
+[์๋ต ๋ชจ๋ธ](../tutorial/response-model.md)์ ์ ์ธํ๋ฉด FastAPI๋ Pydantic์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํฉ๋๋ค.
-รฌ\9dยด รชยฒยฝรฌ\9aยฐ, HTTP รญ\97ยครซ\8d\94 `Content-Type`รฌ\9d\80 `application/json`รฌ\9cยผรซยก\9c รฌ\84ยครฌย \95รซ\90ยฉ๋๋ค.
+รฌ\9d\91รซ\8bยต รซยชยจรซ\8dยธรฌ\9d\84 รฌ\84ย รฌ\96ยธรญ\95\98รฌยง\80 รฌ\95\8aรฌ\9cยผรซยฉยด FastAPIรซ\8a\94 [JSON รญ\98ยธรญ\99\98 รชยฐ\80รซ\8aยฅ รฌ\9dยธรฌยฝ\94รซ\8d\94](../tutorial/encoder.md)รฌ\97\90รฌ\84\9c รฌ\84ยครซยช\85รญ\95\9c `jsonable_encoder`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด รซ\8dยฐรฌ\9dยดรญ\84ยฐรซยฅยผ รซยณ\80รญ\99\98รญ\95\9c รซ\92ยค `JSONResponse`รฌ\97\90 รซ\84ยฃรฌ\8aยต๋๋ค.
-รชยทยธรซยฆยฌรชยณย รฌ\9dยดรซ\8a\94 OpenAPIรฌ\97\90 รชยทยธรซ\8c\80รซยก\9c รซยฌยธรฌ\84\9cรญ\99\94รซ\90ยฉรซ\8b\88รซ\8bยค.
+`JSONResponse`รฌยฒ\98รซ\9fยผ JSON รซยฏยธรซ\94\94รฌ\96ยด รญ\83\80รฌ\9e\85(`application/json`)รฌ\9d\84 รชยฐ\80รฌยง\84 `response_class`รซยฅยผ รฌ\84ย รฌ\96ยธรญ\95\98รซยฉยด, รฌ\97ยฌรซ\9fยฌรซยถ\84รฌ\9dยด *รชยฒยฝรซยก\9c รฌยฒ\98รซยฆยฌ รซ\8dยฐรฌยฝ\94รซย \88รฌ\9dยดรญ\84ยฐ*รฌ\97\90รฌ\84\9c รฌ\84ย รฌ\96ยธรญ\95\9c Pydanticรฌ\9d\98 `response_model`รซยก\9c รซ\8dยฐรฌ\9dยดรญ\84ยฐรชยฐ\80 รฌ\9e\90รซ\8f\99 รซยณ\80รญ\99\98(รซยฐ\8f รญ\95\84รญ\84ยฐรซยง\81)รซ\90ยฉรซ\8b\88รซ\8bยค. รญ\95\98รฌยง\80รซยง\8c รซ\8dยฐรฌ\9dยดรญ\84ยฐรฌ\9d\98 JSON รซยฐ\94รฌ\9dยดรญ\8aยธ รฌยง\81รซย ยฌรญ\99\94 รฌ\9e\90รฌยฒยดรซ\8a\94 Pydanticรฌ\9dยด รฌ\88\98รญ\96\89รญ\95\98รฌยง\80 รฌ\95\8aรชยณย , `jsonable_encoder`รซยก\9c รซยณ\80รญ\99\98รญ\95\9c รญ\9b\84 `JSONResponse` รญ\81ยดรซ\9e\98รฌ\8aยครฌ\97\90 รฌย \84รซ\8bยฌรญ\95\98รซยฉยฐ, รชยทยธ รญ\81ยดรซ\9e\98รฌ\8aยครชยฐ\80 Python รญ\91\9cรฌยค\80 JSON รซ\9dยผรฌ\9dยดรซยธ\8cรซ\9fยฌรซยฆยฌรซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด รซยฐ\94รฌ\9dยดรญ\8aยธรซยก\9c รฌยง\81รซย ยฌรญ\99\94รญ\95ยฉรซ\8b\88รซ\8bยค.
-///
+### JSON ์ฑ๋ฅ { #json-performance }
-/// tip | ํ
+์์ฝํ๋ฉด, ์ต๋ ์ฑ๋ฅ์ด ํ์ํ๋ค๋ฉด [์๋ต ๋ชจ๋ธ](../tutorial/response-model.md)์ ์ฌ์ฉํ๊ณ , *๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `response_class`๋ฅผ ์ ์ธํ์ง ๋ง์ธ์.
-`ORJSONResponse`๋ FastAPI์์๋ง ์ฌ์ฉํ ์ ์๊ณ Starlette์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-
-///
+{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *}
## HTML ์๋ต { #html-response }
**FastAPI**์์ HTML ์๋ต์ ์ง์ ๋ฐํํ๋ ค๋ฉด `HTMLResponse`๋ฅผ ์ฌ์ฉํ์ธ์.
-* `HTMLResponse`๋ฅผ ์ํฌํธ ํฉ๋๋ค.
+* `HTMLResponse`๋ฅผ ์ํฌํธํฉ๋๋ค.
* *๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `response_class` ๋งค๊ฐ๋ณ์๋ก `HTMLResponse`๋ฅผ ์ ๋ฌํฉ๋๋ค.
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
์ด ๊ฒฝ์ฐ, HTTP ํค๋ `Content-Type`์ `text/html`๋ก ์ค์ ๋ฉ๋๋ค.
-๊ทธ๋ฆฌ๊ณ ์ด๋ OpenAPI์ ๊ทธ๋๋ก ๋ฌธ์ํ ๋ฉ๋๋ค.
+๊ทธ๋ฆฌ๊ณ ์ด๋ OpenAPI์ ๊ทธ๋๋ก ๋ฌธ์ํ๋ฉ๋๋ค.
///
### `Response` ๋ฐํํ๊ธฐ { #return-a-response }
-[์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ ์ฒ๋ผ, *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ์๋ต์ ์ง์ ๋ฐํํ์ฌ ์ฌ์ ์ํ ์๋ ์์ต๋๋ค.
+[์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ, *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ์๋ต์ ์ง์ ๋ฐํํ์ฌ ์ฌ์ ์ํ ์๋ ์์ต๋๋ค.
์์ ์์ ์ ๋์ผํ๊ฒ `HTMLResponse`๋ฅผ ๋ฐํํ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
/// warning | ๊ฒฝ๊ณ
-*๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์์ ์ง์ ๋ฐํ๋ `Response`๋ OpenAPI์ ๋ฌธ์ํ๋์ง ์์ต๋๋ค(์๋ฅผ๋ค์ด, `Content-Type`์ด ๋ฌธ์ํ๋์ง ์์) ์๋ ๋ํํ ๋ฌธ์์์๋ ํ์๋์ง ์์ต๋๋ค.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์์ ์ง์ ๋ฐํ๋ `Response`๋ OpenAPI์ ๋ฌธ์ํ๋์ง ์์ต๋๋ค(์๋ฅผ ๋ค์ด, `Content-Type`์ด ๋ฌธ์ํ๋์ง ์์) ๊ทธ๋ฆฌ๊ณ ์๋ ๋ํํ ๋ฌธ์์๋ ํ์๋์ง ์์ต๋๋ค.
///
///
-### OpenAPI์ ๋ฌธ์ํํ๊ณ `Response` ์ฌ์ ์ ํ๊ธฐ { #document-in-openapi-and-override-response }
+### OpenAPI์ ๋ฌธ์ํํ๊ณ `Response` ์ฌ์ ์ํ๊ธฐ { #document-in-openapi-and-override-response }
-รญ\95ยจรฌ\88\98 รซ\82ยดรซยถ\80รฌ\97\90รฌ\84\9c รฌ\9d\91รซ\8bยตรฌ\9d\84 รฌ\9eยฌรฌย \95รฌ\9d\98รญ\95\98รซยฉยดรฌ\84\9c รซ\8f\99รฌ\8b\9cรฌ\97\90 OpenAPIรฌ\97\90รฌ\84\9c "รซยฏยธรซ\94\94รฌ\96ยด รญ\83\80รฌ\9e\85"รฌ\9d\84 รซยฌยธรฌ\84\9cรญ\99\94รญ\95\98รชยณย รฌ\8bยถรซ\8bยครซยฉยด, `response_class` รซยงยครชยฒ\8c๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด์ `Response` ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
+รญ\95ยจรฌ\88\98 รซ\82ยดรซยถ\80รฌ\97\90รฌ\84\9c รฌ\9d\91รซ\8bยตรฌ\9d\84 รฌ\9eยฌรฌย \95รฌ\9d\98รญ\95\98รซยฉยดรฌ\84\9c รซ\8f\99รฌ\8b\9cรฌ\97\90 OpenAPIรฌ\97\90รฌ\84\9c "รซยฏยธรซ\94\94รฌ\96ยด รญ\83\80รฌ\9e\85"รฌ\9d\84 รซยฌยธรฌ\84\9cรญ\99\94รญ\95\98รชยณย รฌ\8bยถรซ\8bยครซยฉยด, `response_class` รซยงยครชยฐ\9c๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด์ `Response` ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
์ด ๊ฒฝ์ฐ `response_class`๋ OpenAPI *๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ๋ฌธ์ํํ๋ ๋ฐ๋ง ์ฌ์ฉ๋๊ณ , ์ค์ ๋ก๋ ์ฌ๋ฌ๋ถ์ด ๋ฐํํ `Response`๊ฐ ๊ทธ๋๋ก ์ฌ์ฉ๋ฉ๋๋ค.
-#### `HTMLResponse`์ง์ ๋ฐํํ๊ธฐ { #return-an-htmlresponse-directly }
+#### `HTMLResponse` ์ง์ ๋ฐํํ๊ธฐ { #return-an-htmlresponse-directly }
์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค:
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
-์ด ์์ ์์, `generate_html_response()` ํจ์๋ HTML์ `str`๋ก ๋ฐํํ๋ ๋์ ์ด๋ฏธ `Response`๋ฅผ ์์ฑํ๊ณ ๋ฐํํฉ๋๋ค.
+์ด ์์ ์์ `generate_html_response()` ํจ์๋ HTML์ `str`๋ก ๋ฐํํ๋ ๋์ ์ด๋ฏธ `Response`๋ฅผ ์์ฑํ๊ณ ๋ฐํํฉ๋๋ค.
-`generate_html_response()`๋ฅผ ํธ์ถํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํจ์ผ๋ก์จ, ๊ธฐ๋ณธ์ ์ธ **FastAPI** ๊ธฐ๋ณธ ๋์์ ์ฌ์ ์ ํ๋ `Response`๋ฅผ ์ด๋ฏธ ๋ฐํํ๊ณ ์์ต๋๋ค.
+`generate_html_response()`๋ฅผ ํธ์ถํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํจ์ผ๋ก์จ, ๊ธฐ๋ณธ์ ์ธ **FastAPI** ๋์์ ์ฌ์ ์ํ๋ `Response`๋ฅผ ์ด๋ฏธ ๋ฐํํ๊ณ ์์ต๋๋ค.
-ํ์ง๋ง `response_class`์ `HTMLResponse`๋ฅผ ํจ๊ป ์ ๋ฌํ๊ธฐ ๋๋ฌธ์, **FastAPI**๋ ์ด๋ฅผ OpenAPI ๋ฐ ๋ํํ ๋ฌธ์์์ `text/html`๋ก HTML์ ๋ฌธ์ํ ํ๋ ๋ฐฉ๋ฒ์ ์ ์ ์์ต๋๋ค.
+ํ์ง๋ง `response_class`์ `HTMLResponse`๋ฅผ ํจ๊ป ์ ๋ฌํ๊ธฐ ๋๋ฌธ์, **FastAPI**๋ ์ด๋ฅผ OpenAPI ๋ฐ ๋ํํ ๋ฌธ์์์ `text/html`์ HTML๋ก ๋ฌธ์ํํ๋ ๋ฐฉ๋ฒ์ ์ ์ ์์ต๋๋ค:
<img src="/img/tutorial/custom-response/image01.png">
## ์ฌ์ฉ ๊ฐ๋ฅํ ์๋ต๋ค { #available-responses }
-๋ค์์ ์ฌ์ฉํ ์ ์๋ ๋ช๊ฐ์ง ์๋ต๋ค ์
๋๋ค.
+๋ค์์ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์๋ต๋ค์
๋๋ค.
-`Response`๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ด๋ค ๊ฒ๋ ๋ฐํ ํ ์ ์์ผ๋ฉฐ, ์ง์ ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์๋ ์์ต๋๋ค.
+`Response`๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ด๋ค ๊ฒ๋ ๋ฐํํ ์ ์์ผ๋ฉฐ, ์ง์ ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์๋ ์์ต๋๋ค.
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
`from starlette.responses import HTMLResponse`๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
-**FastAPI**๋ ๊ฐ๋ฐ์์ธ ์ฌ๋ฌ๋ถ์ ํธ์๋ฅผ ์ํด `starlette.responses`๋ฅผ `fastapi.responses`๋ก ์ ๊ณต ํ์ง๋ง, ๋๋ถ๋ถ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์๋ต์ Starlette์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค.
+**FastAPI**๋ ๊ฐ๋ฐ์์ธ ์ฌ๋ฌ๋ถ์ ํธ์๋ฅผ ์ํด `starlette.responses`๋ฅผ `fastapi.responses`๋ก ๋์ผํ๊ฒ ์ ๊ณตํ์ง๋ง, ๋๋ถ๋ถ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์๋ต์ Starlette์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค.
///
### `Response` { #response }
-๊ธฐ๋ณธ `Response` ํด๋์ค๋ ๋ค๋ฅธ ๋ชจ๋ ์๋ต ํด๋์ค์ ๋ถ๋ชจ ํด๋์ค ์
๋๋ค.
+๊ธฐ๋ณธ `Response` ํด๋์ค์ด๋ฉฐ, ๋ค๋ฅธ ๋ชจ๋ ์๋ต ํด๋์ค๊ฐ ์ด๋ฅผ ์์ํฉ๋๋ค.
์ด ํด๋์ค๋ฅผ ์ง์ ๋ฐํํ ์ ์์ต๋๋ค.
๋ค์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค:
* `content` - `str` ๋๋ `bytes`.
-* `status_code` - HTTP ์ํ์ฝ๋๋ฅผ ๋ํ๋ด๋ `int`.
+* `status_code` - HTTP ์ํ ์ฝ๋๋ฅผ ๋ํ๋ด๋ `int`.
* `headers` - ๋ฌธ์์ด๋ก ์ด๋ฃจ์ด์ง `dict`.
* `media_type` - ๋ฏธ๋์ด ํ์
์ ๋ํ๋ด๋ `str` ์: `"text/html"`.
-FastAPI (์ค์ ๋ก๋ Starlette)๊ฐ ์๋์ผ๋ก Content-Length ํค๋๋ฅผ ํฌํจ์ํต๋๋ค. ๋ํ `media_type`์ ๊ธฐ๋ฐํ์ฌ Content-Type ํค๋๋ฅผ ํฌํจํ๋ฉฐ, ํ
์คํธ ํ์
์ ๊ฒฝ์ฐ ๋ฌธ์ ์งํฉ์ ์ถ๊ฐ ํฉ๋๋ค.
+FastAPI(์ ํํ๋ Starlette)๊ฐ ์๋์ผ๋ก Content-Length ํค๋๋ฅผ ํฌํจ์ํต๋๋ค. ๋ํ `media_type`์ ๊ธฐ๋ฐํ์ฌ Content-Type ํค๋๋ฅผ ํฌํจํ๋ฉฐ, ํ
์คํธ ํ์
์ ๊ฒฝ์ฐ ๋ฌธ์ ์งํฉ์ ์ถ๊ฐํฉ๋๋ค.
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
์ด๋ ์์์ ์ค๋ช
ํ๋ฏ์ด **FastAPI**์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์๋ต ํ์์
๋๋ค.
-### `ORJSONResponse` { #orjsonresponse }
-
- <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>์ ์ฌ์ฉํ์ฌ ๋น ๋ฅธ JSON ์๋ต์ ์ ๊ณตํ๋ ๋์์
๋๋ค. ์์์ ์ค๋ช
ํ ๋ด์ฉ๊ณผ ๊ฐ์ต๋๋ค.
-
-/// info | ์ ๋ณด
-
-์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด `orjson`์ ์ค์นํด์ผํฉ๋๋ค. ์: `pip install orjson`.
-
-///
-
-### `UJSONResponse` { #ujsonresponse }
-
-<a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>์ ์ฌ์ฉํ ๋ ๋ค๋ฅธ JSON ์๋ต ํ์์
๋๋ค.
-
-/// info | ์ ๋ณด
-
-์ด ์๋ต์ ์ฌ์ฉํ๋ ค๋ฉด `ujson`์ ์ค์นํด์ผํฉ๋๋ค. ์: `pip install ujson`.
-
-///
+/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
-/// warning | ๊ฒฝ๊ณ
+ํ์ง๋ง ์๋ต ๋ชจ๋ธ ๋๋ ๋ฐํ ํ์
์ ์ ์ธํ ๊ฒฝ์ฐ, ํด๋น ๋ชจ๋ธ์ด ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํ๋ ๋ฐ ์ง์ ์ฌ์ฉ๋๋ฉฐ, ์ฌ๋ฐ๋ฅธ JSON ๋ฏธ๋์ด ํ์
์ ์๋ต์ด `JSONResponse` ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ฐ๋ก ๋ฐํ๋ฉ๋๋ค.
-`ujson` ์ ์ผ๋ถ ์์ธ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์์ด Python ๋ด์ฅ ๊ตฌํ๋ณด๋ค ๋ ์๊ฒฉํฉ๋๋ค.
-
-///
-
-{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
-
-/// tip | ํ
-
-`ORJSONResponse`๊ฐ ๋ ๋น ๋ฅธ ๋์์ผ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.
+์ด ๋ฐฉ์์ด ์ต์์ ์ฑ๋ฅ์ ์ป๋ ์ด์์ ์ธ ๋ฐฉ๋ฒ์
๋๋ค.
///
HTTP ๋ฆฌ๋๋ ์
์๋ต์ ๋ฐํํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ํ ์ฝ๋๋ 307(์์ ๋ฆฌ๋๋ ์
)์ผ๋ก ์ค์ ๋ฉ๋๋ค.
-`RedirectResponse`๋ฅผ ์ง์ ๋ฐํํ ์ ์์ต๋๋ค.
+`RedirectResponse`๋ฅผ ์ง์ ๋ฐํํ ์ ์์ต๋๋ค:
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
์ด ๊ฒฝ์ฐ, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ํจ์์์ URL์ ์ง์ ๋ฐํํ ์ ์์ต๋๋ค.
-์ด ๊ฒฝ์ฐ, ์ฌ์ฉ๋๋ `status_code`๋ `RedirectResponse`์ ๊ธฐ๋ณธ๊ฐ์ธ `307` ์
๋๋ค.
+์ด ๊ฒฝ์ฐ, ์ฌ์ฉ๋๋ `status_code`๋ `RedirectResponse`์ ๊ธฐ๋ณธ๊ฐ์ธ `307`์
๋๋ค.
---
### `StreamingResponse` { #streamingresponse }
-๋น๋๊ธฐ ์ ๋๋ ์ดํฐ ๋๋ ์ผ๋ฐ ์ ๋๋ ์ดํฐ/์ดํฐ๋ ์ดํฐ๋ฅผ ๋ฐ์ ์๋ต ๋ณธ๋ฌธ์ ์คํธ๋ฆฌ๋ฐ ํฉ๋๋ค.
-
-{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
-
-#### ํ์ผ๊ณผ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ `StreamingResponse` { #using-streamingresponse-with-file-like-objects }
+๋น๋๊ธฐ ์ ๋๋ ์ดํฐ ๋๋ ์ผ๋ฐ ์ ๋๋ ์ดํฐ/์ดํฐ๋ ์ดํฐ(`yield`๊ฐ ์๋ ํจ์)๋ฅผ ๋ฐ์ ์๋ต ๋ณธ๋ฌธ์ ์คํธ๋ฆฌ๋ฐํฉ๋๋ค.
-<a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> ๊ฐ์ฒด(์: `open()`์ผ๋ก ๋ฐํ๋ ๊ฐ์ฒด)๊ฐ ์๋ ๊ฒฝ์ฐ, ํด๋น file-like ๊ฐ์ฒด๋ฅผ ๋ฐ๋ณต(iterate)ํ๋ ์ ๋๋ ์ดํฐ ํจ์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
+{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *}
-์ด ๋ฐฉ์์ผ๋ก, ํ์ผ ์ ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋จผ์ ์ฝ์ด๋ค์ผ ํ์ ์์ด, ์ ๋๋ ์ดํฐ ํจ์๋ฅผ `StreamingResponse`์ ์ ๋ฌํ์ฌ ๋ฐํํ ์ ์์ต๋๋ค.
-
-์ด ๋ฐฉ์์ ํด๋ผ์ฐ๋ ์คํ ๋ฆฌ์ง, ๋น๋์ค ์ฒ๋ฆฌ ๋ฑ์ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
+/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
-{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
+`async` ์์
์ `await`์ ๋๋ฌํ์ ๋๋ง ์ทจ์๋ ์ ์์ต๋๋ค. `await`๊ฐ ์์ผ๋ฉด ์ ๋๋ ์ดํฐ(`yield`๊ฐ ์๋ ํจ์)๋ ์ ๋๋ก ์ทจ์๋ ์ ์๊ณ , ์ทจ์๊ฐ ์์ฒญ๋ ํ์๋ ๊ณ์ ์คํ๋ ์ ์์ต๋๋ค.
-1. ์ด๊ฒ์ด ์ ๋๋ ์ดํฐ ํจ์์
๋๋ค. `yield` ๋ฌธ์ ํฌํจํ๊ณ ์์ผ๋ฏ๋ก "์ ๋๋ ์ดํฐ ํจ์"์
๋๋ค.
-2. `with` ๋ธ๋ก์ ์ฌ์ฉํจ์ผ๋ก์จ, ์ ๋๋ ์ดํฐ ํจ์๊ฐ ์๋ฃ๋ ํ ํ์ผ๊ณผ ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋ซํ๋๋ก ํฉ๋๋ค. ์ฆ, ์๋ต ์ ์ก์ด ๋๋ ํ ๋ซํ๋๋ค.
-3. ์ด `yield from`์ ํจ์๊ฐ `file_like`๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ณต(iterate)ํ๋๋ก ํฉ๋๋ค. ๋ฐ๋ณต๋ ๊ฐ ๋ถ๋ถ์ ์ด ์ ๋๋ ์ดํฐ ํจ์(`iterfile`)์์ ์์ฑ๋ ๊ฒ์ฒ๋ผ `yield` ๋ฉ๋๋ค.
+์ด ์์ ์์ ๋ ์ด๋ค `await`๋ ํ์ํ์ง ์์ผ๋ฏ๋ก, ์ด๋ฒคํธ ๋ฃจํ๊ฐ ์ทจ์๋ฅผ ์ฒ๋ฆฌํ ๊ธฐํ๋ฅผ ์ฃผ๊ธฐ ์ํด `await anyio.sleep(0)`๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- รฌ\9dยดรซย \87รชยฒ\8c รญ\95\98รซยฉยด "รฌ\83\9dรฌ\84ยฑ(generating)" รฌ\9e\91รฌ\97\85รฌ\9d\84 รซ\82ยดรซยถ\80รฌย \81รฌ\9cยผรซยก\9c รซ\8bยครซยฅยธ รซยฌยดรฌ\96ยธรชยฐ\80รฌ\97\90 รฌ\9c\84รฌ\9e\84รญ\95\98รซ\8a\94 รฌย \9cรซ\84\88รซย \88รฌ\9dยดรญ\84ยฐ รญ\95ยจรฌ\88\98รชยฐ\80 รซ\90ยฉรซ\8b\88รซ\8bยค.
+รซ\8c\80รชยท\9cรซยชยจ รซ\98\90รซ\8a\94 รซยฌยดรญ\95\9c รฌ\8aยครญ\8aยธรซยฆยผรฌ\97\90รฌ\84\9cรซ\8a\94 รซ\8d\94รฌ\9aยฑ รฌยค\91รฌ\9a\94รญ\95ยฉรซ\8b\88รซ\8bยค.
- ์ด ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด `with` ๋ธ๋ก ์์์ ํ์ผ์ ์ด ์ ์์ด, ์์
์ด ์๋ฃ๋ ํ ํ์ผ๊ณผ ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋ซํ๋ ๊ฒ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
+///
/// tip | ํ
-์ฌ๊ธฐ์ ํ์ค `open()`์ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ `async`์ `await`๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ๊ฒฝ๋ก ์ฒ๋ฆฌ๋ ์ผ๋ฐ `def`๋ก ์ ์ธํฉ๋๋ค.
+`StreamingResponse`๋ฅผ ์ง์ ๋ฐํํ๋ ๋์ , [๋ฐ์ดํฐ ์คํธ๋ฆฌ๋ฐ](./stream-data.md)์์์ ์คํ์ผ์ ๋ฐ๋ฅด๋ ๊ฒ์ด ๋ ํธ๋ฆฌํ๋ฉฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ทจ์ ์ฒ๋ฆฌ๋ฅผ ํด์ค๋๋ค.
+
+JSON Lines๋ฅผ ์คํธ๋ฆฌ๋ฐํ๋ค๋ฉด, [JSON Lines ์คํธ๋ฆฌ๋ฐ](../tutorial/stream-json-lines.md) ํํ ๋ฆฌ์ผ์ ํ์ธํ์ธ์.
///
`Response`๋ฅผ ์์๋ฐ์ ์ฌ์ฉ์ ์ ์ ์๋ต ํด๋์ค๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-์๋ฅผ ๋ค์ด, ํฌํจ๋ `ORJSONResponse` ํด๋์ค์์ ์ฌ์ฉ๋์ง ์๋ ์ค์ ์ผ๋ก <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>์ ์ฌ์ฉํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค.
+์๋ฅผ ๋ค์ด, [`orjson`](https://github.com/ijl/orjson)์ ์ผ๋ถ ์ค์ ๊ณผ ํจ๊ป ์ฌ์ฉํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค.
-รซยง\8cรฌ\95ยฝ รซ\93ยครฌ\97ยฌรฌ\93ยฐรชยธยฐ รซยฐ\8f รญ\8fยฌรซยงยทรซ\90\9c JSONรฌ\9d\84 รซยฐ\98รญ\99\98รญ\95\98รชยณย รฌ\8bยถรซ\8bยครซยฉยด, `orjson.OPT_INDENT_2` รฌ\98ยตรฌ\85\98รฌ\9d\84 ์ฌ์ฉํ ์ ์์ต๋๋ค.
+รซ\93ยครฌ\97ยฌรฌ\93ยฐรชยธยฐ รซยฐ\8f รญ\8fยฌรซยงยทรซ\90\9c JSONรฌ\9d\84 รซยฐ\98รญ\99\98รญ\95\98รชยณย รฌ\8bยถรซ\8bยครซยฉยด, orjson รฌ\98ยตรฌ\85\98 `orjson.OPT_INDENT_2`รซยฅยผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
`CustomORJSONResponse`๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ํต์ฌ์ `Response.render(content)` ๋ฉ์๋๋ฅผ ์์ฑํ์ฌ ๋ด์ฉ์ `bytes`๋ก ๋ฐํํ๋ ๊ฒ์
๋๋ค:
๋ฌผ๋ก JSON ํฌ๋งทํ
๋ณด๋ค ๋ ์ ์ฉํ๊ฒ ํ์ฉํ ๋ฐฉ๋ฒ์ ์ฐพ์ ์ ์์ ๊ฒ์
๋๋ค. ๐
+### `orjson` ๋๋ ์๋ต ๋ชจ๋ธ { #orjson-or-response-model }
+
+์ฑ๋ฅ์ด ๋ชฉ์ ์ด๋ผ๋ฉด, `orjson` ์๋ต์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค [์๋ต ๋ชจ๋ธ](../tutorial/response-model.md)์ ์ฌ์ฉํ๋ ํธ์ด ๋ ๋์ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
+
+์๋ต ๋ชจ๋ธ์ ์ฌ์ฉํ๋ฉด FastAPI๋ ์ค๊ฐ ๋จ๊ณ(์: `jsonable_encoder`๋ก์ ๋ณํ) ์์ด Pydantic์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํฉ๋๋ค. ์ด๋ฐ ์ค๊ฐ ๋จ๊ณ๋ ๋ค๋ฅธ ๊ฒฝ์ฐ์ ๋ฐ์ํฉ๋๋ค.
+
+๊ทธ๋ฆฌ๊ณ ๋ด๋ถ์ ์ผ๋ก Pydantic์ JSON ์ง๋ ฌํ๋ฅผ ์ํด `orjson`๊ณผ ๋์ผํ Rust ๊ธฐ๋ฐ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๋ฏ๋ก, ์๋ต ๋ชจ๋ธ๋ง์ผ๋ก๋ ์ด๋ฏธ ์ต์์ ์ฑ๋ฅ์ ์ป๊ฒ ๋ฉ๋๋ค.
+
## ๊ธฐ๋ณธ ์๋ต ํด๋์ค { #default-response-class }
-**FastAPI** ํด๋์ค ๊ฐ์ฒด ๋๋ `APIRouter`๋ฅผ ์์ฑํ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ ์๋ต ํด๋์ค๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
+**FastAPI** ํด๋์ค ์ธ์คํด์ค ๋๋ `APIRouter`๋ฅผ ์์ฑํ ๋ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ ์๋ต ํด๋์ค๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์ ์ํ๋ ๋งค๊ฐ๋ณ์๋ `default_response_class`์
๋๋ค.
-์๋ ์์ ์์ **FastAPI**๋ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ๊ธฐ๋ณธ์ ์ผ๋ก `JSONResponse` ๋์ `ORJSONResponse`๋ฅผ ์ฌ์ฉํฉ๋๋ค.
+์๋ ์์ ์์ **FastAPI**๋ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ JSON ๋์ ๊ธฐ๋ณธ์ ์ผ๋ก `HTMLResponse`๋ฅผ ์ฌ์ฉํฉ๋๋ค.
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
## ์ถ๊ฐ ๋ฌธ์ํ { #additional-documentation }
-OpenAPI์์ `responses`๋ฅผ ์ฌ์ฉํ์ฌ ๋ฏธ๋์ด ํ์
๋ฐ ๊ธฐํ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ ์ธํ ์๋ ์์ต๋๋ค: [OpenAPI์์ ์ถ๊ฐ ์๋ต](additional-responses.md){.internal-link target=_blank}.
+OpenAPI์์ `responses`๋ฅผ ์ฌ์ฉํ์ฌ ๋ฏธ๋์ด ํ์
๋ฐ ๊ธฐํ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ ์ธํ ์๋ ์์ต๋๋ค: [OpenAPI์์ ์ถ๊ฐ ์๋ต](additional-responses.md).
FastAPI๋ **Pydantic** ์์ ๊ตฌ์ถ๋์ด ์์ผ๋ฉฐ, ์ง๊ธ๊น์ง๋ Pydantic ๋ชจ๋ธ์ ์ฌ์ฉํด ์์ฒญ๊ณผ ์๋ต์ ์ ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ ธ์ต๋๋ค.
-ํ์ง๋ง FastAPI๋ <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์ง์ํฉ๋๋ค:
+ํ์ง๋ง FastAPI๋ [`dataclasses`](https://docs.python.org/3/library/dataclasses.html)๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์ง์ํฉ๋๋ค:
{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *}
-์ด๋ **Pydantic** ๋๋ถ์ ์ฌ์ ํ ์ง์๋๋๋ฐ, Pydantic์ด <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses`์ ๋ํ ๋ด๋ถ ์ง์</a>์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์
๋๋ค.
+์ด๋ **Pydantic** ๋๋ถ์ ์ฌ์ ํ ์ง์๋๋๋ฐ, Pydantic์ด [`dataclasses`์ ๋ํ ๋ด๋ถ ์ง์](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel)์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ฐ๋ผ์ ์ ์ฝ๋์ฒ๋ผ Pydantic์ ๋ช
์์ ์ผ๋ก ์ฌ์ฉํ์ง ์๋๋ผ๋, FastAPI๋ Pydantic์ ์ฌ์ฉํด ํ์ค dataclasses๋ฅผ Pydantic์ dataclasses ๋ณํ์ผ๋ก ๋ณํํฉ๋๋ค.
์ด๋ Pydantic ๋ชจ๋ธ์ ์ฌ์ฉํ ๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ค์ ๋ก๋ ๋ด๋ถ์ ์ผ๋ก๋ Pydantic์ ์ฌ์ฉํด ๊ฐ์ ๋ฐฉ์์ผ๋ก ๊ตฌํ๋ฉ๋๋ค.
-/// info | ์ ๋ณด
+/// info
dataclasses๋ Pydantic ๋ชจ๋ธ์ด ํ ์ ์๋ ๋ชจ๋ ๊ฒ์ ํ ์๋ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
์ธ์ ๋์ฒ๋ผ FastAPI์์๋ ํ์์ ๋ฐ๋ผ `def`์ `async def`๋ฅผ ์กฐํฉํด ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ด๋ค ๊ฒ์ ์ธ์ ์ฌ์ฉํด์ผ ํ๋์ง ๋ค์ ํ์ธํ๊ณ ์ถ๋ค๋ฉด, [`async`์ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ๋ฌธ์์ _"๊ธํ์ ๊ฐ์?"_ ์น์
์ ํ์ธํ์ธ์.
+ ์ด๋ค ๊ฒ์ ์ธ์ ์ฌ์ฉํด์ผ ํ๋์ง ๋ค์ ํ์ธํ๊ณ ์ถ๋ค๋ฉด, [`async`์ `await`](../async.md#in-a-hurry) ๋ฌธ์์ _"๊ธํ์ ๊ฐ์?"_ ์น์
์ ํ์ธํ์ธ์.
9. ์ด *๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*๋ dataclasses๋ฅผ(๋ฌผ๋ก ๋ฐํํ ์๋ ์์ง๋ง) ๋ฐํํ์ง ์๊ณ , ๋ด๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๋์
๋๋ฆฌ๋ค์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํฉ๋๋ค.
`dataclasses`๋ฅผ ๋ค๋ฅธ Pydantic ๋ชจ๋ธ๊ณผ ์กฐํฉํ๊ฑฐ๋, ์ด๋ฅผ ์์ํ๊ฑฐ๋, ์ฌ๋ฌ๋ถ์ ๋ชจ๋ธ์ ํฌํจํ๋ ๋ฑ์ ์์
๋ ํ ์ ์์ต๋๋ค.
-์์ธํ ๋ด์ฉ์ <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">dataclasses์ ๊ดํ Pydantic ๋ฌธ์</a>๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+์์ธํ ๋ด์ฉ์ [dataclasses์ ๊ดํ Pydantic ๋ฌธ์](https://docs.pydantic.dev/latest/concepts/dataclasses/)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
## ๋ฒ์ { #version }
ํธ๊ธฐ์ฌ ๋ง์ ๋ถ๋ค์ ์ํ ๊ธฐ์ ์ ์ธ ์ธ๋ถ์ฌํญ์
๋๋ค. ๐ค
-๋ด๋ถ์ ์ผ๋ก ASGI ๊ธฐ์ ์ฌ์์์๋ ์ด๊ฒ์ด <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Lifespan Protocol</a>์ ์ผ๋ถ์ด๋ฉฐ, `startup`๊ณผ `shutdown`์ด๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ํฉ๋๋ค.
+๋ด๋ถ์ ์ผ๋ก ASGI ๊ธฐ์ ์ฌ์์์๋ ์ด๊ฒ์ด [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)์ ์ผ๋ถ์ด๋ฉฐ, `startup`๊ณผ `shutdown`์ด๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ํฉ๋๋ค.
/// info | ์ ๋ณด
-Starlette `lifespan` ํธ๋ค๋ฌ์ ๋ํด์๋ <a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Starlette์ Lifespan ๋ฌธ์</a>์์ ๋ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
+Starlette `lifespan` ํธ๋ค๋ฌ์ ๋ํด์๋ [Starlette์ Lifespan ๋ฌธ์](https://www.starlette.dev/lifespan/)์์ ๋ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
๋ํ ์ฝ๋์ ๋ค๋ฅธ ์์ญ์์ ์ฌ์ฉํ ์ ์๋ lifespan ์ํ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ ํฌํจ๋์ด ์์ต๋๋ค.
## ์๋ธ ์ ํ๋ฆฌ์ผ์ด์
{ #sub-applications }
-๐จ ์ด lifespan ์ด๋ฒคํธ(startup ๋ฐ shutdown)๋ ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํด์๋ง ์คํ๋๋ฉฐ, [์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- Mounts](sub-applications.md){.internal-link target=_blank}์๋ ์คํ๋์ง ์์์ ์ ์ํ์ธ์.
+๐จ ์ด lifespan ์ด๋ฒคํธ(startup ๋ฐ shutdown)๋ ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ํด์๋ง ์คํ๋๋ฉฐ, [์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- Mounts](sub-applications.md)์๋ ์คํ๋์ง ์์์ ์ ์ํ์ธ์.
## ์คํ ์์ค SDK ์์ฑ๊ธฐ { #open-source-sdk-generators }
-๋ค์ํ๊ฒ ํ์ฉํ ์ ์๋ ์ต์
์ผ๋ก <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>๊ฐ ์์ผ๋ฉฐ, **๋ค์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด**๋ฅผ ์ง์ํ๊ณ OpenAPI ์ฌ์์ผ๋ก๋ถํฐ SDK๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
+๋ค์ํ๊ฒ ํ์ฉํ ์ ์๋ ์ต์
์ผ๋ก [OpenAPI Generator](https://openapi-generator.tech/)๊ฐ ์์ผ๋ฉฐ, **๋ค์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด**๋ฅผ ์ง์ํ๊ณ OpenAPI ์ฌ์์ผ๋ก๋ถํฐ SDK๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
-**TypeScript ํด๋ผ์ด์ธํธ**์ ๊ฒฝ์ฐ <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a>๋ TypeScript ์ํ๊ณ์ ์ต์ ํ๋ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ชฉ์ ์ ๋ง๊ฒ ์ค๊ณ๋ ์๋ฃจ์
์
๋๋ค.
+**TypeScript ํด๋ผ์ด์ธํธ**์ ๊ฒฝ์ฐ [Hey API](https://heyapi.dev/)๋ TypeScript ์ํ๊ณ์ ์ต์ ํ๋ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ชฉ์ ์ ๋ง๊ฒ ์ค๊ณ๋ ์๋ฃจ์
์
๋๋ค.
-๋ ๋ง์ SDK ์์ฑ๊ธฐ๋ <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+๋ ๋ง์ SDK ์์ฑ๊ธฐ๋ [OpenAPI.Tools](https://openapi.tools/#sdk)์์ ํ์ธํ ์ ์์ต๋๋ค.
/// tip | ํ
์ด ์น์
์์๋ FastAPI๋ฅผ ํ์ํ๋ ํ์ฌ๋ค์ด ์ ๊ณตํ๋ **๋ฒค์ฒ ํฌ์ ๊ธฐ๋ฐ** ๋ฐ **๊ธฐ์
์ง์** ์๋ฃจ์
์ ์๊ฐํฉ๋๋ค. ์ด ์ ํ๋ค์ ๊ณ ํ์ง๋ก ์์ฑ๋ SDK์ ๋ํด **์ถ๊ฐ ๊ธฐ๋ฅ**๊ณผ **ํตํฉ**์ ์ ๊ณตํฉ๋๋ค.
-โจ [**FastAPI ํ์ํ๊ธฐ**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โจ๋ฅผ ํตํด, ์ด ํ์ฌ๋ค์ ํ๋ ์์ํฌ์ ๊ทธ **์ํ๊ณ**๊ฐ ๊ฑด๊ฐํ๊ณ **์ง์ ๊ฐ๋ฅ**ํ๊ฒ ์ ์ง๋๋๋ก ๋์ต๋๋ค.
+โจ [**FastAPI ํ์ํ๊ธฐ**](../help-fastapi.md#sponsor-the-author) โจ๋ฅผ ํตํด, ์ด ํ์ฌ๋ค์ ํ๋ ์์ํฌ์ ๊ทธ **์ํ๊ณ**๊ฐ ๊ฑด๊ฐํ๊ณ **์ง์ ๊ฐ๋ฅ**ํ๊ฒ ์ ์ง๋๋๋ก ๋์ต๋๋ค.
๋ํ ์ด๋ค์ ํ์์ FastAPI **์ปค๋ฎค๋ํฐ**(์ฌ๋ฌ๋ถ)์ ๋ํ ๊ฐํ ํ์ ์ ๋ณด์ฌ์ฃผ๋ฉฐ, **์ข์ ์๋น์ค**๋ฅผ ์ ๊ณตํ๋ ๊ฒ๋ฟ ์๋๋ผ, ๊ฒฌ๊ณ ํ๊ณ ํ๋ฐํ ํ๋ ์์ํฌ์ธ FastAPI๋ฅผ ์ง์ํ๋ ๋ฐ์๋ ๊ด์ฌ์ด ์์์ ๋ํ๋
๋๋ค. ๐
์๋ฅผ ๋ค์ด ๋ค์์ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค:
-* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
-* <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
-* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
+* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship)
+* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral)
+* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi)
์ด ์ค ์ผ๋ถ๋ ์คํ ์์ค์ด๊ฑฐ๋ ๋ฌด๋ฃ ํฐ์ด๋ฅผ ์ ๊ณตํ๋ฏ๋ก, ๋น์ฉ ๋ถ๋ด ์์ด ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค. ๋ค๋ฅธ ์์ฉ SDK ์์ฑ๊ธฐ๋ ์์ผ๋ฉฐ ์จ๋ผ์ธ์์ ์ฐพ์ ์ ์์ต๋๋ค. ๐ค
{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
-*path operation*์์ ์์ฒญ ํ์ด๋ก๋์ ์๋ต ํ์ด๋ก๋์ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ `Item`, `ResponseMessage` ๋ชจ๋ธ๋ก ์ ์ํ๊ณ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ์ธ์.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ์์ฒญ ํ์ด๋ก๋์ ์๋ต ํ์ด๋ก๋์ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ `Item`, `ResponseMessage` ๋ชจ๋ธ๋ก ์ ์ํ๊ณ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ์ธ์.
### API ๋ฌธ์ { #api-docs }
์ด ๋ช
๋ น์ `./src/client`์ TypeScript SDK๋ฅผ ์์ฑํฉ๋๋ค.
-<a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">`@hey-api/openapi-ts` ์ค์น ๋ฐฉ๋ฒ</a>๊ณผ <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ</a>์ ํด๋น ์น์ฌ์ดํธ์์ ํ์ธํ ์ ์์ต๋๋ค.
+[`@hey-api/openapi-ts` ์ค์น ๋ฐฉ๋ฒ](https://heyapi.dev/openapi-ts/get-started)๊ณผ [์์ฑ๋ ๊ฒฐ๊ณผ๋ฌผ](https://heyapi.dev/openapi-ts/output)์ ํด๋น ์น์ฌ์ดํธ์์ ํ์ธํ ์ ์์ต๋๋ค.
### SDK ์ฌ์ฉํ๊ธฐ { #using-the-sdk }
## ํ๊ทธ๊ฐ ์๋ FastAPI ์ฑ { #fastapi-app-with-tags }
-๋๋ถ๋ถ์ ๊ฒฝ์ฐ FastAPI ์ฑ์ ๋ ์ปค์ง๊ณ , ์๋ก ๋ค๋ฅธ *path operations* ๊ทธ๋ฃน์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ํ๊ทธ๋ฅผ ์ฌ์ฉํ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
+๋๋ถ๋ถ์ ๊ฒฝ์ฐ FastAPI ์ฑ์ ๋ ์ปค์ง๊ณ , ์๋ก ๋ค๋ฅธ *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๊ทธ๋ฃน์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ํ๊ทธ๋ฅผ ์ฌ์ฉํ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
์๋ฅผ ๋ค์ด **items** ์น์
๊ณผ **users** ์น์
์ด ์๊ณ , ์ด๋ฅผ ํ๊ทธ๋ก ๋ถ๋ฆฌํ ์ ์์ต๋๋ค:
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```
-...์ด๋ ํด๋ผ์ด์ธํธ ์์ฑ๊ธฐ๊ฐ ๊ฐ *path operation*์ ๋ํด OpenAPI ๋ด๋ถ์ **operation ID**๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค.
+...์ด๋ ํด๋ผ์ด์ธํธ ์์ฑ๊ธฐ๊ฐ ๊ฐ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ๋ํด OpenAPI ๋ด๋ถ์ **operation ID**๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค.
-OpenAPI๋ ๋ชจ๋ *path operations* ์ ์ฒด์์ operation ID๊ฐ ๊ฐ๊ฐ ์ ์ผํด์ผ ํ๋ค๊ณ ์๊ตฌํฉ๋๋ค. ๊ทธ๋์ FastAPI๋ operation ID๊ฐ ์ ์ผํ๋๋ก **ํจ์ ์ด๋ฆ**, **๊ฒฝ๋ก**, **HTTP method/operation**์ ์กฐํฉํด operation ID๋ฅผ ์์ฑํฉ๋๋ค.
+OpenAPI๋ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ ์ฒด์์ operation ID๊ฐ ๊ฐ๊ฐ ์ ์ผํด์ผ ํ๋ค๊ณ ์๊ตฌํฉ๋๋ค. ๊ทธ๋์ FastAPI๋ operation ID๊ฐ ์ ์ผํ๋๋ก **ํจ์ ์ด๋ฆ**, **๊ฒฝ๋ก**, **HTTP method/operation**์ ์กฐํฉํด operation ID๋ฅผ ์์ฑํฉ๋๋ค.
ํ์ง๋ง ๋ค์์์ ์ด๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. ๐ค
์ด ๊ฒฝ์ฐ operation ID๊ฐ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก๋ **์ ์ผ**ํ๋๋ก ๋ณด์ฅํด์ผ ํฉ๋๋ค.
-์๋ฅผ ๋ค์ด ๊ฐ *path operation*์ด ํ๊ทธ๋ฅผ ๊ฐ๋๋ก ํ ๋ค์, **ํ๊ทธ**์ *path operation* **์ด๋ฆ**(ํจ์ ์ด๋ฆ)์ ๊ธฐ๋ฐ์ผ๋ก operation ID๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
+์๋ฅผ ๋ค์ด ๊ฐ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ด ํ๊ทธ๋ฅผ ๊ฐ๋๋ก ํ ๋ค์, **ํ๊ทธ**์ *๊ฒฝ๋ก ์ฒ๋ฆฌ* **์ด๋ฆ**(ํจ์ ์ด๋ฆ)์ ๊ธฐ๋ฐ์ผ๋ก operation ID๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
### ์ ์ผ ID ์์ฑ ํจ์ ์ปค์คํฐ๋ง์ด์ง { #custom-generate-unique-id-function }
-FastAPI๋ ๊ฐ *path operation*์ ๋ํด **์ ์ผ ID**๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ด๋ **operation ID** ๋ฐ ์์ฒญ/์๋ต์ ํ์ํ ์ปค์คํ
๋ชจ๋ธ ์ด๋ฆ์๋ ์ฌ์ฉ๋ฉ๋๋ค.
+FastAPI๋ ๊ฐ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ๋ํด **์ ์ผ ID**๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ด๋ **operation ID** ๋ฐ ์์ฒญ/์๋ต์ ํ์ํ ์ปค์คํ
๋ชจ๋ธ ์ด๋ฆ์๋ ์ฌ์ฉ๋ฉ๋๋ค.
์ด ํจ์๋ฅผ ์ปค์คํฐ๋ง์ด์งํ ์ ์์ต๋๋ค. ์ด ํจ์๋ `APIRoute`๋ฅผ ๋ฐ์ ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
-์๋ฅผ ๋ค์ด ์๋์์๋ ์ฒซ ๋ฒ์งธ ํ๊ทธ(๋๋ถ๋ถ ํ๊ทธ๋ ํ๋๋ง ์์ ๊ฒ์
๋๋ค)์ *path operation* ์ด๋ฆ(ํจ์ ์ด๋ฆ)์ ์ฌ์ฉํฉ๋๋ค.
+์๋ฅผ ๋ค์ด ์๋์์๋ ์ฒซ ๋ฒ์งธ ํ๊ทธ(๋๋ถ๋ถ ํ๊ทธ๋ ํ๋๋ง ์์ ๊ฒ์
๋๋ค)์ *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ด๋ฆ(ํจ์ ์ด๋ฆ)์ ์ฌ์ฉํฉ๋๋ค.
๊ทธ ๋ค์ ์ด ์ปค์คํ
ํจ์๋ฅผ `generate_unique_id_function` ๋งค๊ฐ๋ณ์๋ก **FastAPI**์ ์ ๋ฌํ ์ ์์ต๋๋ค:
๋ํ ๋ชจ๋ ๊ฒ์ ๋ํด **์ธ๋ผ์ธ ์ค๋ฅ**๋ ํ์ธํ ์ ์์ต๋๋ค.
-๊ทธ๋ฆฌ๊ณ ๋ฐฑ์๋ ์ฝ๋๋ฅผ ์
๋ฐ์ดํธํ ๋ค ํ๋ก ํธ์๋๋ฅผ **์ฌ์์ฑ(regenerate)**ํ๋ฉด, ์ *path operations*๊ฐ ๋ฉ์๋๋ก ์ถ๊ฐ๋๊ณ ๊ธฐ์กด ๊ฒ์ ์ ๊ฑฐ๋๋ฉฐ, ๊ทธ ๋ฐ์ ๋ณ๊ฒฝ ์ฌํญ๋ ์์ฑ๋ ์ฝ๋์ ๋ฐ์๋ฉ๋๋ค. ๐ค
+๊ทธ๋ฆฌ๊ณ ๋ฐฑ์๋ ์ฝ๋๋ฅผ ์
๋ฐ์ดํธํ ๋ค ํ๋ก ํธ์๋๋ฅผ **์ฌ์์ฑ(regenerate)**ํ๋ฉด, ์ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ ๋ฉ์๋๋ก ์ถ๊ฐ๋๊ณ ๊ธฐ์กด ๊ฒ์ ์ ๊ฑฐ๋๋ฉฐ, ๊ทธ ๋ฐ์ ๋ณ๊ฒฝ ์ฌํญ๋ ์์ฑ๋ ์ฝ๋์ ๋ฐ์๋ฉ๋๋ค. ๐ค
์ด๋ ๋ฌด์ธ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๊ทธ ๋ณ๊ฒฝ์ด ํด๋ผ์ด์ธํธ ์ฝ๋์๋ ์๋์ผ๋ก **๋ฐ์**๋๋ค๋ ๋ป์
๋๋ค. ๋ํ ํด๋ผ์ด์ธํธ๋ฅผ **๋น๋(build)**ํ๋ฉด ์ฌ์ฉ๋ ๋ฐ์ดํฐ๊ฐ **๋ถ์ผ์น(mismatch)**ํ ๊ฒฝ์ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
## ์ถ๊ฐ ๊ธฐ๋ฅ { #additional-features }
-๋ฉ์ธ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](../tutorial/index.md){.internal-link target=_blank}๋ ์ฌ๋ฌ๋ถ์ด **FastAPI**์ ๋ชจ๋ ์ฃผ์ ๊ธฐ๋ฅ์ ๋๋ฌ๋ณด์๊ธฐ์ ์ถฉ๋ถํ ๊ฒ์
๋๋ค.
+๋ฉ์ธ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](../tutorial/index.md)๋ ์ฌ๋ฌ๋ถ์ด **FastAPI**์ ๋ชจ๋ ์ฃผ์ ๊ธฐ๋ฅ์ ๋๋ฌ๋ณด์๊ธฐ์ ์ถฉ๋ถํ ๊ฒ์
๋๋ค.
์ด์ด์ง๋ ์ฅ์์๋ ์ฌ๋ฌ๋ถ์ด ๋ค๋ฅธ ์ต์
, ๊ตฌ์ฑ ๋ฐ ์ถ๊ฐ ๊ธฐ๋ฅ์ ๋ณด์ค ์ ์์ต๋๋ค.
## ์์ต์๋ฅผ ๋จผ์ ์ฝ์ผ์ญ์์ค { #read-the-tutorial-first }
-์ฌ๋ฌ๋ถ์ ๋ฉ์ธ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](../tutorial/index.md){.internal-link target=_blank}์ ์ง์์ผ๋ก **FastAPI**์ ๋๋ถ๋ถ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ค ์ ์์ต๋๋ค.
+์ฌ๋ฌ๋ถ์ ๋ฉ์ธ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](../tutorial/index.md)์ ์ง์์ผ๋ก **FastAPI**์ ๋๋ถ๋ถ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ค ์ ์์ต๋๋ค.
์ด์ด์ง๋ ์ฅ๋ค์ ์ฌ๋ฌ๋ถ์ด ๋ฉ์ธ ์์ต์ - ์ฌ์ฉ์ ์๋ด์๋ฅผ ์ด๋ฏธ ์ฝ์ผ์
จ์ผ๋ฉฐ ์ฃผ์ ์์ด๋์ด๋ฅผ ์๊ณ ๊ณ์ ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
# ๊ณ ๊ธ Middleware { #advanced-middleware }
-๋ฉ์ธ ํํ ๋ฆฌ์ผ์์ ์ ํ๋ฆฌ์ผ์ด์
์ [์ปค์คํ
Middleware](../tutorial/middleware.md){.internal-link target=_blank}๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ฝ์์ต๋๋ค.
+๋ฉ์ธ ํํ ๋ฆฌ์ผ์์ ์ ํ๋ฆฌ์ผ์ด์
์ [์ปค์คํ
Middleware](../tutorial/middleware.md)๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ฝ์์ต๋๋ค.
-๊ทธ๋ฆฌ๊ณ [`CORSMiddleware`๋ก CORS ์ฒ๋ฆฌํ๊ธฐ](../tutorial/cors.md){.internal-link target=_blank}๋ ์ฝ์์ต๋๋ค.
+๊ทธ๋ฆฌ๊ณ [`CORSMiddleware`๋ก CORS ์ฒ๋ฆฌํ๊ธฐ](../tutorial/cors.md)๋ ์ฝ์์ต๋๋ค.
์ด ์น์
์์๋ ๋ค๋ฅธ middleware๋ค์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์๋ฅผ ๋ค์ด:
-* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn์ `ProxyHeadersMiddleware`</a>
-* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
+* [Uvicorn์ `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py)
+* [MessagePack](https://github.com/florimondmanca/msgpack-asgi)
-์ฌ์ฉ ๊ฐ๋ฅํ ๋ค๋ฅธ middleware๋ฅผ ๋ณด๋ ค๋ฉด <a href="https://www.starlette.dev/middleware/" class="external-link" target="_blank">Starlette์ Middleware ๋ฌธ์</a>์ <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">ASGI Awesome List</a>๋ฅผ ํ์ธํ์ธ์.
+์ฌ์ฉ ๊ฐ๋ฅํ ๋ค๋ฅธ middleware๋ฅผ ๋ณด๋ ค๋ฉด [Starlette์ Middleware ๋ฌธ์](https://www.starlette.dev/middleware/)์ [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi)๋ฅผ ํ์ธํ์ธ์.
/// tip | ํ
-`callback_url` ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ Pydantic์ <a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a> ํ์
์ ์ฌ์ฉํฉ๋๋ค.
+`callback_url` ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ Pydantic์ [Url](https://docs.pydantic.dev/latest/api/networks/) ํ์
์ ์ฌ์ฉํฉ๋๋ค.
///
์ค์ ์ฝ๋ฐฑ์ ๋จ์ง HTTP ์์ฒญ์
๋๋ค.
-์ฝ๋ฐฑ์ ์ง์ ๊ตฌํํ ๋๋ <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>๋ <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a> ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+์ฝ๋ฐฑ์ ์ง์ ๊ตฌํํ ๋๋ [HTTPX](https://www.python-httpx.org)๋ [Requests](https://requests.readthedocs.io/) ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
์ผ๋ฐ์ ์ธ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ์ฃผ์ ์ฐจ์ด์ ์ 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*๋ก ๋ณด๋ด์ง ์๋ ์์ฒญ์ ํ๋ผ๋ฏธํฐ์ ์ผ๋ถ ๊ฐ์ ๋ณ์๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
+* *path*์๋ [OpenAPI 3 ํํ์](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(์์ธํ ๋ด์ฉ์ ์๋ ์ฐธ๊ณ )์ด ํฌํจ๋ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด *์ฌ๋ฌ๋ถ์ 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*๋ก ๋ณด๋ด์ง ์๋ ์์ฒญ์ ์ผ๋ถ๋ฅผ ํฌํจํ ์ ์๋ [OpenAPI 3 ํํ์](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)์ ๊ฐ์ง ์ ์์ต๋๋ค.
์ด ๊ฒฝ์ฐ, ๋ค์ `str`์
๋๋ค:
### ๋ฌธ์ ํ์ธํ๊ธฐ { #check-the-docs }
-์ด์ ์ฑ์ ์คํํ๊ณ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ก ์ด๋ํ์ธ์.
+์ด์ ์ฑ์ ์คํํ๊ณ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ก ์ด๋ํ์ธ์.
*๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ๋ํด "Callbacks" ์น์
์ ํฌํจํ ๋ฌธ์๊ฐ ํ์๋๋ฉฐ, *external API*๊ฐ ์ด๋ค ํํ์ฌ์ผ ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค:
### ๋ฌธ์ ํ์ธํ๊ธฐ { #check-the-docs }
-์ด์ ์ฑ์ ์คํํ๊ณ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ก ์ด๋ํ์ธ์.
+์ด์ ์ฑ์ ์คํํ๊ณ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ก ์ด๋ํ์ธ์.
๋ฌธ์์ ์ผ๋ฐ์ ์ธ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ ๋ณด์ด๊ณ , ์ด์ ๋ ์ผ๋ถ **webhooks**๋ ํจ๊ป ๋ณด์ผ ๊ฒ์
๋๋ค:
๋ชจ๋ธ, ์ํ ์ฝ๋ ๋ฑ๊ณผ ํจ๊ป ์ถ๊ฐ ์๋ต๋ ์ ์ธํ ์ ์์ต๋๋ค.
-์ด์ ๋ํ ๋ฌธ์์ ์ ์ฒด ์ฅ์ด ์์ผ๋, [OpenAPI์ ์ถ๊ฐ ์๋ต](additional-responses.md){.internal-link target=_blank}์์ ์ฝ์ด๋ณด์ธ์.
+์ด์ ๋ํ ๋ฌธ์์ ์ ์ฒด ์ฅ์ด ์์ผ๋, [OpenAPI์ ์ถ๊ฐ ์๋ต](additional-responses.md)์์ ์ฝ์ด๋ณด์ธ์.
## OpenAPI Extra { #openapi-extra }
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
-OpenAPI ๋ช
์ธ์์๋ ์ด๋ฅผ <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Operation Object</a>๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
+OpenAPI ๋ช
์ธ์์๋ ์ด๋ฅผ [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object)๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
///
์ด๋ ์ ์์ค ํ์ฅ ์ง์ ์
๋๋ค.
-์ถ๊ฐ ์๋ต๋ง ์ ์ธํ๋ฉด ๋๋ค๋ฉด, ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ [OpenAPI์ ์ถ๊ฐ ์๋ต](additional-responses.md){.internal-link target=_blank}์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
+์ถ๊ฐ ์๋ต๋ง ์ ์ธํ๋ฉด ๋๋ค๋ฉด, ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ [OpenAPI์ ์ถ๊ฐ ์๋ต](additional-responses.md)์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
///
# ์๋ต - ์ํ ์ฝ๋ ๋ณ๊ฒฝ { #response-change-status-code }
-๊ธฐ๋ณธ [์๋ต ์ํ ์ฝ๋ ์ค์ ](../tutorial/response-status-code.md){.internal-link target=_blank}์ด ๊ฐ๋ฅํ๋ค๋ ๊ฑธ ์ด๋ฏธ ์๊ณ ๊ณ์ค ๊ฒ๋๋ค.
+๊ธฐ๋ณธ [์๋ต ์ํ ์ฝ๋ ์ค์ ](../tutorial/response-status-code.md)์ด ๊ฐ๋ฅํ๋ค๋ ๊ฑธ ์ด๋ฏธ ์๊ณ ๊ณ์ค ๊ฒ๋๋ค.
ํ์ง๋ง ๊ฒฝ์ฐ์ ๋ฐ๋ผ ๊ธฐ๋ณธ ์ค์ ๊ณผ ๋ค๋ฅธ ์ํ ์ฝ๋๋ฅผ ๋ฐํํด์ผ ํ ๋๊ฐ ์์ต๋๋ค.
์ฝ๋์์ `Response`๋ฅผ ์ง์ ๋ฐํํ ๋๋ ์ฟ ํค๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
-์ด๋ฅผ ์ํด [Response๋ฅผ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md){.internal-link target=_blank}์์ ์ค๋ช
ํ ๋๋ก ์๋ต์ ์์ฑํ ์ ์์ต๋๋ค.
+์ด๋ฅผ ์ํด [Response๋ฅผ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md)์์ ์ค๋ช
ํ ๋๋ก ์๋ต์ ์์ฑํ ์ ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ฟ ํค๋ฅผ ์ค์ ํ๊ณ ๋ฐํํ๋ฉด ๋ฉ๋๋ค:
{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
-/// tip | ํ
+/// tip
`Response` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์๋ต์ ์ง์ ๋ฐํํ๋ ๊ฒฝ์ฐ, FastAPI๋ ์ด๋ฅผ ์ง์ ๋ฐํํ๋ค๋ ์ ์ ์ ์ํ์ธ์.
///
-์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ์ต์
์ <a href="https://www.starlette.dev/responses/#set-cookie" class="external-link" target="_blank">Starlette์ ๋ฌธ์</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ์ต์
์ [Starlette์ ๋ฌธ์](https://www.starlette.dev/responses/#set-cookie)์์ ํ์ธํ ์ ์์ต๋๋ค.
**FastAPI**์์ *๊ฒฝ๋ก ์ฒ๋ฆฌ(path operation)*๋ฅผ ์์ฑํ ๋, ์ผ๋ฐ์ ์ผ๋ก `dict`, `list`, Pydantic ๋ชจ๋ธ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ ๋ฑ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
-๊ธฐ๋ณธ์ ์ผ๋ก **FastAPI**๋ [JSON ํธํ ๊ฐ๋ฅ ์ธ์ฝ๋](../tutorial/encoder.md){.internal-link target=_blank}์ ์ค๋ช
๋ `jsonable_encoder`๋ฅผ ์ฌ์ฉํด ํด๋น ๋ฐํ ๊ฐ์ ์๋์ผ๋ก JSON์ผ๋ก ๋ณํํฉ๋๋ค.
+[์๋ต ๋ชจ๋ธ](../tutorial/response-model.md)์ ์ ์ธํ๋ฉด FastAPI๋ Pydantic์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํฉ๋๋ค.
-๊ทธ๋ฐ ๋ค์, ๋ด๋ถ์ ์ผ๋ก๋ JSON ํธํ ๋ฐ์ดํฐ(์: `dict`)๋ฅผ `JSONResponse`์ ๋ฃ์ด ํด๋ผ์ด์ธํธ๋ก ์๋ต์ ์ ์กํ๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค.
+์๋ต ๋ชจ๋ธ์ ์ ์ธํ์ง ์์ผ๋ฉด, FastAPI๋ [JSON ํธํ ๊ฐ๋ฅ ์ธ์ฝ๋](../tutorial/encoder.md)์ ์ค๋ช
๋ `jsonable_encoder`๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๊ณ ์ด๋ฅผ `JSONResponse`์ ๋ฃ์ต๋๋ค.
-ํ์ง๋ง *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ `JSONResponse`๋ฅผ ์ง์ ๋ฐํํ ์๋ ์์ต๋๋ค.
+๋ํ `JSONResponse`๋ฅผ ์ง์ ์์ฑํด ๋ฐํํ ์๋ ์์ต๋๋ค.
-์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ ์ ํค๋๋ ์ฟ ํค๋ฅผ ๋ฐํํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํ ์ ์์ต๋๋ค.
+/// tip | ํ
+
+์ผ๋ฐ์ ์ผ๋ก `JSONResponse`๋ฅผ ์ง์ ๋ฐํํ๋ ๊ฒ๋ณด๋ค [์๋ต ๋ชจ๋ธ](../tutorial/response-model.md)์ ์ฌ์ฉํ๋ ํธ์ด ์ฑ๋ฅ์ด ํจ์ฌ ์ข์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด Pydantic์ด Rust์์ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํํฉ๋๋ค.
+
+///
## `Response` ๋ฐํํ๊ธฐ { #return-a-response }
-์ฌ์ค, `Response` ๋๋ ๊ทธ ํ์ ํด๋์ค๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
+`Response` ๋๋ ๊ทธ ํ์ ํด๋์ค๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
-/// tip | ํ
+/// info | ์ ๋ณด
`JSONResponse` ์์ฒด๋ `Response`์ ํ์ ํด๋์ค์
๋๋ค.
์ด๋ก ์ธํด ๋ง์ ์ ์ฐ์ฑ์ ์ป์ ์ ์์ต๋๋ค. ์ด๋ค ๋ฐ์ดํฐ ์ ํ์ด๋ ๋ฐํํ ์ ์๊ณ , ๋ฐ์ดํฐ ์ ์ธ์ด๋ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
+๋ํ ๋ง์ ์ฑ
์๋ ๋ฐ๋ฆ
๋๋ค. ๋ฐํํ๋ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ณ , ์ฌ๋ฐ๋ฅธ ํ์์ด๋ฉฐ, ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ๋๋ก ์ฌ๋ฌ๋ถ์ด ์ง์ ๋ณด์ฅํด์ผ ํฉ๋๋ค.
+
## `Response`์์ `jsonable_encoder` ์ฌ์ฉํ๊ธฐ { #using-the-jsonable-encoder-in-a-response }
**FastAPI**๋ ๋ฐํํ๋ `Response`์ ์๋ฌด๋ฐ ๋ณ๊ฒฝ๋ ํ์ง ์์ผ๋ฏ๋ก, ๊ทธ ๋ด์ฉ์ด ์ค๋น๋์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
์ด์ , ์ด๋ฅผ ์ฌ์ฉํด ์ฌ์ฉ์ ์ ์ ์๋ต์ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ์ต๋๋ค.
-์๋ฅผ ๋ค์ด <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a> ์๋ต์ ๋ฐํํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
+์๋ฅผ ๋ค์ด [XML](https://en.wikipedia.org/wiki/XML) ์๋ต์ ๋ฐํํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค.
XML ๋ด์ฉ์ ๋ฌธ์์ด์ ๋ฃ๊ณ , ์ด๋ฅผ `Response`์ ๋ฃ์ด ๋ฐํํ ์ ์์ต๋๋ค:
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
+## ์๋ต ๋ชจ๋ธ ๋์ ๋ฐฉ์ { #how-a-response-model-works }
+
+๊ฒฝ๋ก ์ฒ๋ฆฌ์์ [์๋ต ๋ชจ๋ธ - ๋ฐํ ํ์
](../tutorial/response-model.md)์ ์ ์ธํ๋ฉด **FastAPI**๋ Pydantic์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํฉ๋๋ค.
+
+{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *}
+
+์ด๋ Rust ์ธก์์ ์ฒ๋ฆฌ๋๋ฏ๋ก, ์ผ๋ฐ์ ์ธ Python๊ณผ `JSONResponse` ํด๋์ค๋ก ์ํํ๋ ๊ฒ๋ณด๋ค ์ฑ๋ฅ์ด ํจ์ฌ ์ข์ต๋๋ค.
+
+`response_model` ๋๋ ๋ฐํ ํ์
์ ์ฌ์ฉํ ๋ FastAPI๋ `jsonable_encoder`๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํ(์ด๋ ๋ ๋๋ฆฝ๋๋ค)ํ์ง๋ ์๊ณ , `JSONResponse` ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง๋ ์์ต๋๋ค.
+
+๋์ ์๋ต ๋ชจ๋ธ(๋๋ ๋ฐํ ํ์
)์ ์ฌ์ฉํด Pydantic์ด ์์ฑํ JSON ๋ฐ์ดํธ๋ฅผ ๊ฐ์ ธ์, JSON์ ๋ง๋ ๋ฏธ๋์ด ํ์
(`application/json`)์ ๊ฐ์ง `Response`๋ฅผ ์ง์ ๋ฐํํฉ๋๋ค.
+
## ์ฐธ๊ณ ์ฌํญ { #notes }
`Response`๋ฅผ ์ง์ ๋ฐํํ ๋, ๊ทธ ๋ฐ์ดํฐ๋ ์๋์ผ๋ก ์ ํจ์ฑ ๊ฒ์ฌ๋๊ฑฐ๋, ๋ณํ(์ง๋ ฌํ)๋๊ฑฐ๋, ๋ฌธ์ํ๋์ง ์์ต๋๋ค.
-๊ทธ๋ฌ๋ [OpenAPI์์ ์ถ๊ฐ ์๋ต](additional-responses.md){.internal-link target=_blank}์์ ์ค๋ช
๋ ๋๋ก ๋ฌธ์ํํ ์ ์์ต๋๋ค.
+๊ทธ๋ฌ๋ [OpenAPI์์ ์ถ๊ฐ ์๋ต](additional-responses.md)์์ ์ค๋ช
๋ ๋๋ก ๋ฌธ์ํํ ์ ์์ต๋๋ค.
์ดํ ์น์
์์ ์๋ ๋ฐ์ดํฐ ๋ณํ, ๋ฌธ์ํ ๋ฑ์ ๊ณ์ ์ฌ์ฉํ๋ฉด์ ์ด๋ฌํ ์ฌ์ฉ์ ์ ์ `Response`๋ฅผ ์ฌ์ฉํ๋/์ ์ธํ๋ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
`Response`๋ฅผ ์ง์ ๋ฐํํ ๋์๋ ํค๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
-[์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md){.internal-link target=_blank}์์ ์ค๋ช
ํ ๋๋ก ์๋ต์ ์์ฑํ๊ณ , ํค๋๋ฅผ ์ถ๊ฐ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌํ์ธ์:
+[์๋ต์ ์ง์ ๋ฐํํ๊ธฐ](response-directly.md)์ ์ค๋ช
ํ ๋๋ก ์๋ต์ ์์ฑํ๊ณ , ํค๋๋ฅผ ์ถ๊ฐ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌํ์ธ์:
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
## ์ปค์คํ
ํค๋ { #custom-headers }
-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">`X-` ์ ๋์ด๋ฅผ ์ฌ์ฉํ์ฌ</a> ์ปค์คํ
์ฌ์ค ํค๋๋ฅผ ์ถ๊ฐํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
+์ปค์คํ
์ฌ์ค ํค๋๋ [`X-` ์ ๋์ด๋ฅผ ์ฌ์ฉํ์ฌ](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) ์ถ๊ฐํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
-ํ์ง๋ง, ์ฌ๋ฌ๋ถ์ด ๋ธ๋ผ์ฐ์ ์์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณผ ์ ์๊ธฐ๋ฅผ ์ํ๋ ์ปค์คํ
ํค๋๊ฐ ์๋ ๊ฒฝ์ฐ, CORS ์ค์ ์ ์ด๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}์์ ์์ธํ ์์๋ณด์ธ์). <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette์ CORS ๋ฌธ์</a>์ ๋ฌธ์ํ๋ `expose_headers` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ธ์.
+ํ์ง๋ง, ์ฌ๋ฌ๋ถ์ด ๋ธ๋ผ์ฐ์ ์์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณผ ์ ์๊ธฐ๋ฅผ ์ํ๋ ์ปค์คํ
ํค๋๊ฐ ์๋ ๊ฒฝ์ฐ, CORS ์ค์ ์ ์ด๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)์์ ์์ธํ ์์๋ณด์ธ์). [Starlette์ CORS ๋ฌธ์](https://www.starlette.dev/middleware/#corsmiddleware)์ ๋ฌธ์ํ๋ `expose_headers` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ธ์.
dependency๋ฅผ ์ฌ์ฉํด ์ฌ์ฉ์๋ช
๊ณผ ๋น๋ฐ๋ฒํธ๊ฐ ์ฌ๋ฐ๋ฅธ์ง ํ์ธํ์ธ์.
-์ด๋ฅผ ์ํด Python ํ์ค ๋ชจ๋ <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a>๋ฅผ ์ฌ์ฉํด ์ฌ์ฉ์๋ช
๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ํ์ธํฉ๋๋ค.
+์ด๋ฅผ ์ํด Python ํ์ค ๋ชจ๋ [`secrets`](https://docs.python.org/3/library/secrets.html)๋ฅผ ์ฌ์ฉํด ์ฌ์ฉ์๋ช
๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ํ์ธํฉ๋๋ค.
`secrets.compare_digest()`๋ `bytes` ๋๋ ASCII ๋ฌธ์(์์ด์์ ์ฌ์ฉํ๋ ๋ฌธ์)๋ง ํฌํจํ `str`์ ๋ฐ์์ผ ํฉ๋๋ค. ์ฆ, `Sebastiรกn`์ `รก` ๊ฐ์ ๋ฌธ์๊ฐ ์์ผ๋ฉด ๋์ํ์ง ์์ต๋๋ค.
ํ์ง๋ง `secrets.compare_digest()`๋ฅผ ์ฌ์ฉํ๋ฉด "timing attacks"๋ผ๊ณ ๋ถ๋ฆฌ๋ ํ ์ ํ์ ๊ณต๊ฒฉ์ ๋ํด ์์ ํด์ง๋๋ค.
-### Timing Attacks { #timing-attacks }
+### ํ์ด๋ฐ ๊ณต๊ฒฉ { #timing-attacks }
๊ทธ๋ ๋ค๋ฉด "timing attack"์ด๋ ๋ฌด์์ผ๊น์?
## ์ถ๊ฐ ๊ธฐ๋ฅ { #additional-features }
-[ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋: ๋ณด์](../../tutorial/security/index.md){.internal-link target=_blank}์์ ๋ค๋ฃฌ ๋ด์ฉ ์ธ์๋, ๋ณด์์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ์ถ๊ฐ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
+[ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋: ๋ณด์](../../tutorial/security/index.md)์์ ๋ค๋ฃฌ ๋ด์ฉ ์ธ์๋, ๋ณด์์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ์ถ๊ฐ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
/// tip | ํ
## ๋จผ์ ํํ ๋ฆฌ์ผ ์ฝ๊ธฐ { #read-the-tutorial-first }
-๋ค์ ์น์
์ ์ฃผ์ [ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋: ๋ณด์](../../tutorial/security/index.md){.internal-link target=_blank}์ ์ด๋ฏธ ์ฝ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
+๋ค์ ์น์
์ ์ฃผ์ [ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋: ๋ณด์](../../tutorial/security/index.md)์ ์ด๋ฏธ ์ฝ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
๋ชจ๋ ๋์ผํ ๊ฐ๋
์ ๊ธฐ๋ฐ์ผ๋ก ํ์ง๋ง, ๋ช ๊ฐ์ง ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
## ์ ์ฒด ๊ฐ์ { #global-view }
-๋จผ์ , ๋ฉ์ธ **ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋**์ [๋น๋ฐ๋ฒํธ(๋ฐ ํด์ฑ)๋ฅผ ์ฌ์ฉํ๋ OAuth2, JWT ํ ํฐ์ ์ฌ์ฉํ๋ Bearer](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ์์ ์์ ์ด๋ค ๋ถ๋ถ์ด ๋ฐ๋๋์ง ๋น ๋ฅด๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด์ OAuth2 ์ค์ฝํ๋ฅผ ์ฌ์ฉํฉ๋๋ค:
+๋จผ์ , ๋ฉ์ธ **ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋**์ [๋น๋ฐ๋ฒํธ(๋ฐ ํด์ฑ)๋ฅผ ์ฌ์ฉํ๋ OAuth2, JWT ํ ํฐ์ ์ฌ์ฉํ๋ Bearer](../../tutorial/security/oauth2-jwt.md) ์์ ์์ ์ด๋ค ๋ถ๋ถ์ด ๋ฐ๋๋์ง ๋น ๋ฅด๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด์ OAuth2 ์ค์ฝํ๋ฅผ ์ฌ์ฉํฉ๋๋ค:
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
## ๋ฐ์ฝ๋ ์ดํฐ `dependencies`์์์ `Security` { #security-in-decorator-dependencies }
-[๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ์ ์์กด์ฑ](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์์ ์ค๋ช
ํ ๊ฒ์ฒ๋ผ ๋ฐ์ฝ๋ ์ดํฐ์ `dependencies` ๋งค๊ฐ๋ณ์์ `Depends`์ `list`๋ฅผ ์ ์ํ ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก, ๊ฑฐ๊ธฐ์์ `scopes`์ ํจ๊ป `Security`๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
+[๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ์ ์์กด์ฑ](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)์์ ์ค๋ช
ํ ๊ฒ์ฒ๋ผ ๋ฐ์ฝ๋ ์ดํฐ์ `dependencies` ๋งค๊ฐ๋ณ์์ `Depends`์ `list`๋ฅผ ์ ์ํ ์ ์๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก, ๊ฑฐ๊ธฐ์์ `scopes`์ ํจ๊ป `Security`๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
/// tip | ํ
-ํ๊ฒฝ ๋ณ์๋ฅผ ์ดํดํ๋ ค๋ฉด [ํ๊ฒฝ ๋ณ์](../environment-variables.md){.internal-link target=_blank}๋ฅผ ์ฝ์ด๋ณด์ธ์.
+ํ๊ฒฝ ๋ณ์๋ฅผ ์ดํดํ๋ ค๋ฉด [ํ๊ฒฝ ๋ณ์](../environment-variables.md)๋ฅผ ์ฝ์ด๋ณด์ธ์.
///
## Pydantic `Settings` { #pydantic-settings }
-๋คํํ Pydantic์ <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>๋ฅผ ํตํด ํ๊ฒฝ ๋ณ์์์ ์ค๋ ์ด๋ฌํ ์ค์ ์ ์ฒ๋ฆฌํ ์ ์๋ ํ๋ฅญํ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
+๋คํํ Pydantic์ ํ๊ฒฝ ๋ณ์์์ ์ค๋ ์ด๋ฌํ ์ค์ ์ ์ฒ๋ฆฌํ ์ ์๋ ํ๋ฅญํ ์ ํธ๋ฆฌํฐ๋ฅผ [Pydantic: Settings ๊ด๋ฆฌ](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)๋ก ์ ๊ณตํฉ๋๋ค.
### `pydantic-settings` ์ค์นํ๊ธฐ { #install-pydantic-settings }
-๋จผ์ [๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, `pydantic-settings` ํจํค์ง๋ฅผ ์ค์นํ์ธ์:
+๋จผ์ [๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, `pydantic-settings` ํจํค์ง๋ฅผ ์ค์นํ์ธ์:
<div class="termy">
## ๋ค๋ฅธ ๋ชจ๋์ ์ค์ { #settings-in-another-module }
-[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ์ฒ๋ผ, ์ค์ ์ ๋ค๋ฅธ ๋ชจ๋ ํ์ผ์ ๋ฃ์ ์๋ ์์ต๋๋ค.
+[๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ](../tutorial/bigger-applications.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ, ์ค์ ์ ๋ค๋ฅธ ๋ชจ๋ ํ์ผ์ ๋ฃ์ ์๋ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด `config.py` ํ์ผ์ ๋ค์์ฒ๋ผ ๋ง๋ค ์ ์์ต๋๋ค:
/// tip | ํ
-[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ์ฒ๋ผ `__init__.py` ํ์ผ๋ ํ์ํฉ๋๋ค.
+[๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ](../tutorial/bigger-applications.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ `__init__.py` ํ์ผ๋ ํ์ํฉ๋๋ค.
///
///
-Pydantic์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์ด๋ฐ ์ ํ์ ํ์ผ์์ ์ฝ๋ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+Pydantic์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์ด๋ฐ ์ ํ์ ํ์ผ์์ ์ฝ๋ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ [Pydantic Settings: Dotenv (.env) ์ง์](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support)์ ์ฐธ๊ณ ํ์ธ์.
/// tip | ํ
/// 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 ์ค์ ์ ์ํ ๊ฒ์
๋๋ค. ์์ธํ ๋ด์ฉ์ [Pydantic: ๊ฐ๋
: ๊ตฌ์ฑ](https://docs.pydantic.dev/latest/concepts/config/)์ ์ฐธ๊ณ ํ์ธ์.
///
์ด๋ ๊ฒ ํ๋ฉด ๊ฑฐ์ ์ ์ญ ๋ณ์์ฒ๋ผ ๋์ํฉ๋๋ค. ํ์ง๋ง ์์กด์ฑ ํจ์๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ํ
์คํธ๋ฅผ ์ํด ์ฝ๊ฒ overrideํ ์ ์์ต๋๋ค.
-`@lru_cache`๋ Python ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ `functools`์ ํฌํจ๋์ด ์์ผ๋ฉฐ, ์์ธํ ๋ด์ฉ์ <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">`@lru_cache`์ ๋ํ Python ๋ฌธ์</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+`@lru_cache`๋ Python ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ `functools`์ ํฌํจ๋์ด ์์ผ๋ฉฐ, ์์ธํ ๋ด์ฉ์ [`@lru_cache`์ ๋ํ Python ๋ฌธ์](https://docs.python.org/3/library/functools.html#functools.lru_cache)์์ ํ์ธํ ์ ์์ต๋๋ค.
## ์ ๋ฆฌ { #recap }
-# รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ - ๋ง์ดํธ { #sub-applications-mounts }
+# รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 - ๋ง์ดํธ { #sub-applications-mounts }
-รชยฐ\81รชยฐ\81รฌ\9d\98 รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ OpenAPIรฌ\99\80 รซยฌยธรฌ\84\9c UIรซยฅยผ รชยฐ\96รซ\8a\94 รซ\91\90 รชยฐ\9cรฌ\9d\98 รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ FastAPI รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9dยด รญ\95\84รฌ\9a\94รญ\95\98รซ\8bยครซยฉยด, รซยฉ\94รฌ\9dยธ รฌ\95ยฑรฌ\9d\84 รซ\91\90รชยณย รญ\95\98รซ\82\98(รซ\98\90รซ\8a\94 รชยทยธ รฌ\9dยดรฌ\83\81)รฌ\9d\98 รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ "๋ง์ดํธ"ํ ์ ์์ต๋๋ค.
+รชยฐ\81รชยฐ\81รฌ\9d\98 รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ OpenAPIรฌ\99\80 รซยฌยธรฌ\84\9c UIรซยฅยผ รชยฐ\96รซ\8a\94 รซ\91\90 รชยฐ\9cรฌ\9d\98 รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ FastAPI รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9dยด รญ\95\84รฌ\9a\94รญ\95\98รซ\8bยครซยฉยด, รซยฉ\94รฌ\9dยธ รฌ\95ยฑรฌ\9d\84 รซ\91\90รชยณย รญ\95\98รซ\82\98(รซ\98\90รซ\8a\94 รชยทยธ รฌ\9dยดรฌ\83\81)รฌ\9d\98 รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ "๋ง์ดํธ"ํ ์ ์์ต๋๋ค.
## **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
๋ง์ดํธ { #mounting-a-fastapi-application }
-"รซยง\88รฌ\9aยดรญ\8aยธ"รซ\9e\80 รฌ\99\84รฌย \84รญ\9e\88 "รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ" รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9d\84 รญ\8aยนรฌย \95 รชยฒยฝรซยก\9cรฌ\97\90 รฌยถ\94รชยฐ\80รญ\95\98รชยณย , รชยทยธ รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ ์ ์ธ๋ _๊ฒฝ๋ก ์ฒ๋ฆฌ_๋ก ํด๋น ๊ฒฝ๋ก ์๋์ ๋ชจ๋ ๊ฒ์ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
+"รซยง\88รฌ\9aยดรญ\8aยธ"รซ\9e\80 รฌ\99\84รฌย \84รญ\9e\88 "รซ\8f\85รซยฆยฝรฌย \81รฌ\9dยธ" รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9d\84 รญ\8aยนรฌย \95 รชยฒยฝรซยก\9cรฌ\97\90 รฌยถ\94รชยฐ\80รญ\95\98รชยณย , รชยทยธ รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ ์ ์ธ๋ _๊ฒฝ๋ก ์ฒ๋ฆฌ_๋ก ํด๋น ๊ฒฝ๋ก ์๋์ ๋ชจ๋ ๊ฒ์ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
### ์ต์์ ์ ํ๋ฆฌ์ผ์ด์
{ #top-level-application }
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
-### รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ { #sub-application }
+### รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 { #sub-application }
-รชยทยธ รซ\8bยครฌ\9d\8c, รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ๊ณผ ๊ทธ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์์ฑํฉ๋๋ค.
+รชยทยธ รซ\8bยครฌ\9d\8c, รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98๊ณผ ๊ทธ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์์ฑํฉ๋๋ค.
-รฌ\9dยด รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ ๋ ๋ค๋ฅธ ํ์ค FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ด์ง๋ง, "๋ง์ดํธ"๋ ์ ํ๋ฆฌ์ผ์ด์
์
๋๋ค:
+รฌ\9dยด รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ ๋ ๋ค๋ฅธ ํ์ค FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ด์ง๋ง, "๋ง์ดํธ"๋ ์ ํ๋ฆฌ์ผ์ด์
์
๋๋ค:
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
-### รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ ๋ง์ดํธ { #mount-the-sub-application }
+### รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 ๋ง์ดํธ { #mount-the-sub-application }
-รฌยต\9cรฌ\83\81รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 `app`รฌ\97\90รฌ\84\9c รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ `subapi`๋ฅผ ๋ง์ดํธํฉ๋๋ค.
+รฌยต\9cรฌ\83\81รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 `app`รฌ\97\90รฌ\84\9c รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 `subapi`๋ฅผ ๋ง์ดํธํฉ๋๋ค.
์ด ๊ฒฝ์ฐ `/subapi` ๊ฒฝ๋ก์ ๋ง์ดํธ๋ฉ๋๋ค:
### ์๋ API ๋ฌธ์ ํ์ธ { #check-the-automatic-api-docs }
-์ด์ ํ์ผ๊ณผ ํจ๊ป `fastapi` ๋ช
๋ น์ ์คํํ์ธ์:
+์ด์ `fastapi` ๋ช
๋ น์ด๋ฅผ ์คํํ์ธ์:
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
-๊ทธ๋ฆฌ๊ณ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>์์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
+๊ทธ๋ฆฌ๊ณ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)์์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
๋ฉ์ธ ์ฑ์ ์๋ API ๋ฌธ์๋ฅผ ๋ณด๊ฒ ๋ ๊ฒ์ด๋ฉฐ, ๋ฉ์ธ ์ฑ ์์ฒด์ _๊ฒฝ๋ก ์ฒ๋ฆฌ_๋ง ํฌํจ๋ฉ๋๋ค:
<img src="/img/tutorial/sub-applications/image01.png">
-๊ทธ ๋ค์, <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>์์ ํ์ ์์ฉํ๋ก๊ทธ๋จ์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
+๊ทธ ๋ค์, [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs)์์ ํ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
-รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจรฌ\9d\98 รฌ\9e\90รซ\8f\99 API รซยฌยธรฌ\84\9cรซยฅยผ รซยณยดรชยฒ\8c รซ\90ย รชยฒ\83รฌ\9dยดรซยฉยฐ, รญ\95\98รฌ\9c\84 รชยฒยฝรซยก\9c รฌย \91รซ\91\90รฌ\82ยฌ `/subapi` รฌ\95\84รซ\9e\98รฌ\97\90 รฌ\98ยฌรซยฐ\94รซยฅยดรชยฒ\8c รญ\8fยฌรญ\95ยจรซ\90\9c รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ ์์ฒด์ _๊ฒฝ๋ก ์ฒ๋ฆฌ_๋ง ํฌํจ๋ฉ๋๋ค:
+รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9d\98 รฌ\9e\90รซ\8f\99 API รซยฌยธรฌ\84\9cรซยฅยผ รซยณยดรชยฒ\8c รซ\90ย รชยฒ\83รฌ\9dยดรซยฉยฐ, รญ\95\98รฌ\9c\84 รชยฒยฝรซยก\9c รฌย \91รซ\91\90รฌ\82ยฌ `/subapi` รฌ\95\84รซ\9e\98รฌ\97\90 รฌ\98ยฌรซยฐ\94รซยฅยดรชยฒ\8c รญ\8fยฌรญ\95ยจรซ\90\9c รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98 ์์ฒด์ _๊ฒฝ๋ก ์ฒ๋ฆฌ_๋ง ํฌํจ๋ฉ๋๋ค:
<img src="/img/tutorial/sub-applications/image02.png">
### ๊ธฐ์ ์ ์ธ๋ถ์ฌํญ: `root_path` { #technical-details-root-path }
-รฌ\9c\84รฌ\97\90รฌ\84\9c รฌ\84ยครซยช\85รญ\95\9c รซ\8c\80รซยก\9c รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจรฌ\9d\84 รซยง\88รฌ\9aยดรญ\8aยธรญ\95\98รซยฉยด, FastAPIรซ\8a\94 ASGI รซยช\85รฌ\84ยธรฌ\9d\98 รซยฉ\94รฌยปยครซ\8b\88รฌยฆ\98รฌ\9dยธ `root_path`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ ๋ํ ๋ง์ดํธ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ๋ ์์
์ ์ฒ๋ฆฌํฉ๋๋ค.
+รฌ\9c\84รฌ\97\90รฌ\84\9c รฌ\84ยครซยช\85รญ\95\9c รซ\8c\80รซยก\9c รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98รฌ\9d\84 รซยง\88รฌ\9aยดรญ\8aยธรญ\95\98รซยฉยด, FastAPIรซ\8a\94 ASGI รซยช\85รฌ\84ยธรฌ\9d\98 รซยฉ\94รฌยปยครซ\8b\88รฌยฆ\98รฌ\9dยธ `root_path`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95ยด รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ ๋ํ ๋ง์ดํธ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ๋ ์์
์ ์ฒ๋ฆฌํฉ๋๋ค.
-รฌ\9dยดรซย \87รชยฒ\8c รญ\95\98รซยฉยด รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ ๋ฌธ์ UI๋ฅผ ์ํด ํด๋น ๊ฒฝ๋ก ์ ๋์ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๊ฒ์ ์๊ฒ ๋ฉ๋๋ค.
+รฌ\9dยดรซย \87รชยฒ\8c รญ\95\98รซยฉยด รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ ๋ฌธ์ UI๋ฅผ ์ํด ํด๋น ๊ฒฝ๋ก ์ ๋์ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๊ฒ์ ์๊ฒ ๋ฉ๋๋ค.
-รซ\98\90รญ\95\9c รญ\95\98รฌ\9c\84 รฌ\9d\91รฌ\9aยฉรญ\94\84รซยก\9cรชยทยธรซ\9eยจ๋ ์์ฒด์ ์ผ๋ก ํ์ ์ฑ์ ๋ง์ดํธํ ์ ์์ผ๋ฉฐ, FastAPI๊ฐ ์ด ๋ชจ๋ `root_path`๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํฉ๋๋ค.
+รซ\98\90รญ\95\9c รญ\95\98รฌ\9c\84 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98๋ ์์ฒด์ ์ผ๋ก ํ์ ์ฑ์ ๋ง์ดํธํ ์ ์์ผ๋ฉฐ, FastAPI๊ฐ ์ด ๋ชจ๋ `root_path`๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํฉ๋๋ค.
-`root_path`์ ์ด๋ฅผ ๋ช
์์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ [ํ๋ก์ ๋ค](behind-a-proxy.md){.internal-link target=_blank} ์น์
์์ ๋ ์์๋ณผ ์ ์์ต๋๋ค.
+`root_path`์ ์ด๋ฅผ ๋ช
์์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ [ํ๋ก์ ๋ค](behind-a-proxy.md) ์น์
์์ ๋ ์์๋ณผ ์ ์์ต๋๋ค.
## ์์กด์ฑ ์ค์น { #install-dependencies }
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ , ํ์ฑํํ ํ `jinja2`๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ , ํ์ฑํํ ํ `jinja2`๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค:
<div class="termy">
## ๋ ๋ง์ ์ธ๋ถ ์ฌํญ { #more-details }
-ํ
ํ๋ฆฟ ํ
์คํธ๋ฅผ ํฌํจํ ๋ ๋ง์ ์ธ๋ถ ์ฌํญ์ <a href="https://www.starlette.dev/templates/" class="external-link" target="_blank">Starlette์ ํ
ํ๋ฆฟ ๋ฌธ์</a>๋ฅผ ํ์ธํ์ธ์.
+ํ
ํ๋ฆฟ ํ
์คํธ๋ฅผ ํฌํจํ ๋ ๋ง์ ์ธ๋ถ ์ฌํญ์ [Starlette์ ํ
ํ๋ฆฟ ๋ฌธ์](https://www.starlette.dev/templates/)๋ฅผ ํ์ธํ์ธ์.
{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
-/// note | ์ฐธ๊ณ
+/// note
-์์ธํ ๋ด์ฉ์ Starlette์ <a href="https://www.starlette.dev/testclient/#testing-websocket-sessions" class="external-link" target="_blank">WebSocket ํ
์คํธ</a> ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
+์์ธํ ๋ด์ฉ์ Starlette์ [WebSocket ํ
์คํธ](https://www.starlette.dev/testclient/#testing-websocket-sessions) ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
///
## `Request` ๊ฐ์ฒด์ ๋ํ ์ธ๋ถ ์ฌํญ { #details-about-the-request-object }
-**FastAPI**๋ ์ค์ ๋ก ๋ด๋ถ์ **Starlette**์ ์ฌ์ฉํ๋ฉฐ, ๊ทธ ์์ ์ฌ๋ฌ ๋๊ตฌ๋ฅผ ๋ง๋ถ์ธ ๊ตฌ์กฐ์
๋๋ค. ๋ฐ๋ผ์ ์ฌ๋ฌ๋ถ์ด ํ์ํ ๋ Starlette์ <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request`</a> ๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+**FastAPI**๋ ์ค์ ๋ก ๋ด๋ถ์ **Starlette**์ ์ฌ์ฉํ๋ฉฐ, ๊ทธ ์์ ์ฌ๋ฌ ๋๊ตฌ๋ฅผ ๋ง๋ถ์ธ ๊ตฌ์กฐ์
๋๋ค. ๋ฐ๋ผ์ ์ฌ๋ฌ๋ถ์ด ํ์ํ ๋ Starlette์ [`Request`](https://www.starlette.dev/requests/) ๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ํ ์ด๋ `Request` ๊ฐ์ฒด์์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ(์: ๋ณธ๋ฌธ์ ์ฝ๊ธฐ) FastAPI๊ฐ ํด๋น ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ๊ฑฐ๋ ๋ณํํ์ง ์์ผ๋ฉฐ, ๋ฌธ์ํ(OpenAPI๋ฅผ ํตํ ์๋ API ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ฉ)๋ ๋์ง ์๋๋ค๋ ์๋ฏธ์ด๊ธฐ๋ ํฉ๋๋ค.
## `Request` ์ค๋ช
์ { #request-documentation }
-์ฌ๋ฌ๋ถ์ <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">๊ณต์ Starlette ์ค๋ช
์ ์ฌ์ดํธ์ `Request` ๊ฐ์ฒด</a>์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
+์ฌ๋ฌ๋ถ์ [`Request` ๊ฐ์ฒด์ ๋ํ ๊ณต์ Starlette ์ค๋ช
์ ์ฌ์ดํธ](https://www.starlette.dev/requests/)์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
# WebSockets { #websockets }
-์ฌ๋ฌ๋ถ์ **FastAPI**์์ <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a>๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+์ฌ๋ฌ๋ถ์ **FastAPI**์์ [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
## `websockets` ์ค์น { #install-websockets }
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, `websockets`("WebSocket" ํ๋กํ ์ฝ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ฅผ ์ค์นํ์ธ์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, `websockets`("WebSocket" ํ๋กํ ์ฝ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ฅผ ์ค์นํ์ธ์:
<div class="termy">
## ์๋ํด๋ณด๊ธฐ { #try-it }
-ํ์ผ ์ด๋ฆ์ด `main.py`๋ผ๊ณ ๊ฐ์ ํ๊ณ ๋ค์์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํฉ๋๋ค:
+์ฝ๋๋ฅผ `main.py` ํ์ผ์ ๋ฃ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํฉ๋๋ค:
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
-๋ธ๋ผ์ฐ์ ์์ <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>์ ์ฌ์ธ์.
+๋ธ๋ผ์ฐ์ ์์ [http://127.0.0.1:8000](http://127.0.0.1:8000)์ ์ฌ์ธ์.
๊ฐ๋จํ ํ์ด์ง๊ฐ ๋ํ๋ ๊ฒ์
๋๋ค:
WebSocket์ด๊ธฐ ๋๋ฌธ์ `HTTPException`์ ๋ฐ์์ํค๋ ๊ฒ์ ์ ์ ํ์ง ์์ต๋๋ค. ๋์ `WebSocketException`์ ๋ฐ์์ํต๋๋ค.
-๋ช
์ธ์์ ์ ์๋ <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">์ ํจํ ์ฝ๋</a>๋ฅผ ์ฌ์ฉํ์ฌ ์ข
๋ฃ ์ฝ๋๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
+๋ช
์ธ์์ ์ ์๋ [์ ํจํ ์ฝ๋](https://tools.ietf.org/html/rfc6455#section-7.4.1)๋ฅผ ์ฌ์ฉํ์ฌ ์ข
๋ฃ ์ฝ๋๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
///
### ์ข
์์ฑ์ ๊ฐ์ง WebSockets ์๋ํด๋ณด๊ธฐ { #try-the-websockets-with-dependencies }
-ํ์ผ ์ด๋ฆ์ด `main.py`๋ผ๊ณ ๊ฐ์ ํ๊ณ ๋ค์์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํฉ๋๋ค:
+์ ํ๋ฆฌ์ผ์ด์
์ ์คํํฉ๋๋ค:
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
-๋ธ๋ผ์ฐ์ ์์ <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>์ ์ฌ์ธ์.
+๋ธ๋ผ์ฐ์ ์์ [http://127.0.0.1:8000](http://127.0.0.1:8000)์ ์ฌ์ธ์.
์ฌ๊ธฐ์์ ๋ค์์ ์ค์ ํ ์ ์์ต๋๋ค:
ํ์ง๋ง ๋ชจ๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์ผ ๋ฆฌ์คํธ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก, ํ๋ก์ธ์ค๊ฐ ์คํ ์ค์ธ ๋์๋ง ๋์ํ๋ฉฐ ๋จ์ผ ํ๋ก์ธ์ค์์๋ง ์๋ํ๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
-FastAPI์ ์ฝ๊ฒ ํตํฉํ ์ ์์ผ๋ฉด์ ๋ ๊ฒฌ๊ณ ํ๊ณ Redis, PostgreSQL ๋ฑ์ ์ง์ํ๋ ๋๊ตฌ๊ฐ ํ์ํ๋ค๋ฉด, <a href="https://github.com/encode/broadcaster" class="external-link" target="_blank">encode/broadcaster</a>๋ฅผ ํ์ธํ์ธ์.
+FastAPI์ ์ฝ๊ฒ ํตํฉํ ์ ์์ผ๋ฉด์ ๋ ๊ฒฌ๊ณ ํ๊ณ Redis, PostgreSQL ๋ฑ์ ์ง์ํ๋ ๋๊ตฌ๊ฐ ํ์ํ๋ค๋ฉด, [encode/broadcaster](https://github.com/encode/broadcaster)๋ฅผ ํ์ธํ์ธ์.
///
๋ค์ ์ต์
์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด Starlette์ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์:
-* <a href="https://www.starlette.dev/websockets/" class="external-link" target="_blank">`WebSocket` ํด๋์ค</a>.
-* <a href="https://www.starlette.dev/endpoints/#websocketendpoint" class="external-link" target="_blank">ํด๋์ค ๊ธฐ๋ฐ WebSocket ์ฒ๋ฆฌ</a>.
+* [`WebSocket` ํด๋์ค](https://www.starlette.dev/websockets/).
+* [ํด๋์ค ๊ธฐ๋ฐ WebSocket ์ฒ๋ฆฌ](https://www.starlette.dev/endpoints/#websocketendpoint).
# WSGI ํฌํจํ๊ธฐ - Flask, Django ๋ฑ { #including-wsgi-flask-django-others }
-[์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- ๋ง์ดํธ](sub-applications.md){.internal-link target=_blank}, [ํ๋ก์ ๋ค์์](behind-a-proxy.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ์ฒ๋ผ WSGI ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง์ดํธํ ์ ์์ต๋๋ค.
+[์๋ธ ์ ํ๋ฆฌ์ผ์ด์
- ๋ง์ดํธ](sub-applications.md), [ํ๋ก์ ๋ค์์](behind-a-proxy.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ WSGI ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง์ดํธํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์ํด `WSGIMiddleware`๋ฅผ ์ฌ์ฉํด WSGI ์ ํ๋ฆฌ์ผ์ด์
(์: Flask, Django ๋ฑ)์ ๊ฐ์ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง๋ **FastAPI**์ ์ํด ์ฒ๋ฆฌ๋ฉ๋๋ค.
-์คํํ๊ณ <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>๋ก ์ด๋ํ๋ฉด Flask์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+์คํํ๊ณ [http://localhost:8000/v1/](http://localhost:8000/v1/)๋ก ์ด๋ํ๋ฉด Flask์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```txt
Hello, World from Flask!
```
-๊ทธ๋ฆฌ๊ณ <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a>๋ก ์ด๋ํ๋ฉด **FastAPI**์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+๊ทธ๋ฆฌ๊ณ [http://localhost:8000/v2](http://localhost:8000/v2)๋ก ์ด๋ํ๋ฉด **FastAPI**์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{
## ์ด์ ๋๊ตฌ๋ค { #previous-tools }
-### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
+### [Django](https://www.djangoproject.com/) { #django }
๊ฐ์ฅ ์ธ๊ธฐ ์๋ Python framework์ด๋ฉฐ ๋๋ฆฌ ์ ๋ขฐ๋ฐ๊ณ ์์ต๋๋ค. Instagram ๊ฐ์ ์์คํ
์ ๋ง๋๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๋ฐฑ์๋์์ HTML์ ์์ฑํ๊ธฐ ์ํด ๋ง๋ค์ด์ก์ง, ํ๋์ ์ธ ํ๋ฐํธ์๋(์: React, Vue.js, Angular)๋ ๋ค๋ฅธ ์์คํ
(์: <abbr title="Internet of Things - ์ฌ๋ฌผ ์ธํฐ๋ท">IoT</abbr> ๊ธฐ๊ธฐ)์์ ์ฌ์ฉ๋๋ API๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ค๊ณ๋ ๊ฒ์ ์๋๋๋ค.
-### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
+### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework }
Django REST framework๋ Django๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Web API๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ์ ์ฐํ toolkit์ผ๋ก ๋ง๋ค์ด์ก๊ณ , Django์ API ๊ธฐ๋ฅ์ ๊ฐ์ ํ๊ธฐ ์ํ ๋ชฉ์ ์ด์์ต๋๋ค.
///
-### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
+### [Flask](https://flask.palletsprojects.com) { #flask }
Flask๋ "microframework"๋ก, Django์ ๊ธฐ๋ณธ์ผ๋ก ํฌํจ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํตํฉ์ด๋ ์ฌ๋ฌ ๊ธฐ๋ฅ๋ค์ ํฌํจํ์ง ์์ต๋๋ค.
///
-### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
+### [Requests](https://requests.readthedocs.io) { #requests }
**FastAPI**๋ ์ค์ ๋ก **Requests**์ ๋์์ด ์๋๋๋ค. ๋์ ๋ฒ์๋ ๋งค์ฐ ๋ค๋ฆ
๋๋ค.
///
-### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
+### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi }
์ ๊ฐ Django REST Framework์์ ๊ฐ์ฅ ์ํ๋ ์ฃผ์ ๊ธฐ๋ฅ์ ์๋ API ๋ฌธ์ํ์์ต๋๋ค.
๋ํ ํ์ค ๊ธฐ๋ฐ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ๋๊ตฌ๋ฅผ ํตํฉํ๊ธฐ:
-* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
-* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
+* [Swagger UI](https://github.com/swagger-api/swagger-ui)
+* [ReDoc](https://github.com/Rebilly/ReDoc)
์ด ๋ ๊ฐ์ง๋ ๊ฝค ๋์ค์ ์ด๊ณ ์์ ์ ์ด๊ธฐ ๋๋ฌธ์ ์ ํ๋์์ต๋๋ค. ํ์ง๋ง ๊ฐ๋จํ ๊ฒ์ํด๋ณด๋ฉด OpenAPI๋ฅผ ์ํ ๋์ UI๊ฐ ์์ญ ๊ฐ์ง๋ ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค(**FastAPI**์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค).
Flask REST framework๋ ์ฌ๋ฌ ๊ฐ๊ฐ ์์ง๋ง, ์๊ฐ์ ๋ค์ฌ ์กฐ์ฌํด ๋ณธ ๊ฒฐ๊ณผ, ์๋น์๊ฐ ์ค๋จ๋์๊ฑฐ๋ ๋ฐฉ์น๋์ด ์์๊ณ , ํด๊ฒฐ๋์ง ์์ ์ฌ๋ฌ ์ด์ ๋๋ฌธ์ ์ ํฉํ์ง ์์ ๊ฒฝ์ฐ๊ฐ ๋ง์์ต๋๋ค.
-### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
+### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow }
API ์์คํ
์ ํ์ํ ์ฃผ์ ๊ธฐ๋ฅ ์ค ํ๋๋ ๋ฐ์ดํฐ "<dfn title="๋ง์ฌ๋ง, ๋ณํ์ด๋ผ๊ณ ๋ ํจ">์ง๋ ฌํ</dfn>"์
๋๋ค. ์ด๋ ์ฝ๋(Python)์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ๋คํธ์ํฌ๋ก ์ ์กํ ์ ์๋ ํํ๋ก ๋ณํํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ฐ์ฒด๋ฅผ JSON ๊ฐ์ฒด๋ก ๋ณํํ๊ฑฐ๋, `datetime` ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ๋ ๋ฑ์ ์์
์
๋๋ค.
///
-### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
+### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs }
API์ ํ์ํ ๋ ๋ค๋ฅธ ํฐ ๊ธฐ๋ฅ์ ๋ค์ด์ค๋ ์์ฒญ์์ ๋ฐ์ดํฐ๋ฅผ <dfn title="์ฝ์ด์ Python ๋ฐ์ดํฐ๋ก ๋ณํํ๊ธฐ">ํ์ฑ</dfn>ํ๋ ๊ฒ์
๋๋ค.
///
-### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
+### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec }
Marshmallow์ Webargs๋ plug-in ํํ๋ก ๊ฒ์ฆ, parsing, serialization์ ์ ๊ณตํฉ๋๋ค.
///
-### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
+### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec }
Flask plug-in์ผ๋ก, Webargs, Marshmallow, APISpec์ ๋ฌถ์ด์ค๋๋ค.
์ด๋ฅผ ์ฌ์ฉํ๋ฉด์ ์ฌ๋ฌ Flask full-stack generator๊ฐ ๋ง๋ค์ด์ก์ต๋๋ค. ์ด๊ฒ๋ค์ด ์ง๊ธ๊น์ง ์ (๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ์ธ๋ถ ํ)๊ฐ ์ฌ์ฉํด ์จ ์ฃผ์ stack์
๋๋ค:
-* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
-* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
-* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
+* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack)
+* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase)
+* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb)
-๊ทธ๋ฆฌ๊ณ ์ด ๋์ผํ full-stack generator๋ค์ด [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}์ ๊ธฐ๋ฐ์ด ๋์์ต๋๋ค.
+๊ทธ๋ฆฌ๊ณ ์ด ๋์ผํ full-stack generator๋ค์ด [**FastAPI** Project Generators](project-generation.md)์ ๊ธฐ๋ฐ์ด ๋์์ต๋๋ค.
/// info | ์ ๋ณด
///
-### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (๊ทธ๋ฆฌ๊ณ <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
+### [NestJS](https://nestjs.com/) (๊ทธ๋ฆฌ๊ณ [Angular](https://angular.io/)) { #nestjs-and-angular }
์ด๊ฑด Python๋ ์๋๋๋ค. NestJS๋ Angular์์ ์๊ฐ์ ๋ฐ์ JavaScript(TypeScript) NodeJS framework์
๋๋ค.
///
-### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
+### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic }
`asyncio` ๊ธฐ๋ฐ์ ๋งค์ฐ ๋น ๋ฅธ Python framework ์ค ์ด๊ธฐ ์ฌ๋ก์์ต๋๋ค. Flask์ ๋งค์ฐ ์ ์ฌํ๊ฒ ๋ง๋ค์ด์ก์ต๋๋ค.
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
-๊ธฐ๋ณธ Python `asyncio` ๋ฃจํ ๋์ <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a>๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ์ด๊ฒ์ด ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ง๋ ์์ธ์
๋๋ค.
+[`uvloop`](https://github.com/MagicStack/uvloop)๋ฅผ ๊ธฐ๋ณธ Python `asyncio` ๋ฃจํ ๋์ ์ฌ์ฉํ์ต๋๋ค. ์ด๊ฒ์ด ๋งค์ฐ ๋น ๋ฅด๊ฒ ๋ง๋ ์์ธ์
๋๋ค.
์ด๋ Uvicorn๊ณผ Starlette์ ๋ช
ํํ ์๊ฐ์ ์ฃผ์๊ณ , ํ์ฌ ๊ณต๊ฐ benchmark์์๋ ์ด ๋์ด Sanic๋ณด๋ค ๋ ๋น ๋ฆ
๋๋ค.
///
-### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
+### [Falcon](https://falconframework.org/) { #falcon }
Falcon์ ๋ ๋ค๋ฅธ ๊ณ ์ฑ๋ฅ Python framework๋ก, ์ต์ํ์ผ๋ก ์ค๊ณ๋์๊ณ Hug ๊ฐ์ ๋ค๋ฅธ framework์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋๋ก ๋ง๋ค์ด์ก์ต๋๋ค.
///
-### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
+### [Molten](https://moltenframework.com/) { #molten }
**FastAPI**๋ฅผ ๋ง๋ค๊ธฐ ์์ํ ์ด๊ธฐ ๋จ๊ณ์์ Molten์ ์๊ฒ ๋์๊ณ , ๊ฝค ๋น์ทํ ์์ด๋์ด๋ฅผ ๊ฐ๊ณ ์์์ต๋๋ค:
///
-### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
+### [Hug](https://github.com/hugapi/hug) { #hug }
Hug๋ Python type hints๋ฅผ ์ฌ์ฉํด API ํ๋ผ๋ฏธํฐ ํ์
์ ์ ์ธํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ด๊ธฐ framework ์ค ํ๋์์ต๋๋ค. ์ด๋ ๋ค๋ฅธ ๋๊ตฌ๋ค๋ ๊ฐ์ ๋ฐฉ์์ ํ๋๋ก ์๊ฐ์ ์ค ํ๋ฅญํ ์์ด๋์ด์์ต๋๋ค.
/// info | ์ ๋ณด
-Hug๋ Timothy Crosley๊ฐ ๋ง๋ค์์ต๋๋ค. Python ํ์ผ์์ import๋ฅผ ์๋์ผ๋ก ์ ๋ ฌํ๋ ํ๋ฅญํ ๋๊ตฌ์ธ <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>์ ์ ์์์ด๊ธฐ๋ ํฉ๋๋ค.
+Hug๋ Timothy Crosley๊ฐ ๋ง๋ค์์ต๋๋ค. Python ํ์ผ์์ import๋ฅผ ์๋์ผ๋ก ์ ๋ ฌํ๋ ํ๋ฅญํ ๋๊ตฌ์ธ [`isort`](https://github.com/timothycrosley/isort)์ ์ ์์์ด๊ธฐ๋ ํฉ๋๋ค.
///
///
-### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
+### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 }
**FastAPI**๋ฅผ ๋ง๋ค๊ธฐ๋ก ๊ฒฐ์ ํ๊ธฐ ์ง์ ์ **APIStar** ์๋ฒ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค. ์ฐพ๊ณ ์๋ ๊ฑฐ์ ๋ชจ๋ ๊ฒ์ ๊ฐ์ถ๊ณ ์์๊ณ ์ค๊ณ๋ ํ๋ฅญํ์ต๋๋ค.
## **FastAPI**๊ฐ ์ฌ์ฉํ๋ ๊ฒ { #used-by-fastapi }
-### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
+### [Pydantic](https://docs.pydantic.dev/) { #pydantic }
Pydantic์ Python type hints๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ ๊ฒ์ฆ, serialization, ๋ฌธ์ํ(JSON Schema ์ฌ์ฉ)๋ฅผ ์ ์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
///
-### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
+### [Starlette](https://www.starlette.dev/) { #starlette }
Starlette๋ ๊ฒฝ๋ <dfn title="๋น๋๊ธฐ Python ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๊ธฐ ์ํ ์๋ก์ด ํ์ค">ASGI</dfn> framework/toolkit์ผ๋ก, ๊ณ ์ฑ๋ฅ asyncio ์๋น์ค๋ฅผ ๋ง๋ค๊ธฐ์ ์ด์์ ์
๋๋ค.
///
-### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
+### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn }
Uvicorn์ uvloop๊ณผ httptools๋ก ๊ตฌ์ถ๋ ์ด๊ณ ์ ASGI ์๋ฒ์
๋๋ค.
๋ํ `--workers` ์ปค๋งจ๋๋ผ์ธ ์ต์
์ ์ฌ์ฉํ๋ฉด ๋น๋๊ธฐ ๋ฉํฐํ๋ก์ธ์ค ์๋ฒ๋ก ์คํํ ์๋ ์์ต๋๋ค.
-์์ธํ ๋ด์ฉ์ [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank} ์น์
์ ํ์ธํ์ธ์.
+์์ธํ ๋ด์ฉ์ [๋ฐฐํฌ](deployment/index.md) ์น์
์ ํ์ธํ์ธ์.
///
## ๋ฒค์น๋งํฌ์ ์๋ { #benchmarks-and-speed }
-Uvicorn, Starlette, FastAPI ์ฌ์ด์ ์ฐจ์ด๋ฅผ ์ดํดํ๊ณ ๋น๊ตํ๋ ค๋ฉด [๋ฒค์น๋งํฌ](benchmarks.md){.internal-link target=_blank} ์น์
์ ํ์ธํ์ธ์.
+Uvicorn, Starlette, FastAPI ์ฌ์ด์ ์ฐจ์ด๋ฅผ ์ดํดํ๊ณ ๋น๊ตํ๋ ค๋ฉด [๋ฒค์น๋งํฌ](benchmarks.md) ์น์
์ ํ์ธํ์ธ์.
/// info | ์ ๋ณด
-์๋ฆ๋ค์ด ์ผ๋ฌ์คํธ: <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. ๐จ
+์๋ฆ๋ค์ด ์ผ๋ฌ์คํธ: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). ๐จ
///
/// info | ์ ๋ณด
-์๋ฆ๋ค์ด ์ผ๋ฌ์คํธ: <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. ๐จ
+์๋ฆ๋ค์ด ์ผ๋ฌ์คํธ: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). ๐จ
///
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ด **FastAPI**๋ก ์ป๋ ๊ฒ๊ณผ ๊ฐ์ ์์ค์ ์ฑ๋ฅ์
๋๋ค.
-๋ํ ๋ณ๋ ฌ์ฑ๊ณผ ๋น๋๊ธฐ์ฑ์ ๋์์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ๋๋ถ๋ถ์ ํ
์คํธ๋ NodeJS ํ๋ ์์ํฌ๋ณด๋ค ๋ ๋์ ์ฑ๋ฅ์ ์ป๊ณ , C์ ๋ ๊ฐ๊น์ด ์ปดํ์ผ ์ธ์ด์ธ Go์ ๋๋ฑํ ์ฑ๋ฅ์ ์ป์ ์ ์์ต๋๋ค <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(๋ชจ๋ Starlette ๋๋ถ์
๋๋ค)</a>.
+๋ํ ๋ณ๋ ฌ์ฑ๊ณผ ๋น๋๊ธฐ์ฑ์ ๋์์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ๋๋ถ๋ถ์ ํ
์คํธ๋ NodeJS ํ๋ ์์ํฌ๋ณด๋ค ๋ ๋์ ์ฑ๋ฅ์ ์ป๊ณ , C์ ๋ ๊ฐ๊น์ด ์ปดํ์ผ ์ธ์ด์ธ Go์ ๋๋ฑํ ์ฑ๋ฅ์ ์ป์ ์ ์์ต๋๋ค [(๋ชจ๋ Starlette ๋๋ถ์
๋๋ค)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1).
### ๋์์ฑ์ด ๋ณ๋ ฌ์ฑ๋ณด๋ค ๋ ๋์๊ฐ์? { #is-concurrency-better-than-parallelism }
์ด๊ฒ์ ํ์ด์ฌ์ด **๋ฐ์ดํฐ ์ฌ์ด์ธ์ค**, ๋จธ์ ๋ฌ๋, ํนํ ๋ฅ๋ฌ๋์ ์ฃผ์ ์ธ์ด๋ผ๋ ๋จ์ํ ์ฌ์ค๊ณผ ๋ํด์ ธ, FastAPI๋ฅผ ๋ฐ์ดํฐ ์ฌ์ด์ธ์ค/๋จธ์ ๋ฌ๋ ์น API ๋ฐ ์ ํ๋ฆฌ์ผ์ด์
(๊ทธ ์ธ์๋ ๋ง์ ๊ฒ๋ค)์ ๋งค์ฐ ์ ๋ง๋ ์ ํ์ผ๋ก ๋ง๋ค์ด ์ค๋๋ค.
-ํ๋ก๋์
์์ ์ด ๋ณ๋ ฌ์ฑ์ ์ด๋ป๊ฒ ๋ฌ์ฑํ๋์ง ๋ณด๋ ค๋ฉด [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank} ์น์
์ ์ฐธ๊ณ ํ์ธ์.
+ํ๋ก๋์
์์ ์ด ๋ณ๋ ฌ์ฑ์ ์ด๋ป๊ฒ ๋ฌ์ฑํ๋์ง ๋ณด๋ ค๋ฉด [๋ฐฐํฌ](deployment/index.md) ์น์
์ ์ฐธ๊ณ ํ์ธ์.
## `async`์ `await` { #async-and-await }
### ์ฌ๋ฌ๋ถ๋ง์ async ์ฝ๋ ์์ฑํ๊ธฐ { #write-your-own-async-code }
-Starlette(๊ทธ๋ฆฌ๊ณ **FastAPI**)๋ <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์์ผ๋ฉฐ, ํ์ด์ฌ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a>์ <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a> ๋ชจ๋์ ํธํ๋ฉ๋๋ค.
+Starlette(๊ทธ๋ฆฌ๊ณ **FastAPI**)๋ [AnyIO](https://anyio.readthedocs.io/en/stable/)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์์ผ๋ฉฐ, ํ์ด์ฌ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ [asyncio](https://docs.python.org/3/library/asyncio-task.html)์ [Trio](https://trio.readthedocs.io/en/stable/) ๋ชจ๋์ ํธํ๋ฉ๋๋ค.
-ํนํ, ์ฝ๋์์ ๋ ๊ณ ๊ธ ํจํด์ด ํ์ํ ๊ณ ๊ธ ๋์์ฑ ์ฌ์ฉ ์ฌ๋ก์์๋ ์ง์ <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+ํนํ, ์ฝ๋์์ ๋ ๊ณ ๊ธ ํจํด์ด ํ์ํ ๊ณ ๊ธ ๋์์ฑ ์ฌ์ฉ ์ฌ๋ก์์๋ ์ง์ [AnyIO](https://anyio.readthedocs.io/en/stable/)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-๊ทธ๋ฆฌ๊ณ FastAPI๋ฅผ ์ฌ์ฉํ์ง ์๋๋ผ๋, ๋์ ํธํ์ฑ์ ํ๋ณดํ๊ณ ๊ทธ ์ด์ (์: *structured concurrency*)์ ์ป๊ธฐ ์ํด <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>๋ก ์ฌ๋ฌ๋ถ๋ง์ async ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฑํ ์๋ ์์ต๋๋ค.
+๊ทธ๋ฆฌ๊ณ FastAPI๋ฅผ ์ฌ์ฉํ์ง ์๋๋ผ๋, ๋์ ํธํ์ฑ์ ํ๋ณดํ๊ณ ๊ทธ ์ด์ (์: *structured concurrency*)์ ์ป๊ธฐ ์ํด [AnyIO](https://anyio.readthedocs.io/en/stable/)๋ก ์ฌ๋ฌ๋ถ๋ง์ async ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฑํ ์๋ ์์ต๋๋ค.
-์ ๋ AnyIO ์์ ์์ ๋ ์ด์ด๋ก ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค์๋๋ฐ, ํ์
์ด๋
ธํ
์ด์
์ ์กฐ๊ธ ๊ฐ์ ํ๊ณ ๋ ๋์ **์๋์์ฑ**, **์ธ๋ผ์ธ ์ค๋ฅ** ๋ฑ์ ์ป๊ธฐ ์ํ ๊ฒ์
๋๋ค. ๋ํ **์ดํด**ํ๊ณ **์ฌ๋ฌ๋ถ๋ง์ async ์ฝ๋**๋ฅผ ์์ฑํ๋๋ก ๋๋ ์น์ ํ ์๊ฐ์ ํํ ๋ฆฌ์ผ๋ ์ ๊ณตํฉ๋๋ค: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. ํนํ **async ์ฝ๋์ ์ผ๋ฐ**(blocking/๋๊ธฐ) ์ฝ๋๋ฅผ **๊ฒฐํฉ**ํด์ผ ํ๋ค๋ฉด ์์ฃผ ์ ์ฉํฉ๋๋ค.
+์ ๋ AnyIO ์์ ์์ ๋ ์ด์ด๋ก ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค์๋๋ฐ, ํ์
์ด๋
ธํ
์ด์
์ ์กฐ๊ธ ๊ฐ์ ํ๊ณ ๋ ๋์ **์๋์์ฑ**, **์ธ๋ผ์ธ ์ค๋ฅ** ๋ฑ์ ์ป๊ธฐ ์ํ ๊ฒ์
๋๋ค. ๋ํ **์ดํด**ํ๊ณ **์ฌ๋ฌ๋ถ๋ง์ async ์ฝ๋**๋ฅผ ์์ฑํ๋๋ก ๋๋ ์น์ ํ ์๊ฐ์ ํํ ๋ฆฌ์ผ๋ ์ ๊ณตํฉ๋๋ค: [Asyncer](https://asyncer.tiangolo.com/). ํนํ **async ์ฝ๋์ ์ผ๋ฐ**(blocking/๋๊ธฐ) ์ฝ๋๋ฅผ **๊ฒฐํฉ**ํด์ผ ํ๋ค๋ฉด ์์ฃผ ์ ์ฉํฉ๋๋ค.
### ๋น๋๊ธฐ ์ฝ๋์ ๋ค๋ฅธ ํํ { #other-forms-of-asynchronous-code }
ํ์ง๋ง ๊ทธ ์ด์ ์๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ํจ์ฌ ๋ ๋ณต์กํ๊ณ ์ด๋ ค์ ์ต๋๋ค.
-์ด์ ๋ฒ์ ์ ํ์ด์ฌ์์๋ ์ค๋ ๋ ๋๋ <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>๋ฅผ ์ฌ์ฉํ ์ ์์์ ๊ฒ์
๋๋ค. ํ์ง๋ง ์ฝ๋๋ฅผ ์ดํดํ๊ณ , ๋๋ฒ๊น
ํ๊ณ , ์ด์ ๋ํด ์๊ฐํ๋ ๊ฒ์ด ํจ์ฌ ๋ ๋ณต์กํฉ๋๋ค.
+์ด์ ๋ฒ์ ์ ํ์ด์ฌ์์๋ ์ค๋ ๋ ๋๋ [Gevent](https://www.gevent.org/)๋ฅผ ์ฌ์ฉํ ์ ์์์ ๊ฒ์
๋๋ค. ํ์ง๋ง ์ฝ๋๋ฅผ ์ดํดํ๊ณ , ๋๋ฒ๊น
ํ๊ณ , ์ด์ ๋ํด ์๊ฐํ๋ ๊ฒ์ด ํจ์ฌ ๋ ๋ณต์กํฉ๋๋ค.
์ด์ ๋ฒ์ ์ NodeJS/๋ธ๋ผ์ฐ์ JavaScript์์๋ "callback"์ ์ฌ์ฉํ์ ๊ฒ์
๋๋ค. ์ด๋ "callback hell"๋ก ์ด์ด์ง๋๋ค.
์์์ ์ค๋ช
ํ ๋ฐฉ์์ผ๋ก ๋์ํ์ง ์๋ ๋ค๋ฅธ async ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด๋ณธ ์ ์ด ์๊ณ , ์์ฃผ ์์ ์ฑ๋ฅ ํฅ์(์ฝ 100 ๋๋
ธ์ด)์ ์ํด ๊ณ์ฐ๋ง ํ๋ ์ฌ์ํ *๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*๋ฅผ ์ผ๋ฐ `def`๋ก ์ ์ํ๊ณค ํ๋ค๋ฉด, **FastAPI**์์๋ ๊ทธ ํจ๊ณผ๊ฐ ์ ๋ฐ๋๊ฐ ๋ ์ ์๋ค๋ ์ ์ ์ ์ํ์ธ์. ์ด๋ฐ ๊ฒฝ์ฐ์๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์์ ๋ธ๋กํน <abbr title="Input/Output - ์
๋ ฅ/์ถ๋ ฅ: ๋์คํฌ ์ฝ๊ธฐ ๋๋ ์ฐ๊ธฐ, ๋คํธ์ํฌ ํต์ .">I/O</abbr> ๋ฅผ ์ํํ๋ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ง ์๋ ํ `async def`๋ฅผ ์ฌ์ฉํ๋ ํธ์ด ๋ ๋ซ์ต๋๋ค.
-๊ทธ๋ผ์๋ ๋ ๊ฒฝ์ฐ ๋ชจ๋, **FastAPI**๋ ์ด์ ์ ์ฌ์ฉํ๋ ํ๋ ์์ํฌ๋ณด๋ค [์ฌ์ ํ ๋ ๋น ๋ฅผ](index.md#performance){.internal-link target=_blank} ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค(๋๋ ์ต์ํ ๋น์ทํฉ๋๋ค).
+๊ทธ๋ผ์๋ ๋ ๊ฒฝ์ฐ ๋ชจ๋, **FastAPI**๋ ์ด์ ์ ์ฌ์ฉํ๋ ํ๋ ์์ํฌ๋ณด๋ค [์ฌ์ ํ ๋ ๋น ๋ฅผ](index.md#performance) ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค(๋๋ ์ต์ํ ๋น์ทํฉ๋๋ค).
### ์์กด์ฑ { #dependencies }
-[์์กด์ฑ](tutorial/dependencies/index.md){.internal-link target=_blank}์๋ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค. ์์กด์ฑ์ด `async def` ๋์ ํ์ค `def` ํจ์๋ผ๋ฉด, ์ธ๋ถ ์ค๋ ๋ํ์์ ์คํ๋ฉ๋๋ค.
+[์์กด์ฑ](tutorial/dependencies/index.md)์๋ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค. ์์กด์ฑ์ด `async def` ๋์ ํ์ค `def` ํจ์๋ผ๋ฉด, ์ธ๋ถ ์ค๋ ๋ํ์์ ์คํ๋ฉ๋๋ค.
### ํ์ ์์กด์ฑ { #sub-dependencies }
-์๋ก๋ฅผ ํ์๋ก ํ๋ ์ฌ๋ฌ ์์กด์ฑ๊ณผ [ํ์ ์์กด์ฑ](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}์ ํจ์ ์ ์์ ๋งค๊ฐ๋ณ์๋ก ๊ฐ์ง ์ ์์ผ๋ฉฐ, ๊ทธ์ค ์ผ๋ถ๋ `async def`๋ก, ๋ค๋ฅธ ์ผ๋ถ๋ ์ผ๋ฐ `def`๋ก ์์ฑ๋์์ ์ ์์ต๋๋ค. ๊ทธ๋๋ ์ ์ ๋์ํ๋ฉฐ, ์ผ๋ฐ `def`๋ก ์์ฑ๋ ๊ฒ๋ค์ "await"๋๋ ๋์ (์ค๋ ๋ํ์์) ์ธ๋ถ ์ค๋ ๋์์ ํธ์ถ๋ฉ๋๋ค.
+์๋ก๋ฅผ ํ์๋ก ํ๋ ์ฌ๋ฌ ์์กด์ฑ๊ณผ [ํ์ ์์กด์ฑ](tutorial/dependencies/sub-dependencies.md)์ ํจ์ ์ ์์ ๋งค๊ฐ๋ณ์๋ก ๊ฐ์ง ์ ์์ผ๋ฉฐ, ๊ทธ์ค ์ผ๋ถ๋ `async def`๋ก, ๋ค๋ฅธ ์ผ๋ถ๋ ์ผ๋ฐ `def`๋ก ์์ฑ๋์์ ์ ์์ต๋๋ค. ๊ทธ๋๋ ์ ์ ๋์ํ๋ฉฐ, ์ผ๋ฐ `def`๋ก ์์ฑ๋ ๊ฒ๋ค์ "await"๋๋ ๋์ (์ค๋ ๋ํ์์) ์ธ๋ถ ์ค๋ ๋์์ ํธ์ถ๋ฉ๋๋ค.
### ๋ค๋ฅธ ์ ํธ๋ฆฌํฐ ํจ์ { #other-utility-functions }
# ๋ฒค์น๋งํฌ { #benchmarks }
-๋
๋ฆฝ์ ์ธ TechEmpower ๋ฒค์น๋งํฌ์ ๋ฐ๋ฅด๋ฉด **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ด Uvicorn์ ์ฌ์ฉํ์ฌ <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋</a>๋ก ์คํ๋๋ฉฐ, Starlette์ Uvicorn ์์ฒด(๋ด๋ถ์ ์ผ๋ก FastAPI๊ฐ ์ฌ์ฉํ๋ ๋๊ตฌ)๋ณด๋ค ์กฐ๊ธ ์๋์ ์์นํฉ๋๋ค.
+๋
๋ฆฝ์ ์ธ TechEmpower ๋ฒค์น๋งํฌ์ ๋ฐ๋ฅด๋ฉด **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ด Uvicorn์ ์ฌ์ฉํ์ฌ [์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)๋ก ์คํ๋๋ฉฐ, Starlette์ Uvicorn ์์ฒด(๋ด๋ถ์ ์ผ๋ก FastAPI๊ฐ ์ฌ์ฉํ๋ ๋๊ตฌ)๋ณด๋ค ์กฐ๊ธ ์๋์ ์์นํฉ๋๋ค.
๊ทธ๋ฌ๋ ๋ฒค์น๋งํฌ์ ๋น๊ต๋ฅผ ํ์ธํ ๋ ๋ค์ ์ฌํญ์ ์ผ๋์ ๋์ด์ผ ํฉ๋๋ค.
## FastAPI Cloud { #fastapi-cloud }
-**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**๋ **FastAPI**๋ฅผ ๋ง๋ ๋์ผํ ์์ฑ์์ ํ์ด ๊ตฌ์ถํ์ต๋๋ค.
+**[FastAPI Cloud](https://fastapicloud.com)**๋ **FastAPI**๋ฅผ ๋ง๋ ๋์ผํ ์์ฑ์์ ํ์ด ๊ตฌ์ถํ์ต๋๋ค.
์ต์ํ์ ๋
ธ๋ ฅ์ผ๋ก API๋ฅผ **๊ตฌ์ถ**, **๋ฐฐํฌ**, **์ ๊ทผ**ํ๋ ๊ณผ์ ์ ๊ฐ์ํํฉ๋๋ค.
## ํด๋ผ์ฐ๋ ์ ๊ณต์
์ฒด - ํ์์๋ค { #cloud-providers-sponsors }
-๋ค๋ฅธ ๋ช๋ช ํด๋ผ์ฐ๋ ์ ๊ณต์
์ฒด๋ค๋ โจ [**FastAPI๋ฅผ ํ์ํฉ๋๋ค**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โจ. ๐
+๋ค๋ฅธ ๋ช๋ช ํด๋ผ์ฐ๋ ์ ๊ณต์
์ฒด๋ค๋ โจ [**FastAPI๋ฅผ ํ์ํฉ๋๋ค**](../help-fastapi.md#sponsor-the-author) โจ. ๐
๊ฐ์ด๋๋ฅผ ๋ฐ๋ผ ํ๊ณ ์๋น์ค๋ฅผ ์ฌ์ฉํด๋ณด๊ธฐ ์ํด ์ด๋ค๋ ๊ณ ๋ คํด๋ณผ ์ ์์ต๋๋ค:
-* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
-* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>
+* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi)
+* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi)
## ๋ณด์ - HTTPS { #security-https }
-[์ด์ HTTPS ์ฅ](https.md){.internal-link target=_blank}์์ HTTPS๊ฐ API์ ์ํธํ๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ์์ ๋ํด ๋ฐฐ์ ์ต๋๋ค.
+[์ด์ HTTPS ์ฅ](https.md)์์ HTTPS๊ฐ API์ ์ํธํ๋ฅผ ์ ๊ณตํ๋ ๋ฐฉ์์ ๋ํด ๋ฐฐ์ ์ต๋๋ค.
๋ํ HTTPS๋ ์ผ๋ฐ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์๋ฒ ๋ฐ๊นฅ์ **์ธ๋ถ** ์ปดํฌ๋ํธ์ธ **TLS Termination Proxy**๊ฐ ์ ๊ณตํ๋ค๋ ๊ฒ๋ ํ์ธํ์ต๋๋ค.
### ์์ปค ํ๋ก์ธ์ค์ ํฌํธ { #worker-processes-and-ports }
-[HTTPS์ ๋ํ ๋ฌธ์](https.md){.internal-link target=_blank}์์, ์๋ฒ์์ ํ๋์ ํฌํธ์ IP ์ฃผ์ ์กฐํฉ์๋ ํ๋์ ํ๋ก์ธ์ค๋ง ๋ฆฌ์ค๋ํ ์ ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์๋์?
+[HTTPS์ ๋ํ ๋ฌธ์](https.md)์์, ์๋ฒ์์ ํ๋์ ํฌํธ์ IP ์ฃผ์ ์กฐํฉ์๋ ํ๋์ ํ๋ก์ธ์ค๋ง ๋ฆฌ์ค๋ํ ์ ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์๋์?
์ด๊ฒ์ ์ฌ์ ํ ์ฌ์ค์
๋๋ค.
**์ปจํ
์ด๋**, Docker, Kubernetes์ ๋ํ ์ผ๋ถ ๋ด์ฉ์ด ์์ง์ ์ ์ดํด๋์ง ์์๋ ๊ด์ฐฎ์ต๋๋ค.
-๋ค์ ์ฅ์์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง, Docker, Kubernetes ๋ฑ์ ๋ ์ค๋ช
ํ๊ฒ ์ต๋๋ค: [์ปจํ
์ด๋์์ FastAPI - Docker](docker.md){.internal-link target=_blank}.
+๋ค์ ์ฅ์์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง, Docker, Kubernetes ๋ฑ์ ๋ ์ค๋ช
ํ๊ฒ ์ต๋๋ค: [์ปจํ
์ด๋์์ FastAPI - Docker](docker.md).
///
/// tip | ํ
-์ปจํ
์ด๋๋ก ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ ๊ตฌ์ฒด์ ์ธ ์์๋ ๋ค์ ์ฅ์์ ์ ๊ณตํ๊ฒ ์ต๋๋ค: [์ปจํ
์ด๋์์ FastAPI - Docker](docker.md){.internal-link target=_blank}.
+์ปจํ
์ด๋๋ก ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ ๊ตฌ์ฒด์ ์ธ ์์๋ ๋ค์ ์ฅ์์ ์ ๊ณตํ๊ฒ ์ต๋๋ค: [์ปจํ
์ด๋์์ FastAPI - Docker](docker.md).
///
# ์ปจํ
์ด๋์ FastAPI - ๋์ปค { #fastapi-in-containers-docker }
-FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๋ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ๋ฒ์ **๋ฆฌ๋
์ค ์ปจํ
์ด๋ ์ด๋ฏธ์ง**๋ฅผ ๋น๋ํ๋ ๊ฒ์
๋๋ค. ๋ณดํต <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>๋ฅผ ์ฌ์ฉํด ์ํํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํด๋น ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๋ช ๊ฐ์ง ๊ฐ๋ฅํ ๋ฐฉ๋ฒ ์ค ํ๋๋ก ๋ฐฐํฌํ ์ ์์ต๋๋ค.
+FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๋ ์ผ๋ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ๋ฒ์ **๋ฆฌ๋
์ค ์ปจํ
์ด๋ ์ด๋ฏธ์ง**๋ฅผ ๋น๋ํ๋ ๊ฒ์
๋๋ค. ๋ณดํต [**Docker**](https://www.docker.com/)๋ฅผ ์ฌ์ฉํด ์ํํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํด๋น ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ๋ช ๊ฐ์ง ๊ฐ๋ฅํ ๋ฐฉ๋ฒ ์ค ํ๋๋ก ๋ฐฐํฌํ ์ ์์ต๋๋ค.
๋ฆฌ๋
์ค ์ปจํ
์ด๋๋ฅผ ์ฌ์ฉํ๋ฉด **๋ณด์**, **์ฌํ ๊ฐ๋ฅ์ฑ**, **๋จ์ํจ** ๋ฑ ์ฌ๋ฌ ์ฅ์ ์ด ์์ต๋๋ค.
Docker๋ **์ปจํ
์ด๋ ์ด๋ฏธ์ง**์ **์ปจํ
์ด๋**๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ์ฃผ์ ๋๊ตฌ ์ค ํ๋์
๋๋ค.
-๋ํ <a href="https://hub.docker.com/" class="external-link" target="_blank">Docker Hub</a>์๋ ๋ค์ํ ๋๊ตฌ, ํ๊ฒฝ, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง **๊ณต์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง**๊ฐ ๊ณต๊ฐ๋์ด ์์ต๋๋ค.
+๋ํ [Docker Hub](https://hub.docker.com/)์๋ ๋ค์ํ ๋๊ตฌ, ํ๊ฒฝ, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง **๊ณต์ ์ปจํ
์ด๋ ์ด๋ฏธ์ง**๊ฐ ๊ณต๊ฐ๋์ด ์์ต๋๋ค.
-์๋ฅผ ๋ค์ด, ๊ณต์ <a href="https://hub.docker.com/_/python" class="external-link" target="_blank">Python Image</a>๊ฐ ์์ต๋๋ค.
+์๋ฅผ ๋ค์ด, ๊ณต์ [Python Image](https://hub.docker.com/_/python)๊ฐ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฑ ๋ค์ํ ์ฉ๋์ ๋ค๋ฅธ ์ด๋ฏธ์ง๋ ๋ง์ด ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด:
-* <a href="https://hub.docker.com/_/postgres" class="external-link" target="_blank">PostgreSQL</a>
-* <a href="https://hub.docker.com/_/mysql" class="external-link" target="_blank">MySQL</a>
-* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
-* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a> ๋ฑ
+* [PostgreSQL](https://hub.docker.com/_/postgres)
+* [MySQL](https://hub.docker.com/_/mysql)
+* [MongoDB](https://hub.docker.com/_/mongo)
+* [Redis](https://hub.docker.com/_/redis) ๋ฑ
๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง ์ปจํ
์ด๋ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ก ๋ค๋ฅธ ๋๊ตฌ๋ฅผ **๊ฒฐํฉ**ํ๊ณ ์ฌ์ฉํ๊ธฐ๊ฐ ๋งค์ฐ ์ฝ์ต๋๋ค. ์๋ฅผ ๋ค์ด ์๋ก์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ํํด ๋ณผ ๋๋ ๊ทธ๋ ์ต๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ **๊ณต์ ์ด๋ฏธ์ง**๋ฅผ ์ฌ์ฉํ๊ณ , ํ๊ฒฝ ๋ณ์๋ก ์ค์ ๋ง ํ๋ฉด ๋ฉ๋๋ค.
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ํจํค์ง ์ด๋ฆ๊ณผ ๋ฒ์ ์ ํ ์ค์ ํ๋์ฉ ์ ์ด ๋ `requirements.txt` ํ์ผ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
-๋ฒ์ ๋ฒ์๋ฅผ ์ค์ ํ ๋๋ [FastAPI ๋ฒ์ ๋ค์ ๋ํ์ฌ](versions.md){.internal-link target=_blank}์์ ์ฝ์ ๊ฒ๊ณผ ๊ฐ์ ์์ด๋์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
+๋ฒ์ ๋ฒ์๋ฅผ ์ค์ ํ ๋๋ [FastAPI ๋ฒ์ ๋ค์ ๋ํ์ฌ](versions.md)์์ ์ฝ์ ๊ฒ๊ณผ ๊ฐ์ ์์ด๋์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด `requirements.txt`๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
#### `CMD` ์ฌ์ฉํ๊ธฐ - Exec Form { #use-cmd-exec-form }
-Docker ์ง์์ด <a href="https://docs.docker.com/reference/dockerfile/#cmd" class="external-link" target="_blank">`CMD`</a>๋ ๋ ๊ฐ์ง ํ์์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค:
+Docker ์ง์์ด [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd)๋ ๋ ๊ฐ์ง ํ์์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค:
โ
**Exec** form:
CMD fastapi run app/main.py --port 80
```
-FastAPI๊ฐ ์ ์์ ์ผ๋ก ์ข
๋ฃ(graceful shutdown)๋๊ณ [lifespan ์ด๋ฒคํธ](../advanced/events.md){.internal-link target=_blank}๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋๋ก ํ๋ ค๋ฉด, ํญ์ **exec** form์ ์ฌ์ฉํ์ธ์.
+FastAPI๊ฐ ์ ์์ ์ผ๋ก ์ข
๋ฃ(graceful shutdown)๋๊ณ [lifespan ์ด๋ฒคํธ](../advanced/events.md)๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋๋ก ํ๋ ค๋ฉด, ํญ์ **exec** form์ ์ฌ์ฉํ์ธ์.
-์์ธํ ๋ด์ฉ์ <a href="https://docs.docker.com/reference/dockerfile/#shell-and-exec-form" class="external-link" target="_blank">shell and exec form์ ๋ํ Docker ๋ฌธ์</a>๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+์์ธํ ๋ด์ฉ์ [shell and exec form์ ๋ํ Docker ๋ฌธ์](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
-์ด๋ `docker compose`๋ฅผ ์ฌ์ฉํ ๋ ๊ฝค ๋์ ๋ ์ ์์ต๋๋ค. ์ข ๋ ๊ธฐ์ ์ ์ธ ์์ธ ๋ด์ฉ์ Docker Compose FAQ ์น์
์ ์ฐธ๊ณ ํ์ธ์: <a href="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop" class="external-link" target="_blank">Why do my services take 10 seconds to recreate or stop?</a>.
+์ด๋ `docker compose`๋ฅผ ์ฌ์ฉํ ๋ ๊ฝค ๋์ ๋ ์ ์์ต๋๋ค. ์ข ๋ ๊ธฐ์ ์ ์ธ ์์ธ ๋ด์ฉ์ Docker Compose FAQ ์น์
์ ์ฐธ๊ณ ํ์ธ์: [Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop).
#### ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ { #directory-structure }
ํจํค์ง ์์กด์ฑ์ ๋ค์ด๋ก๋ํ๊ณ ์ค์นํ๋ ๋ฐ์๋ **๋ช ๋ถ**์ด ๊ฑธ๋ฆด ์ ์์ง๋ง, **์บ์**๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์์ผ **๋ช ์ด**๋ฉด ๋๋ฉ๋๋ค.
-รซ\98\90รญ\95\9c รชยฐ\9cรซยฐ\9c รฌยค\91รฌ\97\90 รฌยฝ\94รซ\93\9c รซยณ\80รชยฒยฝ รฌ\82ยฌรญ\95ยญรฌ\9dยด รซ\8f\99รฌ\9e\91รญ\95\98รซ\8a\94รฌยง\80 รญ\99\95รฌ\9dยธรญ\95\98รชยธยฐ รฌ\9c\84รญ\95ยด รฌยปยจรญ\85\8cรฌ\9dยดรซ\84\88 รฌ\9dยดรซยฏยธรฌยง\80รซยฅยผ รชยณ\84รฌ\86\8d รซยน\8cรซ\93\9cรญ\95\98รชยฒ\8c รซ\90\98รซยฏ\80รซยก\9c, รฌ\9dยดรซย \87รชยฒ\8c รฌย \88รฌ\95ยฝรซ\90\98รซ\8a\94 รฌ\8b\9cรชยฐ\84รฌ\9d\80 รซ\88\84รฌย \81๋์ด ์๋นํ ์ปค์ง๋๋ค.
+รซ\98\90รญ\95\9c รชยฐ\9cรซยฐ\9c รฌยค\91รฌ\97\90 รฌยฝ\94รซ\93\9c รซยณ\80รชยฒยฝ รฌ\82ยฌรญ\95ยญรฌ\9dยด รซ\8f\99รฌ\9e\91รญ\95\98รซ\8a\94รฌยง\80 รญ\99\95รฌ\9dยธรญ\95\98รชยธยฐ รฌ\9c\84รญ\95ยด รฌยปยจรญ\85\8cรฌ\9dยดรซ\84\88 รฌ\9dยดรซยฏยธรฌยง\80รซยฅยผ รชยณ\84รฌ\86\8d รซยน\8cรซ\93\9cรญ\95\98รชยฒ\8c รซ\90\98รซยฏ\80รซยก\9c, รฌ\9dยดรซย \87รชยฒ\8c รฌย \88รฌ\95ยฝรซ\90\98รซ\8a\94 รฌ\8b\9cรชยฐ\84รฌ\9d\80 รซ\88\84รฌยค\91๋์ด ์๋นํ ์ปค์ง๋๋ค.
๊ทธ ๋ค์ `Dockerfile`์ ๋๋ถ๋ถ ๊ทผ์ฒ์์ ๋ชจ๋ ์ฝ๋๋ฅผ ๋ณต์ฌํฉ๋๋ค. ์ด ๋ถ๋ถ์ **๊ฐ์ฅ ์์ฃผ ๋ณ๊ฒฝ๋๋** ๋ถ๋ถ์ด๋ฏ๋ก, ๊ฑฐ์ ํญ์ ์ด ๋จ๊ณ ์ดํ์๋ ์บ์๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ ๋ก๋๋ค.
## ํ์ธํ๊ธฐ { #check-it }
-Docker ์ปจํ
์ด๋์ URL์์ ํ์ธํ ์ ์์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ๋๋ <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a>(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ํ์ธํ ์ ์์ต๋๋ค).
+Docker ์ปจํ
์ด๋์ URL์์ ํ์ธํ ์ ์์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) ๋๋ [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery)(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ํ์ธํ ์ ์์ต๋๋ค).
์๋์ ๊ฐ์ ๊ฒ์ ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค:
## ์ธํฐ๋ํฐ๋ธ API ๋ฌธ์ { #interactive-api-docs }
-์ด์ <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ๋๋ <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a>(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ์ ๊ทผ)๋ก ์ด๋ํ ์ ์์ต๋๋ค.
+์ด์ [http://192.168.99.100/docs](http://192.168.99.100/docs) ๋๋ [http://127.0.0.1/docs](http://127.0.0.1/docs)(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ์ ๊ทผ)๋ก ์ด๋ํ ์ ์์ต๋๋ค.
-์๋์ผ๋ก ์์ฑ๋ ์ธํฐ๋ํฐ๋ธ API ๋ฌธ์(<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> ์ ๊ณต)๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
+์๋์ผ๋ก ์์ฑ๋ ์ธํฐ๋ํฐ๋ธ API ๋ฌธ์([Swagger UI](https://github.com/swagger-api/swagger-ui) ์ ๊ณต)๋ฅผ ๋ณผ ์ ์์ต๋๋ค:

## ๋์ API ๋ฌธ์ { #alternative-api-docs }
-๋ํ <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ๋๋ <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a>(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ์ ๊ทผ)๋ก ์ด๋ํ ์๋ ์์ต๋๋ค.
+๋ํ [http://192.168.99.100/redoc](http://192.168.99.100/redoc) ๋๋ [http://127.0.0.1/redoc](http://127.0.0.1/redoc)(๋๋ Docker ํธ์คํธ๋ฅผ ์ฌ์ฉํด ๋๋ฑํ๊ฒ ์ ๊ทผ)๋ก ์ด๋ํ ์๋ ์์ต๋๋ค.
-๋์ ์๋ ๋ฌธ์(<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> ์ ๊ณต)๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
+๋์ ์๋ ๋ฌธ์([ReDoc](https://github.com/Rebilly/ReDoc) ์ ๊ณต)๋ฅผ ๋ณผ ์ ์์ต๋๋ค:

## ๋ฐฐํฌ ๊ฐ๋
{ #deployment-concepts }
-์ปจํ
์ด๋ ๊ด์ ์์ ๊ฐ์ [๋ฐฐํฌ ๊ฐ๋
](concepts.md){.internal-link target=_blank}๋ค์ ๋ค์ ์ด์ผ๊ธฐํด ๋ด
์๋ค.
+์ปจํ
์ด๋ ๊ด์ ์์ ๊ฐ์ [๋ฐฐํฌ ๊ฐ๋
](concepts.md)๋ค์ ๋ค์ ์ด์ผ๊ธฐํด ๋ด
์๋ค.
์ปจํ
์ด๋๋ ์ฃผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ **๋น๋ ๋ฐ ๋ฐฐํฌ** ๊ณผ์ ์ ๋จ์ํํ๋ ๋๊ตฌ์ด์ง๋ง, ์ด๋ฌํ **๋ฐฐํฌ ๊ฐ๋
**์ ์ฒ๋ฆฌํ๋ ํน์ ์ ๊ทผ ๋ฐฉ์์ ๊ฐ์ ํ์ง๋ ์์ผ๋ฉฐ, ๊ฐ๋ฅํ ์ ๋ต์ ์ฌ๋ฌ ๊ฐ์ง์
๋๋ค.
FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ **์ปจํ
์ด๋ ์ด๋ฏธ์ง**(๊ทธ๋ฆฌ๊ณ ๋์ค์ ์คํ ์ค์ธ **์ปจํ
์ด๋**)์๋ง ์ง์คํ๋ค๋ฉด, HTTPS๋ ๋ณดํต ๋ค๋ฅธ ๋๊ตฌ์ ์ํด **์ธ๋ถ์ ์ผ๋ก** ์ฒ๋ฆฌ๋ฉ๋๋ค.
-์๋ฅผ ๋ค์ด <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>์ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ปจํ
์ด๋๊ฐ **HTTPS**์ **์ธ์ฆ์**์ **์๋** ํ๋์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
+์๋ฅผ ๋ค์ด [Traefik](https://traefik.io/)์ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ปจํ
์ด๋๊ฐ **HTTPS**์ **์ธ์ฆ์**์ **์๋** ํ๋์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
/// tip | ํ
/// info | ์ ๋ณด
-Kubernetes๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์ด๋ ์๋ง๋ <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>์ผ ๊ฒ์
๋๋ค.
+Kubernetes๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์ด๋ ์๋ง๋ [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)์ผ ๊ฒ์
๋๋ค.
///
### ๋ฒ ์ด์ค ๋์ปค ์ด๋ฏธ์ง { #base-docker-image }
-๊ณผ๊ฑฐ์๋ ๊ณต์ FastAPI Docker ์ด๋ฏธ์ง๊ฐ ์์์ต๋๋ค: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. ํ์ง๋ง ์ด์ ๋ deprecated๋์์ต๋๋ค. โ๏ธ
+๊ณผ๊ฑฐ์๋ ๊ณต์ FastAPI Docker ์ด๋ฏธ์ง๊ฐ ์์์ต๋๋ค: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). ํ์ง๋ง ์ด์ ๋ deprecated๋์์ต๋๋ค. โ๏ธ
์๋ง๋ ์ด ๋ฒ ์ด์ค ๋์ปค ์ด๋ฏธ์ง(๋๋ ์ ์ฌํ ๋ค๋ฅธ ์ด๋ฏธ์ง)๋ **์ฌ์ฉํ์ง ์๋** ๊ฒ์ด ์ข์ต๋๋ค.
## `uv`๋ฅผ ์ฌ์ฉํ๋ ๋์ปค ์ด๋ฏธ์ง { #docker-image-with-uv }
-ํ๋ก์ ํธ๋ฅผ ์ค์นํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํด <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, <a href="https://docs.astral.sh/uv/guides/integration/docker/" class="external-link" target="_blank">uv Docker guide</a>๋ฅผ ๋ฐ๋ฅผ ์ ์์ต๋๋ค.
+ํ๋ก์ ํธ๋ฅผ ์ค์นํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํด [uv](https://github.com/astral-sh/uv)๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/)๋ฅผ ๋ฐ๋ฅผ ์ ์์ต๋๋ค.
## ์์ฝ { #recap }
# FastAPI Cloud { #fastapi-cloud }
-**ํ ๋ฒ์ ๋ช
๋ น**์ผ๋ก FastAPI ์ฑ์ <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง์ด๋ผ๋ฉด ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํด ๋ณด์ธ์. ๐
+**ํ ๋ฒ์ ๋ช
๋ น**์ผ๋ก FastAPI ์ฑ์ [FastAPI Cloud](https://fastapicloud.com)์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง์ด๋ผ๋ฉด ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํด ๋ณด์ธ์. ๐
## ๋ก๊ทธ์ธํ๊ธฐ { #login }
## FastAPI Cloud ์๊ฐ { #about-fastapi-cloud }
-**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**๋ **FastAPI**๋ฅผ ๋ง๋ ๋์ผํ ์ ์์ ํ์ด ๊ตฌ์ถํ์ต๋๋ค.
+**[FastAPI Cloud](https://fastapicloud.com)**๋ **FastAPI**๋ฅผ ๋ง๋ ๋์ผํ ์ ์์ ํ์ด ๊ตฌ์ถํ์ต๋๋ค.
์ต์ํ์ ๋
ธ๋ ฅ์ผ๋ก API๋ฅผ **๊ตฌ์ถ**, **๋ฐฐํฌ**, **์ ๊ทผ**ํ๋ ๊ณผ์ ์ ๊ฐ์ํํฉ๋๋ค.
///
-์๋น์ ๊ด์ ์์ **HTTPS์ ๊ธฐ๋ณธ์ ๋ฐฐ์ฐ๋ ค๋ฉด** <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>๋ฅผ ํ์ธํ์ธ์.
+์๋น์ ๊ด์ ์์ **HTTPS์ ๊ธฐ๋ณธ์ ๋ฐฐ์ฐ๋ ค๋ฉด** [https://howhttps.works/](https://howhttps.works/)๋ฅผ ํ์ธํ์ธ์.
์ด์ **๊ฐ๋ฐ์ ๊ด์ **์์ HTTPS๋ฅผ ์๊ฐํ ๋ ์ผ๋์ ๋์ด์ผ ํ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค:
* **๊ธฐ๋ณธ์ ์ผ๋ก** ์ด๋ IP ์ฃผ์ ํ๋๋น **HTTPS ์ธ์ฆ์ ํ๋๋ง** ๋ ์ ์๋ค๋ ๋ป์
๋๋ค.
* ์๋ฒ๊ฐ ์๋ฌด๋ฆฌ ํฌ๋ , ๊ทธ ์์ ์ฌ๋ฆฐ ๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ด ์๋ฌด๋ฆฌ ์๋ ์๊ด์์ต๋๋ค.
* ํ์ง๋ง ์ด์ ๋ํ **ํด๊ฒฐ์ฑ
**์ด ์์ต๋๋ค.
-* **TLS** ํ๋กํ ์ฝ(HTTP ์ด์ , TCP ๋ ๋ฒจ์์ ์ํธํ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ)์ ๋ํ **ํ์ฅ** ์ค์ **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication - ์๋ฒ ์ด๋ฆ ํ์">SNI</abbr></a>**๋ผ๋ ๊ฒ์ด ์์ต๋๋ค.
+* **TLS** ํ๋กํ ์ฝ(HTTP ์ด์ , TCP ๋ ๋ฒจ์์ ์ํธํ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ)์ ๋ํ **ํ์ฅ** ์ค์ **[<abbr title="Server Name Indication - ์๋ฒ ์ด๋ฆ ํ์">SNI</abbr>](https://en.wikipedia.org/wiki/Server_Name_Indication)**๋ผ๋ ๊ฒ์ด ์์ต๋๋ค.
* ์ด SNI ํ์ฅ์ ์ฌ์ฉํ๋ฉด, ๋จ์ผ ์๋ฒ(**๋จ์ผ IP ์ฃผ์**)์์ **์ฌ๋ฌ HTTPS ์ธ์ฆ์**๋ฅผ ์ฌ์ฉํ๊ณ **์ฌ๋ฌ HTTPS ๋๋ฉ์ธ/์ ํ๋ฆฌ์ผ์ด์
**์ ์ ๊ณตํ ์ ์์ต๋๋ค.
* ์ด๋ฅผ ์ํด์๋ ์๋ฒ์์ **๊ณต๊ฐ IP ์ฃผ์**๋ก ๋ฆฌ์ค๋ํ๋ **ํ๋์** ์ปดํฌ๋ํธ(ํ๋ก๊ทธ๋จ)๊ฐ ์๋ฒ์ ์๋ **๋ชจ๋ HTTPS ์ธ์ฆ์**์ ์ ๊ทผํ ์ ์์ด์ผ ํฉ๋๋ค.
* ๋ณด์ ์ฐ๊ฒฐ์ ์ป์ **์ดํ์๋**, ํต์ ํ๋กํ ์ฝ ์์ฒด๋ **์ฌ์ ํ HTTP**์
๋๋ค.
* **HTTP ํ๋กํ ์ฝ**๋ก ์ ์ก๋๋๋ผ๋, ๋ด์ฉ์ **์ํธํ**๋์ด ์์ต๋๋ค.
-์ผ๋ฐ์ ์ผ๋ก ์๋ฒ(๋จธ์ , ํธ์คํธ ๋ฑ)์๋ **ํ๋ก๊ทธ๋จ/HTTP ์๋ฒ ํ๋**๋ฅผ ์คํํด **HTTPS ๊ด๋ จ ๋ถ๋ถ ์ ์ฒด**๋ฅผ ๊ด๋ฆฌํ๊ฒ ํฉ๋๋ค: **์ํธํ๋ HTTPS ์์ฒญ**์ ๋ฐ๊ณ , ๋ณตํธํ๋ **HTTP ์์ฒญ**์ ๊ฐ์ ์๋ฒ์์ ์คํ ์ค์ธ ์ค์ HTTP ์ ํ๋ฆฌ์ผ์ด์
(์ด ๊ฒฝ์ฐ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
)์ผ๋ก ์ ๋ฌํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ **HTTP ์๋ต**์ ๋ฐ์ ์ ์ ํ **HTTPS ์ธ์ฆ์**๋ก **์ํธํ**ํ ๋ค **HTTPS**๋ก ํด๋ผ์ด์ธํธ์ ๋ค์ ๋ณด๋ด๋ ์ญํ ์
๋๋ค. ์ด๋ฐ ์๋ฒ๋ฅผ ํํ **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>**๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
+์ผ๋ฐ์ ์ผ๋ก ์๋ฒ(๋จธ์ , ํธ์คํธ ๋ฑ)์๋ **ํ๋ก๊ทธ๋จ/HTTP ์๋ฒ ํ๋**๋ฅผ ์คํํด **HTTPS ๊ด๋ จ ๋ถ๋ถ ์ ์ฒด**๋ฅผ ๊ด๋ฆฌํ๊ฒ ํฉ๋๋ค: **์ํธํ๋ HTTPS ์์ฒญ**์ ๋ฐ๊ณ , ๋ณตํธํ๋ **HTTP ์์ฒญ**์ ๊ฐ์ ์๋ฒ์์ ์คํ ์ค์ธ ์ค์ HTTP ์ ํ๋ฆฌ์ผ์ด์
(์ด ๊ฒฝ์ฐ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
)์ผ๋ก ์ ๋ฌํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ **HTTP ์๋ต**์ ๋ฐ์ ์ ์ ํ **HTTPS ์ธ์ฆ์**๋ก **์ํธํ**ํ ๋ค **HTTPS**๋ก ํด๋ผ์ด์ธํธ์ ๋ค์ ๋ณด๋ด๋ ์ญํ ์
๋๋ค. ์ด๋ฐ ์๋ฒ๋ฅผ ํํ **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
TLS Termination Proxy๋ก ์ฌ์ฉํ ์ ์๋ ์ต์
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
์ธ์ฆ์๋ฅผ ํ๋ํ๋ ๊ณผ์ ์ ๋ฒ๊ฑฐ๋กญ๊ณ , ๊ฝค ๋ง์ ์๋ฅ ์์
์ด ํ์ํ์ผ๋ฉฐ, ์ธ์ฆ์๋ ์๋นํ ๋น์์ต๋๋ค.
-ํ์ง๋ง ๊ทธ ํ **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>**๊ฐ ๋ง๋ค์ด์ก์ต๋๋ค.
+ํ์ง๋ง ๊ทธ ํ **[Let's Encrypt](https://letsencrypt.org/)**๊ฐ ๋ง๋ค์ด์ก์ต๋๋ค.
์ด๋ Linux Foundation์ ํ๋ก์ ํธ์
๋๋ค. ํ์ค ์ํธํ์ ๋ณด์์ ๋ชจ๋ ์ฌ์ฉํ๋ **HTTPS ์ธ์ฆ์**๋ฅผ **๋ฌด๋ฃ๋ก**, ์๋ํ๋ ๋ฐฉ์์ผ๋ก ์ ๊ณตํฉ๋๋ค. ์ด ์ธ์ฆ์๋ค์ ์๋ช
์ด ์งง๊ณ (์ฝ 3๊ฐ์) ๊ทธ๋์ ์ ํจ ๊ธฐ๊ฐ์ด ์งง์ ๋งํผ **์ค์ ๋ก ๋ณด์์ด ๋ ์ข์์ง๊ธฐ๋** ํฉ๋๋ค.
ํ๋ก์ ํค๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
-* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
+* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For)
+* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto)
+* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host)
///
/// tip | ํ
-์ด์ ๋ํด์๋ [ํ๋ก์ ๋ค์์ ์คํํ๊ธฐ - ํ๋ก์ ์ ๋ฌ ํค๋ ํ์ฑํ](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} ๋ฌธ์์์ ๋ ์์๋ณผ ์ ์์ต๋๋ค.
+์ด์ ๋ํด์๋ [ํ๋ก์ ๋ค์์ ์คํํ๊ธฐ - ํ๋ก์ ์ ๋ฌ ํค๋ ํ์ฑํ](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) ๋ฌธ์์์ ๋ ์์๋ณผ ์ ์์ต๋๋ค.
///
์ฌ๋ฌ ๋๊ตฌ๋ฅผ ์กฐํฉํด ์ง์ **์๋ฒ๋ฅผ ๋ฐฐํฌ**ํ ์๋ ์๊ณ , ์์
์ ์ผ๋ถ๋ฅผ ๋์ ํด ์ฃผ๋ **ํด๋ผ์ฐ๋ ์๋น์ค**๋ฅผ ์ฌ์ฉํ ์๋ ์์ผ๋ฉฐ, ๋ค๋ฅธ ๊ฐ๋ฅํ ์ ํ์ง๋ ์์ต๋๋ค.
-์๋ฅผ ๋ค์ด, FastAPI ๋ค์ ์๋ ์ ํฌ ํ์ FastAPI๋ก ์์
ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฐ๋ฐ์ ๊ฒฝํ์ ์ ์งํ๋ฉด์, FastAPI ์ฑ์ ํด๋ผ์ฐ๋์ ๊ฐ๋ฅํ ํ ๊ฐ์ํ๋ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌํ ์ ์๋๋ก <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a>๋ฅผ ๋ง๋ค์์ต๋๋ค.
+์๋ฅผ ๋ค์ด, FastAPI ๋ค์ ์๋ ์ ํฌ ํ์ FastAPI๋ก ์์
ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฐ๋ฐ์ ๊ฒฝํ์ ์ ์งํ๋ฉด์, FastAPI ์ฑ์ ํด๋ผ์ฐ๋์ ๊ฐ๋ฅํ ํ ๊ฐ์ํ๋ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌํ ์ ์๋๋ก [**FastAPI Cloud**](https://fastapicloud.com)๋ฅผ ๋ง๋ค์์ต๋๋ค.
**FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๋ ์๋ง ์ผ๋์ ๋์ด์ผ ํ ๋ช ๊ฐ์ง ์ฃผ์ ๊ฐ๋
์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค(๋๋ถ๋ถ์ ๋ค๋ฅธ ์ ํ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์๋ ์ ์ฉ๋ฉ๋๋ค).
๋ค์์ ํฌํจํด ์ฌ๋ฌ ๋์์ด ์์ต๋๋ค:
-* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>: ๊ณ ์ฑ๋ฅ ASGI ์๋ฒ.
-* <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a>: HTTP/2 ๋ฐ Trio ๋ฑ ์ฌ๋ฌ ๊ธฐ๋ฅ๊ณผ ํธํ๋๋ ASGI ์๋ฒ.
-* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a>: Django Channels๋ฅผ ์ํด ๋ง๋ค์ด์ง ASGI ์๋ฒ.
-* <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a>: Python ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ Rust HTTP ์๋ฒ.
-* <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a>: NGINX Unit์ ๊ฐ๋ณ๊ณ ๋ค์ฉ๋๋ก ์ฌ์ฉํ ์ ์๋ ์น ์ ํ๋ฆฌ์ผ์ด์
๋ฐํ์์
๋๋ค.
+* [Uvicorn](https://www.uvicorn.dev/): ๊ณ ์ฑ๋ฅ ASGI ์๋ฒ.
+* [Hypercorn](https://hypercorn.readthedocs.io/): HTTP/2 ๋ฐ Trio ๋ฑ ์ฌ๋ฌ ๊ธฐ๋ฅ๊ณผ ํธํ๋๋ ASGI ์๋ฒ.
+* [Daphne](https://github.com/django/daphne): Django Channels๋ฅผ ์ํด ๋ง๋ค์ด์ง ASGI ์๋ฒ.
+* [Granian](https://github.com/emmett-framework/granian): Python ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ Rust HTTP ์๋ฒ.
+* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit์ ๊ฐ๋ณ๊ณ ๋ค์ฉ๋๋ก ์ฌ์ฉํ ์ ์๋ ์น ์ ํ๋ฆฌ์ผ์ด์
๋ฐํ์์
๋๋ค.
## ์๋ฒ ๋จธ์ ๊ณผ ์๋ฒ ํ๋ก๊ทธ๋จ { #server-machine-and-server-program }
ํ์ง๋ง ASGI ์๋ฒ๋ฅผ ์๋์ผ๋ก ์ค์นํ ์๋ ์์ต๋๋ค.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์นํ์ธ์.
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์นํ์ธ์.
์๋ฅผ ๋ค์ด Uvicorn์ ์ค์นํ๋ ค๋ฉด:
`standard`๋ฅผ ์ถ๊ฐํ๋ฉด Uvicorn์ด ๊ถ์ฅ๋๋ ์ถ๊ฐ ์์กด์ฑ ๋ช ๊ฐ์ง๋ฅผ ์ค์นํ๊ณ ์ฌ์ฉํฉ๋๋ค.
-์ฌ๊ธฐ์๋ `asyncio`๋ฅผ ๊ณ ์ฑ๋ฅ์ผ๋ก ๋์ฒดํ ์ ์๋ ๋๋กญ์ธ ๋์ฒด์ฌ์ธ `uvloop`๊ฐ ํฌํจ๋๋ฉฐ, ํฐ ๋์์ฑ ์ฑ๋ฅ ํฅ์์ ์ ๊ณตํฉ๋๋ค.
+์ฌ๊ธฐ์๋ `uvloop`๊ฐ ํฌํจ๋๋ฉฐ, ์ด๋ `asyncio`๋ฅผ ๊ณ ์ฑ๋ฅ์ผ๋ก ๋์ฒดํ ์ ์๋ ๋๋กญ์ธ ๋์ฒด์ฌ๋ก, ํฐ ๋์์ฑ ์ฑ๋ฅ ํฅ์์ ์ ๊ณตํฉ๋๋ค.
`pip install "fastapi[standard]"` ๊ฐ์ ๋ฐฉ์์ผ๋ก FastAPI๋ฅผ ์ค์นํ๋ฉด `uvicorn[standard]`๋ ํจ๊ป ์ค์น๋ฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ๋๋ **๋ค์ค ์ฝ์ด**๋ฅผ ํ์ฉํ๊ณ ๋ ๋ง์ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋๋ก **ํ๋ก์ธ์ค ๋ณต์ **๋ฅผ ํ๊ณ ์ถ์ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
-์ด์ ์ฅ์ [๋ฐฐํฌ ๊ฐ๋
๋ค](concepts.md){.internal-link target=_blank}์์ ๋ณธ ๊ฒ์ฒ๋ผ, ์ฌ์ฉํ ์ ์๋ ์ ๋ต์ด ์ฌ๋ฌ ๊ฐ์ง ์์ต๋๋ค.
+์ด์ ์ฅ์ [๋ฐฐํฌ ๊ฐ๋
๋ค](concepts.md)์์ ๋ณธ ๊ฒ์ฒ๋ผ, ์ฌ์ฉํ ์ ์๋ ์ ๋ต์ด ์ฌ๋ฌ ๊ฐ์ง ์์ต๋๋ค.
์ฌ๊ธฐ์๋ `fastapi` ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ `uvicorn` ๋ช
๋ น์ด๋ฅผ ์ง์ ์ฌ์ฉํด์, **์์ปค ํ๋ก์ธ์ค**์ ํจ๊ป **Uvicorn**์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
/// info | ์ ๋ณด
-Docker๋ Kubernetes ๊ฐ์ ์ปจํ
์ด๋๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, ๋ค์ ์ฅ์ธ [์ปจํ
์ด๋์์์ FastAPI - ๋์ปค](docker.md){.internal-link target=_blank}์์ ๋ ์์ธํ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
+Docker๋ Kubernetes ๊ฐ์ ์ปจํ
์ด๋๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, ๋ค์ ์ฅ์ธ [์ปจํ
์ด๋์์์ FastAPI - ๋์ปค](docker.md)์์ ๋ ์์ธํ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
ํนํ **Kubernetes**์์ ์คํํ ๋๋ ์์ปค๋ฅผ ์ฌ์ฉํ๊ธฐ๋ณด๋ค๋, ๋์ **์ปจํ
์ด๋๋น ๋จ์ผ Uvicorn ํ๋ก์ธ์ค ํ๋**๋ฅผ ์คํํ๊ณ ์ถ์ ๊ฐ๋ฅ์ฑ์ด ํฌ์ง๋ง, ํด๋น ๋ด์ฉ์ ๊ทธ ์ฅ์ ๋ค์์ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
## ์ปจํ
์ด๋์ ๋์ปค { #containers-and-docker }
-๋ค์ ์ฅ์ธ [์ปจํ
์ด๋์์์ FastAPI - ๋์ปค](docker.md){.internal-link target=_blank}์์๋ ๋ค๋ฅธ **๋ฐฐํฌ ๊ฐ๋
๋ค**์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ ๋ต์ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
+๋ค์ ์ฅ์ธ [์ปจํ
์ด๋์์์ FastAPI - ๋์ปค](docker.md)์์๋ ๋ค๋ฅธ **๋ฐฐํฌ ๊ฐ๋
๋ค**์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ ๋ต์ ์ค๋ช
ํ๊ฒ ์ต๋๋ค.
๋จ์ผ Uvicorn ํ๋ก์ธ์ค๋ฅผ ์คํํ๊ธฐ ์ํด, **์ฒ์๋ถํฐ ์ฌ๋ฌ๋ถ๋ง์ ์ด๋ฏธ์ง๋ฅผ ์ง์ ๋น๋**ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. ์ด๋ ๊ฐ๋จํ ๊ณผ์ ์ด๋ฉฐ, **Kubernetes** ๊ฐ์ ๋ถ์ฐ ์ปจํ
์ด๋ ๊ด๋ฆฌ ์์คํ
์ ์ฌ์ฉํ ๋ ์๋ง๋ ์ด๋ ๊ฒ ํ๊ณ ์ถ์ ๊ฒ์
๋๋ค.
์๋ก์ด ๊ธฐ๋ฅ์ด ์์ฃผ ์ถ๊ฐ๋๊ณ , ๋ฒ๊ทธ๊ฐ ๊ท์น์ ์ผ๋ก ์์ ๋๋ฉฐ, ์ฝ๋๋ ๊ณ์ํด์ ์ง์์ ์ผ๋ก ๊ฐ์ ๋๊ณ ์์ต๋๋ค.
-๊ทธ๋์ ํ์ฌ ๋ฒ์ ์ด ์์ง `0.x.x`์ธ ๊ฒ์
๋๋ค. ์ด๋ ๊ฐ ๋ฒ์ ์ด ์ ์ฌ์ ์ผ๋ก ํ์ ํธํ์ฑ์ด ๊นจ์ง๋ ๋ณ๊ฒฝ์ ํฌํจํ ์ ์์์ ๋ฐ์ํฉ๋๋ค. ์ด๋ <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> ๊ด๋ก๋ฅผ ๋ฐ๋ฆ
๋๋ค.
+๊ทธ๋์ ํ์ฌ ๋ฒ์ ์ด ์์ง `0.x.x`์ธ ๊ฒ์
๋๋ค. ์ด๋ ๊ฐ ๋ฒ์ ์ด ์ ์ฌ์ ์ผ๋ก ํ์ ํธํ์ฑ์ด ๊นจ์ง๋ ๋ณ๊ฒฝ์ ํฌํจํ ์ ์์์ ๋ฐ์ํฉ๋๋ค. ์ด๋ [Semantic Versioning](https://semver.org/) ๊ด๋ก๋ฅผ ๋ฐ๋ฆ
๋๋ค.
์ง๊ธ ๋ฐ๋ก **FastAPI**๋ก ํ๋ก๋์
์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค ์ ์์ต๋๋ค(๊ทธ๋ฆฌ๊ณ ์๋ง๋ ํ๋์ ๊ทธ๋ ๊ฒ ํด์ค์
จ์ ๊ฒ์
๋๋ค). ๋ค๋ง ๋๋จธ์ง ์ฝ๋์ ํจ๊ป ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋ ๋ฒ์ ์ ์ฌ์ฉํ๊ณ ์๋์ง ํ์ธํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
## ์ด์ฉ ๊ฐ๋ฅํ ๋ฒ์ ๋ค { #available-versions }
-์ฌ์ฉ ๊ฐ๋ฅํ ๋ฒ์ (์: ํ์ฌ ์ต์ ๋ฒ์ ์ด ๋ฌด์์ธ์ง ํ์ธํ๊ธฐ ์ํด)์ [๋ฆด๋ฆฌ์ค ๋
ธํธ](../release-notes.md){.internal-link target=_blank}์์ ํ์ธํ ์ ์์ต๋๋ค.
+์ฌ์ฉ ๊ฐ๋ฅํ ๋ฒ์ (์: ํ์ฌ ์ต์ ๋ฒ์ ์ด ๋ฌด์์ธ์ง ํ์ธํ๊ธฐ ์ํด)์ [๋ฆด๋ฆฌ์ค ๋
ธํธ](../release-notes.md)์์ ํ์ธํ ์ ์์ต๋๋ค.
## ๋ฒ์ ๋ค์ ๋ํด { #about-versions }
์ฑ์ ํ
์คํธ๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
-**FastAPI**์์๋ ๋งค์ฐ ์ฝ์ต๋๋ค(Starlette ๋๋ถ์). ๋ฌธ์๋ฅผ ํ์ธํด ๋ณด์ธ์: [ํ
์คํธ](../tutorial/testing.md){.internal-link target=_blank}
+**FastAPI**์์๋ ๋งค์ฐ ์ฝ์ต๋๋ค(Starlette ๋๋ถ์). ๋ฌธ์๋ฅผ ํ์ธํด ๋ณด์ธ์: [ํ
์คํธ](../tutorial/testing.md)
ํ
์คํธ๋ฅผ ๊ฐ์ถ ๋ค์๋ **FastAPI** ๋ฒ์ ์ ๋ ์ต์ ๋ฒ์ ์ผ๋ก ์
๊ทธ๋ ์ด๋ํ๊ณ , ํ
์คํธ๋ฅผ ์คํํ์ฌ ๋ชจ๋ ์ฝ๋๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋์ง ํ์ธํ์ธ์.
/// tip | ํ
-<a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> ์ ๋ ๋ฒ์งธ ์ธ์๋ ๋ฐํํ ๊ธฐ๋ณธ๊ฐ์
๋๋ค.
+[`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) ์ ๋ ๋ฒ์งธ ์ธ์๋ ๋ฐํํ ๊ธฐ๋ณธ๊ฐ์
๋๋ค.
์ ๊ณตํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ์ `None`์ด๋ฉฐ, ์ฌ๊ธฐ์๋ ์ฌ์ฉํ ๊ธฐ๋ณธ๊ฐ์ผ๋ก `"World"`๋ฅผ ์ ๊ณตํฉ๋๋ค.
/// tip | ํ
-<a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a> ์์ ์ข ๋ ์์ธํ ์์๋ณผ ์ ์์ต๋๋ค.
+[The Twelve-Factor App: Config](https://12factor.net/config) ์์ ์ข ๋ ์์ธํ ์์๋ณผ ์ ์์ต๋๋ค.
///
์ฆ, ํ์ด์ฌ์์ ํ๊ฒฝ ๋ณ์๋ก๋ถํฐ ์ฝ์ **๋ชจ๋ ๊ฐ**์ **`str`**์ด ๋๊ณ , ๋ค๋ฅธ ํ์
์ผ๋ก์ ๋ณํ์ด๋ ๊ฒ์ฆ์ ์ฝ๋์์ ์ํํด์ผ ํฉ๋๋ค.
-**์ ํ๋ฆฌ์ผ์ด์
์ค์ **์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํ๊ฒฝ ๋ณ์ ์ฌ์ฉ์ ๋ํ ์์ธํ ๋ด์ฉ์ [๊ณ ๊ธ ์ฌ์ฉ์ ๊ฐ์ด๋ - ์ค์ ๋ฐ ํ๊ฒฝ ๋ณ์](./advanced/settings.md){.internal-link target=_blank} ์์ ํ์ธํ ์ ์์ต๋๋ค.
+**์ ํ๋ฆฌ์ผ์ด์
์ค์ **์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํ๊ฒฝ ๋ณ์ ์ฌ์ฉ์ ๋ํ ์์ธํ ๋ด์ฉ์ [๊ณ ๊ธ ์ฌ์ฉ์ ๊ฐ์ด๋ - ์ค์ ๋ฐ ํ๊ฒฝ ๋ณ์](./advanced/settings.md) ์์ ํ์ธํ ์ ์์ต๋๋ค.
## `PATH` ํ๊ฒฝ ๋ณ์ { #path-environment-variable }
////
-์ด ์ ๋ณด๋ [๊ฐ์ ํ๊ฒฝ](virtual-environments.md){.internal-link target=_blank} ์ ๋ํด ์์๋ณผ ๋ ์ ์ฉํ ๊ฒ์
๋๋ค.
+์ด ์ ๋ณด๋ [๊ฐ์ ํ๊ฒฝ](virtual-environments.md) ์ ๋ํด ์์๋ณผ ๋ ์ ์ฉํ ๊ฒ์
๋๋ค.
## ๊ฒฐ๋ก { #conclusion }
์ด ๋ฌธ์๋ฅผ ํตํด **ํ๊ฒฝ ๋ณ์**๊ฐ ๋ฌด์์ด๊ณ ํ์ด์ฌ์์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ๊ธฐ๋ณธ์ ์ผ๋ก ์ดํดํ์
จ์ ๊ฒ๋๋ค.
-๋ํ <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">ํ๊ฒฝ ๋ณ์์ ๋ํ ์ํคํผ๋์</a>์์ ์ด์ ๋ํด ์์ธํ ์์๋ณผ ์ ์์ต๋๋ค.
+๋ํ [ํ๊ฒฝ ๋ณ์์ ๋ํ ์ํคํผ๋์](https://en.wikipedia.org/wiki/Environment_variable)์์ ์ด์ ๋ํด ์์ธํ ์์๋ณผ ์ ์์ต๋๋ค.
๋ง์ ๊ฒฝ์ฐ์์, ํ๊ฒฝ ๋ณ์๊ฐ ์ด๋ป๊ฒ ์ ์ฉํ๊ณ ์ ์ฉ ๊ฐ๋ฅํ์ง ๋ฐ๋ก ๋ช
ํํ๊ฒ ์ ์๋ ์์ต๋๋ค. ํ์ง๋ง ๊ฐ๋ฐํ ๋ ๋ค์ํ ์๋๋ฆฌ์ค์์ ๊ณ์ ๋ํ๋๋ฏ๋ก ์ด์ ๋ํด ์๋ ๊ฒ์ด ์ข์ต๋๋ค.
# FastAPI CLI { #fastapi-cli }
-**FastAPI CLI**๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์๋นํ๊ณ , FastAPI ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฑ ๋ค์ํ ์์
์ ์ฌ์ฉํ ์ ์๋ ์ปค๋งจ๋ ๋ผ์ธ ํ๋ก๊ทธ๋จ์
๋๋ค.
+**FastAPI <abbr title="command line interface - ๋ช
๋ น์ค ์ธํฐํ์ด์ค">CLI</abbr>**๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์๋นํ๊ณ , FastAPI ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฑ ๋ค์ํ ์์
์ ์ฌ์ฉํ ์ ์๋ ์ปค๋งจ๋ ๋ผ์ธ ํ๋ก๊ทธ๋จ์
๋๋ค.
-FastAPIรซยฅยผ รฌ\84ยครฌยน\98รญ\95ย รซ\95\8c(รฌ\98\88: `pip install "fastapi[standard]"`), `fastapi-cli`รซ\9dยผรซ\8a\94 รญ\8cยจรญ\82ยครฌยง\80รชยฐ\80 รญ\8fยฌรญ\95ยจรซ\90\98รซยฉยฐ, รฌ\9dยด รญ\8cยจรญ\82ยครฌยง\80รซ\8a\94 รญ\84ยฐรซยฏยธรซ\84\90รฌ\97\90รฌ\84\9c `fastapi` รซยช\85รซย ยนรฌ\96ยดรซยฅยผ รฌย \9cรชยณยตรญ\95ยฉรซ\8b\88รซ\8bยค.
+FastAPIรซยฅยผ รฌ\84ยครฌยน\98รญ\95\98รซยฉยด(รฌ\98\88: `pip install "fastapi[standard]"`) รญ\84ยฐรซยฏยธรซ\84\90รฌ\97\90รฌ\84\9c รฌ\8bยครญ\96\89รญ\95ย รฌ\88\98 รฌ\9e\88รซ\8a\94 รฌยปยครซยงยจรซ\93\9c รซ\9dยผรฌ\9dยธ รญ\94\84รซยก\9cรชยทยธรซ\9eยจรฌ\9dยด รญ\95ยจรชยป\98 รฌย \9cรชยณยตรซ\90ยฉรซ\8b\88รซ\8bยค.
๊ฐ๋ฐ์ฉ์ผ๋ก FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ๋ ค๋ฉด `fastapi dev` ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
<div class="termy">
```console
-$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
+$ <font color="#4E9A06">fastapi</font> dev
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server ๐
</div>
-`fastapi`๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ปค๋งจ๋ ๋ผ์ธ ํ๋ก๊ทธ๋จ์ **FastAPI CLI**์
๋๋ค.
+/// tip | ํ
+
+ํ๋ก๋์
์์๋ `fastapi dev` ๋์ `fastapi run`์ ์ฌ์ฉํฉ๋๋ค. ๐
+
+///
+
+๋ด๋ถ์ ์ผ๋ก **FastAPI CLI**๋ ๊ณ ์ฑ๋ฅ์, ํ๋ก๋์
์ ์ ํฉํ ASGI ์๋ฒ์ธ [Uvicorn](https://www.uvicorn.dev)์ ์ฌ์ฉํฉ๋๋ค. ๐
+
+`fastapi` CLI๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์คํํ FastAPI ์ฑ์ ์๋์ผ๋ก ๊ฐ์งํ๋ ค๊ณ ์๋ํฉ๋๋ค. `main.py` ํ์ผ ์์ `app`์ด๋ผ๋ ๊ฐ์ฒด(๋๋ ๋ช ๊ฐ์ง ๋ณํ)๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
+
+ํ์ง๋ง ์ฌ์ฉํ ์ฑ์ ๋ช
์์ ์ผ๋ก ๊ตฌ์ฑํ ์๋ ์์ต๋๋ค.
+
+## `pyproject.toml`์์ ์ฑ `entrypoint` ๊ตฌ์ฑํ๊ธฐ { #configure-the-app-entrypoint-in-pyproject-toml }
+
+`pyproject.toml` ํ์ผ์์ ์ฑ์ด ์ด๋์ ์๋์ง ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํ ์ ์์ต๋๋ค:
+
+```toml
+[tool.fastapi]
+entrypoint = "main:app"
+```
+
+์ด `entrypoint`๋ `fastapi` ๋ช
๋ น์ด์ ๋ค์๊ณผ ๊ฐ์ด ์ฑ์ ์ํฌํธํ๋ผ๊ณ ์๋ ค์ค๋๋ค:
+
+```python
+from main import app
+```
-FastAPI CLI๋ Python ํ๋ก๊ทธ๋จ์ ๊ฒฝ๋ก(์: `main.py`)๋ฅผ ๋ฐ์ `FastAPI` ์ธ์คํด์ค(์ผ๋ฐ์ ์ผ๋ก `app`์ผ๋ก ์ด๋ฆ์ ๋ถ์)๋ฅผ ์๋์ผ๋ก ๊ฐ์งํ๊ณ , ์ฌ๋ฐ๋ฅธ ์ํฌํธ ๊ณผ์ ์ ๊ฒฐ์ ํ ๋ค์ ์๋นํฉ๋๋ค.
+์ฝ๋ ๊ตฌ์กฐ๊ฐ ๋ค์๊ณผ ๊ฐ๋ค๋ฉด:
+
+```
+.
+โโโ backend
+โย ย โโโ main.py
+โย ย โโโ __init__.py
+```
+
+`entrypoint`๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํฉ๋๋ค:
+
+```toml
+[tool.fastapi]
+entrypoint = "backend.main:app"
+```
+
+์ด๋ ๋ค์๊ณผ ๋์ผํฉ๋๋ค:
+
+```python
+from backend.main import app
+```
+
+### ๊ฒฝ๋ก์ ํจ๊ป `fastapi dev` { #fastapi-dev-with-path }
+
+`fastapi dev` ๋ช
๋ น์ด์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ ์๋ ์์ผ๋ฉฐ, ๊ทธ๋ฌ๋ฉด ์ฌ์ฉํ FastAPI ์ฑ ๊ฐ์ฒด๋ฅผ ์ถ์ ํฉ๋๋ค:
+
+```console
+$ fastapi dev main.py
+```
-รญ\94\84รซยก\9cรซ\8d\95รฌ\85\98รฌ\97\90รฌ\84\9cรซ\8a\94 รซ\8c\80รฌ\8bย `fastapi run`รฌ\9d\84 รฌ\82ยฌรฌ\9aยฉรญ\95ยฉรซ\8b\88รซ\8bยค. รฐ\9f\9a\80
+รญ\95\98รฌยง\80รซยง\8c รซยงยครซยฒ\88 `fastapi` รซยช\85รซย ยนรฌ\96ยดรซยฅยผ รญ\98ยธรฌยถ\9cรญ\95ย รซ\95\8c รฌ\98ยฌรซยฐ\94รซยฅยธ รชยฒยฝรซยก\9cรซยฅยผ รฌย \84รซ\8bยฌรญ\95\98รซ\8a\94 รชยฒ\83รฌ\9d\84 รชยธยฐรฌ\96ยตรญ\95ยดรฌ\95ยผ รญ\95ยฉรซ\8b\88รซ\8bยค.
-รซ\82ยดรซยถ\80รฌย \81รฌ\9cยผรซยก\9c **FastAPI CLI**รซ\8a\94 รชยณย รฌ\84ยฑรซ\8aยฅรฌ\9d\98, รญ\94\84รซยก\9cรซ\8d\95รฌ\85\98รฌ\97\90 รฌย \81รญ\95ยฉรญ\95\9c ASGI รฌ\84\9cรซยฒ\84รฌ\9dยธ <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>รฌ\9d\84 รฌ\82ยฌรฌ\9aยฉรญ\95ยฉรซ\8b\88รซ\8bยค. รฐ\9f\98\8e
+รซ\98\90รญ\95\9c [VS Code รญ\99\95รฌ\9eยฅ](editor-support.md)รฌ\9dยดรซ\82\98 [FastAPI Cloud](https://fastapicloud.com) รชยฐ\99รฌ\9d\80 รซ\8bยครซยฅยธ รซ\8f\84รชยตยฌรฌ\97\90รฌ\84\9cรซ\8a\94 รฌ\9dยดรซยฅยผ รฌยฐยพรฌยง\80 รซยชยปรญ\95ย รฌ\88\98รซ\8f\84 รฌ\9e\88รฌ\9cยผรซยฏ\80รซยก\9c, `pyproject.toml`รฌ\9d\98 `entrypoint`รซยฅยผ รฌ\82ยฌรฌ\9aยฉรญ\95\98รซ\8a\94 รชยฒ\83รฌ\9d\84 รชยถ\8cรฌ\9eยฅรญ\95ยฉรซ\8b\88รซ\8bยค.
## `fastapi dev` { #fastapi-dev }
## `fastapi run` { #fastapi-run }
-`fastapi run`์ ์คํํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก๋์
๋ชจ๋๋ก FastAPI๊ฐ ์์๋ฉ๋๋ค.
+`fastapi run`์ ์คํํ๋ฉด ํ๋ก๋์
๋ชจ๋๋ก FastAPI๊ฐ ์์๋ฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก **auto-reload**๋ ๋นํ์ฑํ๋์ด ์์ต๋๋ค. ๋ํ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ IP ์ฃผ์๋ฅผ ์๋ฏธํ๋ `0.0.0.0`์์ ์ฐ๊ฒฐ์ ๋๊ธฐํ๋ฏ๋ก, ํด๋น ์ปดํจํฐ์ ํต์ ํ ์ ์๋ ๋๊ตฌ์๊ฒ๋ ๊ณต๊ฐ์ ์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํด์ง๋๋ค. ๋ณดํต ํ๋ก๋์
์์๋ ์ด๋ ๊ฒ ์คํํ๋ฉฐ, ์๋ฅผ ๋ค์ด ์ปจํ
์ด๋์์ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์คํํฉ๋๋ค.
/// tip | ํ
-์์ธํ ๋ด์ฉ์ [๋ฐฐํฌ ๋ฌธ์](deployment/index.md){.internal-link target=_blank}์์ ํ์ธํ ์ ์์ต๋๋ค.
+์์ธํ ๋ด์ฉ์ [๋ฐฐํฌ ๋ฌธ์](deployment/index.md)์์ ํ์ธํ ์ ์์ต๋๋ค.
///
### ๊ฐ๋ฐฉํ ํ์ค์ ๊ธฐ๋ฐ์ผ๋ก { #based-on-open-standards }
-* <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๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์
๋๋ค).
+* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification): <dfn title="๋ํ ๋ค์์ผ๋ก๋ ๋ถ๋ฆผ: ์๋ํฌ์ธํธ, ๋ผ์ฐํธ">๊ฒฝ๋ก</dfn> <dfn title="HTTP ๋ฉ์๋(POST, GET, PUT, DELETE ๋ฑ)๋ก๋ ์๋ ค์ง">์ฒ๋ฆฌ</dfn>, ๋งค๊ฐ๋ณ์, ์์ฒญ ๋ณธ๋ฌธ, ๋ณด์ ๋ฑ์ ์ ์ธ์ ํฌํจํ์ฌ API๋ฅผ ์์ฑํฉ๋๋ค.
+* [**JSON Schema**](https://json-schema.org/)๋ฅผ ์ฌ์ฉํ ์๋ ๋ฐ์ดํฐ ๋ชจ๋ธ ๋ฌธ์ํ(OpenAPI ์์ฒด๊ฐ JSON Schema๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์
๋๋ค).
* ๋จ์ํ ๋ ์ฌ๋ ค์ ๋ง๋ถ์ธ ๋ ์ด์ด๊ฐ ์๋๋ผ, ์ธ์ฌํ ๊ฒํ ๋ฅผ ๊ฑฐ์น ๋ค ์ด๋ฌํ ํ์ค์ ์ค์ฌ์ผ๋ก ์ค๊ณ๋์์ต๋๋ค.
* ์ด๋ ๋ํ ๋ค์ํ ์ธ์ด๋ก ์๋ **ํด๋ผ์ด์ธํธ ์ฝ๋ ์์ฑ**์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
๋ํํ API ๋ฌธ์์ ํ์์ฉ ์น ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ๋ ์์ํฌ๊ฐ OpenAPI๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ์ ์ฌ๋ฌ ์ต์
์ด ์์ผ๋ฉฐ, ๊ธฐ๋ณธ์ผ๋ก 2๊ฐ์ง๊ฐ ํฌํจ๋ฉ๋๋ค.
-* ๋ํํ ํ์์ด ๊ฐ๋ฅํ <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>๋ก ๋ธ๋ผ์ฐ์ ์์ ์ง์ API๋ฅผ ํธ์ถํ๊ณ ํ
์คํธํ ์ ์์ต๋๋ค.
+* [**Swagger UI**](https://github.com/swagger-api/swagger-ui)๋ก ๋ํํ ํ์์ด ๊ฐ๋ฅํ๋ฉฐ ๋ธ๋ผ์ฐ์ ์์ ์ง์ API๋ฅผ ํธ์ถํ๊ณ ํ
์คํธํ ์ ์์ต๋๋ค.

-* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>์ ์ด์ฉํ ๋์ฒด API ๋ฌธ์ํ.
+* [**ReDoc**](https://github.com/Rebilly/ReDoc)์ ์ด์ฉํ ๋์ฒด API ๋ฌธ์ํ.

### ๊ทธ์ ํ๋ ํ์ด์ฌ { #just-modern-python }
-( Pydantic ๋๋ถ์) ๋ชจ๋ ๊ฒ์ด ํ์ค **Python ํ์
** ์ ์ธ์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์๋ก ๋ฐฐ์ธ ๋ฌธ๋ฒ์ด ์์ต๋๋ค. ๊ทธ์ ํ์ค์ ์ธ ํ๋ ํ์ด์ฌ์
๋๋ค.
+(Pydantic ๋๋ถ์) ๋ชจ๋ ๊ฒ์ด ํ์ค **Python ํ์
** ์ ์ธ์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์๋ก ๋ฐฐ์ธ ๋ฌธ๋ฒ์ด ์์ต๋๋ค. ๊ทธ์ ํ์ค์ ์ธ ํ๋ ํ์ด์ฌ์
๋๋ค.
-Python ํ์
์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง 2๋ถ ์ ๋ ๋ณต์ต์ด ํ์ํ๋ค๋ฉด(FastAPI๋ฅผ ์ฌ์ฉํ์ง ์๋๋ผ๋), ๋ค์์ ์งง์ ์์ต์๋ฅผ ํ์ธํ์ธ์: [Python ํ์
](python-types.md){.internal-link target=_blank}.
+Python ํ์
์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง 2๋ถ ์ ๋ ๋ณต์ต์ด ํ์ํ๋ค๋ฉด(FastAPI๋ฅผ ์ฌ์ฉํ์ง ์๋๋ผ๋), ๋ค์์ ์งง์ ์์ต์๋ฅผ ํ์ธํ์ธ์: [Python ํ์
](python-types.md).
์ฌ๋ฌ๋ถ์ ํ์
์ด ์๋ ํ์ค Python์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค:
ํ๋ ์์ํฌ ์ ์ฒด๋ ์ฌ์ฉํ๊ธฐ ์ฝ๊ณ ์ง๊ด์ ์ผ๋ก ์ค๊ณ๋์์ผ๋ฉฐ, ์ต๊ณ ์ ๊ฐ๋ฐ ๊ฒฝํ์ ๋ณด์ฅํ๊ธฐ ์ํด ๊ฐ๋ฐ์ ์์ํ๊ธฐ๋ ์ ์ ๋ชจ๋ ๊ฒฐ์ ์ ์ฌ๋ฌ ํธ์ง๊ธฐ์์ ํ
์คํธ๋์์ต๋๋ค.
-Python ๊ฐ๋ฐ์ ์ค๋ฌธ์กฐ์ฌ์์ <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ ์ค ํ๋๊ฐ "์๋ ์์ฑ"์ด๋ผ๋ ์ </a>์ด ๋ถ๋ช
ํฉ๋๋ค.
+Python ๊ฐ๋ฐ์ ์ค๋ฌธ์กฐ์ฌ์์ [๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ธฐ๋ฅ ์ค ํ๋๊ฐ "์๋ ์์ฑ"์ด๋ผ๋ ์ ](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)์ด ๋ถ๋ช
ํฉ๋๋ค.
**FastAPI** ํ๋ ์์ํฌ ์ ์ฒด๋ ์ด๋ฅผ ๋ง์กฑํ๊ธฐ ์ํด ๋ง๋ค์ด์ก์ต๋๋ค. ์๋ ์์ฑ์ ์ด๋์๋ ์๋ํฉ๋๋ค.
ํธ์ง๊ธฐ๊ฐ ์ฌ๋ฌ๋ถ์ ์ด๋ป๊ฒ ๋์์ค ์ ์๋์ง ์ดํด๋ณด์ธ์:
-* <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>์์:
+* [Visual Studio Code](https://code.visualstudio.com/)์์:

-* <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>์์:
+* [PyCharm](https://www.jetbrains.com/pycharm/)์์:

๋ค์์ ํฌํจํด OpenAPI์ ์ ์๋ ๋ชจ๋ ๋ณด์ ์คํค๋ง:
* HTTP Basic.
-* **OAuth2**(**JWT tokens** ๋ํ ํฌํจ). [JWT๋ฅผ ์ฌ์ฉํ OAuth2](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ์์ต์๋ฅผ ํ์ธํด ๋ณด์ธ์.
+* **OAuth2**(**JWT tokens** ๋ํ ํฌํจ). [JWT๋ฅผ ์ฌ์ฉํ OAuth2](tutorial/security/oauth2-jwt.md) ์์ต์๋ฅผ ํ์ธํด ๋ณด์ธ์.
* ๋ค์์ ๋ค์ด ์๋ API ํค:
* ํค๋.
* ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์.
## Starlette ๊ธฐ๋ฅ { #starlette-features }
-**FastAPI**๋ <a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette</strong></a>์ ์์ ํ ํธํ๋๋ฉฐ(๋ํ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค). ๋ฐ๋ผ์ ์ถ๊ฐ๋ก ๊ฐ์ง๊ณ ์๋ Starlette ์ฝ๋๋ ๋ชจ๋ ๋์ํฉ๋๋ค.
+**FastAPI**๋ [**Starlette**](https://www.starlette.dev/)์ ์์ ํ ํธํ๋๋ฉฐ(๋ํ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค). ๋ฐ๋ผ์ ์ถ๊ฐ๋ก ๊ฐ์ง๊ณ ์๋ Starlette ์ฝ๋๋ ๋ชจ๋ ๋์ํฉ๋๋ค.
`FastAPI`๋ ์ค์ ๋ก `Starlette`์ ํ์ ํด๋์ค์
๋๋ค. ๊ทธ๋์ Starlette์ ์ด๋ฏธ ์๊ณ ์๊ฑฐ๋ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, ๋๋ถ๋ถ์ ๊ธฐ๋ฅ์ด ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋์ํ ๊ฒ์
๋๋ค.
**FastAPI**๋ฅผ ์ฌ์ฉํ๋ฉด **Starlette**์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ป๊ฒ ๋ฉ๋๋ค(FastAPI๋ Starlette์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋ํ ๊ฒ์
๋๋ค):
-* ์ ๋ง ์ธ์์ ์ธ ์ฑ๋ฅ. <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">**NodeJS**์ **Go**์ ๋ฒ๊ธ๊ฐ๋, ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋์
๋๋ค</a>.
+* ์ ๋ง ์ธ์์ ์ธ ์ฑ๋ฅ. [**NodeJS**์ **Go**์ ๋ฒ๊ธ๊ฐ๋, ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋์
๋๋ค](https://github.com/encode/starlette#performance).
* **WebSocket** ์ง์.
* ํ๋ก์ธ์ค ๋ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
.
* ์์ ๋ฐ ์ข
๋ฃ ์ด๋ฒคํธ.
## Pydantic ๊ธฐ๋ฅ { #pydantic-features }
-**FastAPI**๋ <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>๊ณผ ์๋ฒฝํ๊ฒ ํธํ๋๋ฉฐ(๋ํ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค). ๋ฐ๋ผ์ ์ถ๊ฐ๋ก ๊ฐ์ง๊ณ ์๋ Pydantic ์ฝ๋๋ ๋ชจ๋ ๋์ํฉ๋๋ค.
+**FastAPI**๋ [**Pydantic**](https://docs.pydantic.dev/)๊ณผ ์๋ฒฝํ๊ฒ ํธํ๋๋ฉฐ(๋ํ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค). ๋ฐ๋ผ์ ์ถ๊ฐ๋ก ๊ฐ์ง๊ณ ์๋ Pydantic ์ฝ๋๋ ๋ชจ๋ ๋์ํฉ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ํ <abbr title="Object-Relational Mapper - ๊ฐ์ฒด-๊ด๊ณ ๋งคํผ">ORM</abbr>, <abbr title="Object-Document Mapper - ๊ฐ์ฒด-๋ฌธ์ ๋งคํผ">ODM</abbr>๊ณผ ๊ฐ์, Pydantic์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํฌํจํฉ๋๋ค.
## ๋ด์ค๋ ํฐ ๊ตฌ๋
{ #subscribe-to-the-newsletter }
-(์์ฃผ ๋ฐ์ก๋์ง ์๋) [**FastAPI and friends** ๋ด์ค๋ ํฐ](newsletter.md){.internal-link target=_blank}๋ฅผ ๊ตฌ๋
ํ์ฌ ์ต์ ์ ๋ณด๋ฅผ ์ ์งํ ์ ์์ต๋๋ค:
+(์์ฃผ ๋ฐ์ก๋์ง ์๋) [**FastAPI and friends** ๋ด์ค๋ ํฐ](newsletter.md)๋ฅผ ๊ตฌ๋
ํ์ฌ ์ต์ ์ ๋ณด๋ฅผ ์ ์งํ ์ ์์ต๋๋ค:
* FastAPI and friends์ ๋ํ ๋ด์ค ๐
* ๊ฐ์ด๋ ๐
## X(Twitter)์์ FastAPI ํ๋ก์ฐํ๊ธฐ { #follow-fastapi-on-x-twitter }
-<a href="https://x.com/fastapi" class="external-link" target="_blank">**X (Twitter)**์ @fastapi๋ฅผ ํ๋ก์ฐ</a>ํ์ฌ **FastAPI** ์ ๋ํ ์ต์ ๋ด์ค๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๐ฆ
+[**X (Twitter)**์ @fastapi๋ฅผ ํ๋ก์ฐ](https://x.com/fastapi)ํ์ฌ **FastAPI** ์ ๋ํ ์ต์ ๋ด์ค๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๐ฆ
## GitHub์์ **FastAPI**์ Star ์ฃผ๊ธฐ { #star-fastapi-in-github }
-GitHub์์ FastAPI์ "star"๋ฅผ ๋ถ์ผ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ์ star ๋ฒํผ์ ํด๋ฆญ): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. โญ๏ธ
+GitHub์์ FastAPI์ "star"๋ฅผ ๋ถ์ผ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ์ star ๋ฒํผ์ ํด๋ฆญ): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). โญ๏ธ
์คํ๋ฅผ ๋๋ฆผ์ผ๋ก์จ, ๋ค๋ฅธ ์ฌ์ฉ์๋ค์ด ์ข ๋ ์ฝ๊ฒ ์ฐพ์ ์ ์๊ณ , ๋ง์ ์ฌ๋๋ค์๊ฒ ์ ์ฉํ ๊ฒ์์ ๋ํ๋ผ ์ ์์ต๋๋ค.
## ๋ฆด๋ฆฌ์ฆ ํ์ธ์ ์ํด GitHub ์ ์ฅ์ ๋ณด๊ธฐ { #watch-the-github-repository-for-releases }
-GitHub์์ FastAPI๋ฅผ "watch"ํ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ "watch" ๋ฒํผ์ ํด๋ฆญ): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ๐
+GitHub์์ FastAPI๋ฅผ "watch"ํ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ "watch" ๋ฒํผ์ ํด๋ฆญ): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ๐
์ฌ๊ธฐ์ "Releases only"๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
## ๊ฐ๋ฐ์์์ ์ฐ๊ฒฐ { #connect-with-the-author }
-๊ฐ๋ฐ์(์์ฑ์)์ธ <a href="https://tiangolo.com" class="external-link" target="_blank">์ (Sebastiรกn Ramรญrez / `tiangolo`)</a>์ ์ฐ๋ฝ์ ์ทจํ ์ ์์ต๋๋ค.
+๊ฐ๋ฐ์(์์ฑ์)์ธ [์ (Sebastiรกn Ramรญrez / `tiangolo`)](https://tiangolo.com)์ ์ฐ๋ฝ์ ์ทจํ ์ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ ํ ์ ์์ต๋๋ค:
-* <a href="https://github.com/tiangolo" class="external-link" target="_blank">**GitHub**์์ ํ๋ก์ฐํ๊ธฐ</a>.
+* [**GitHub**์์ ํ๋ก์ฐํ๊ธฐ](https://github.com/tiangolo).
* ์ฌ๋ฌ๋ถ์๊ฒ ๋์์ด ๋ ์ ์ ๋ค๋ฅธ ์คํ์์ค ํ๋ก์ ํธ๋ฅผ ํ์ธํ์ญ์์ค.
* ์๋ก์ด ์คํ์์ค ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์์ ๋ ํ์ธํ๋ ค๋ฉด ํ๋ก์ฐ ํ์ญ์์ค.
-* <a href="https://x.com/tiangolo" class="external-link" target="_blank">**X (Twitter)**</a> ๋๋ <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodon</a>์์ ํ๋ก์ฐํ๊ธฐ.
+* [**X (Twitter)**](https://x.com/tiangolo) ๋๋ [Mastodon](https://fosstodon.org/@tiangolo)์์ ํ๋ก์ฐํ๊ธฐ.
* FastAPI์ ์ฌ์ฉ ์ฉ๋๋ฅผ ์๋ ค์ฃผ์ธ์ (๊ทธ๊ฒ์ ๋ฃ๋ ๊ฒ์ ์ข์ํฉ๋๋ค).
* ๋ฐํ๋ ์๋ก์ด ํด ์ถ์ ์์์ ๋ฐ์๋ณด์ญ์์ค.
- * <a href="https://x.com/fastapi" class="external-link" target="_blank">X(Twitter)์์ @fastapi๋ฅผ ํ๋ก์ฐ</a> (๋ณ๋ ๊ณ์ ์์) ํ ์ ์์ต๋๋ค.
-* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">**LinkedIn**์์ ํ๋ก์ฐํ๊ธฐ</a>.
+ * [X(Twitter)์์ @fastapi๋ฅผ ํ๋ก์ฐ](https://x.com/fastapi) (๋ณ๋ ๊ณ์ ์์) ํ ์ ์์ต๋๋ค.
+* [**LinkedIn**์์ ํ๋ก์ฐํ๊ธฐ](https://www.linkedin.com/in/tiangolo/).
* ์๋ก์ด ํด์ ๋ฐํ๋ ์ถ์ ์์์ ๋ฐ์๋ณด์ญ์์ค (๋จ, X (Twitter)๋ฅผ ๋ ์์ฃผ ์ฌ์ฉํฉ๋๋ค ๐คทโโ).
-* <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> ๋๋ <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>์์ ์ ๊ฐ ์์ฑํ ๋ด์ฉ์ ์ฝ์ด ๋ณด์ญ์์ค (๋๋ ํ๋ก์ฐ).
+* [**Dev.to**](https://dev.to/tiangolo) ๋๋ [**Medium**](https://medium.com/@tiangolo)์์ ์ ๊ฐ ์์ฑํ ๋ด์ฉ์ ์ฝ์ด ๋ณด์ญ์์ค (๋๋ ํ๋ก์ฐ).
* ๋ค๋ฅธ ์์ด๋์ด์ ๊ธฐ์ฌ๋ค์ ์ฝ๊ณ , ์ ๊ฐ ๋ง๋ค์ด์๋ ํด์ ๋ํด์๋ ์ฝ์ผ์ญ์์ค.
* ์๋ก์ด ๋ด์ฉ์ ๊ฒ์ํ ๋ ์ฝ๊ธฐ ์ํด ํ๋ก์ฐ ํ์ญ์์ค.
## **FastAPI**์ ๋ํด ํธ์ํ๊ธฐ { #tweet-about-fastapi }
-<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">**FastAPI**์ ๋ํด ํธ์</a> ํ๊ณ ์ ์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ FastAPI๊ฐ ๋ง์์ ๋๋ ์ด์ ๋ฅผ ์๋ ค์ฃผ์ธ์. ๐
+[**FastAPI**์ ๋ํด ํธ์](https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi) ํ๊ณ ์ ์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ FastAPI๊ฐ ๋ง์์ ๋๋ ์ด์ ๋ฅผ ์๋ ค์ฃผ์ธ์. ๐
**FastAPI**๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉ๋๊ณ ์๋์ง, ์ด๋ค ์ ์ด ๋ง์์ ๋ค์๋์ง, ์ด๋ค ํ๋ก์ ํธ/ํ์ฌ์์ ์ฌ์ฉํ๊ณ ์๋์ง ๋ฑ์ ๋ํด ๋ฃ๊ณ ์ถ์ต๋๋ค.
## FastAPI์ ํฌํํ๊ธฐ { #vote-for-fastapi }
-* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Slant์์ **FastAPI** ์ ๋ํด ํฌํํ์ญ์์ค</a>.
-* <a href="https://alternativeto.net/software/fastapi/about/" class="external-link" target="_blank">AlternativeTo์์ **FastAPI** ์ ๋ํด ํฌํํ์ญ์์ค</a>.
-* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">StackShare์์ **FastAPI**๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ์ํ์ธ์</a>.
+* [Slant์์ **FastAPI** ์ ๋ํด ํฌํํ์ญ์์ค](https://www.slant.co/options/34241/~fastapi-review).
+* [AlternativeTo์์ **FastAPI** ์ ๋ํด ํฌํํ์ญ์์ค](https://alternativeto.net/software/fastapi/about/).
+* [StackShare์์ **FastAPI**๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ์ํ์ธ์](https://stackshare.io/pypi-fastapi).
## GitHub์์ ์ง๋ฌธ์ผ๋ก ๋ค๋ฅธ ์ฌ๋ ๋๊ธฐ { #help-others-with-questions-in-github }
๋ค๋ฅธ ์ฌ๋๋ค์ ์ง๋ฌธ์ ๋์์ ์ค ์ ์์ต๋๋ค:
-* <a href="https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">GitHub Discussions</a>
-* <a href="https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">GitHub Issues</a>
+* [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered)
+* [GitHub Issues](https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+)
๋ง์ ๊ฒฝ์ฐ, ์ฌ๋ฌ๋ถ์ ์ด๋ฏธ ๊ทธ ์ง๋ฌธ์ ๋ํ ๋ต์ ์๊ณ ์์ ์๋ ์์ต๋๋ค. ๐ค
-๋ง์ฝ ๋ง์ ์ฌ๋๋ค์ ์ง๋ฌธ์ ๋์์ค๋ค๋ฉด, ๊ณต์์ ์ธ [FastAPI ์ ๋ฌธ๊ฐ](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๊ฐ ๋ ๊ฒ์
๋๋ค. ๐
+๋ง์ฝ ๋ง์ ์ฌ๋๋ค์ ์ง๋ฌธ์ ๋์์ค๋ค๋ฉด, ๊ณต์์ ์ธ [FastAPI ์ ๋ฌธ๊ฐ](fastapi-people.md#fastapi-experts)๊ฐ ๋ ๊ฒ์
๋๋ค. ๐
๊ฐ์ฅ ์ค์ํ ์ ์: ์น์ ํ๋ ค๊ณ ๋
ธ๋ ฅํ๋ ๊ฒ์
๋๋ค. ์ฌ๋๋ค์ ์ข์ ๊ฐ์ ์๊ณ ์ค๋ฉฐ, ๋ง์ ๊ฒฝ์ฐ ์ต์ ์ ๋ฐฉ์์ผ๋ก ์ง๋ฌธํ์ง ์์ ์๋ ์์ต๋๋ค. ํ์ง๋ง ์ต๋ํ ์น์ ํ๊ฒ ๋ํ๋ ค๊ณ ๋
ธ๋ ฅํ์ธ์. ๐ค
๋ง์ ๊ฒฝ์ฐ, ์ฝ๋์ ์ผ๋ถ๋ง ๋ณต์ฌํด์ ์ฌ๋ฆฌ์ง๋ง, ๊ทธ๊ฒ๋ง์ผ๋ก๋ **๋ฌธ์ ๋ฅผ ์ฌํ**ํ๊ธฐ์ ์ถฉ๋ถํ์ง ์์ต๋๋ค.
-* ์ง๋ฌธ์์๊ฒ <a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">์ต์ํ์ ์ฌํ ๊ฐ๋ฅํ ์์ </a>๋ฅผ ์ ๊ณตํด๋ฌ๋ผ๊ณ ์์ฒญํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ฅผ **๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ**ํ์ฌ ๋ก์ปฌ์์ ์คํํ๊ณ , ์ง๋ฌธ์๊ฐ ๋ณด๊ณ ์๋ ๊ฒ๊ณผ ๋์ผํ ์ค๋ฅ๋ ๋์์ ํ์ธํ๊ฑฐ๋ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ ์ ์ดํดํ ์ ์์ต๋๋ค.
+* ์ง๋ฌธ์์๊ฒ [์ต์ํ์ ์ฌํ ๊ฐ๋ฅํ ์์ ](https://stackoverflow.com/help/minimal-reproducible-example)๋ฅผ ์ ๊ณตํด๋ฌ๋ผ๊ณ ์์ฒญํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ฅผ **๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ**ํ์ฌ ๋ก์ปฌ์์ ์คํํ๊ณ , ์ง๋ฌธ์๊ฐ ๋ณด๊ณ ์๋ ๊ฒ๊ณผ ๋์ผํ ์ค๋ฅ๋ ๋์์ ํ์ธํ๊ฑฐ๋ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ ์ ์ดํดํ ์ ์์ต๋๋ค.
* ๋๊ทธ๋ฌ์ด ๋ง์์ด ๋ ๋ค๋ฉด, ๋ฌธ์ ์ค๋ช
๋ง์ ๊ธฐ๋ฐ์ผ๋ก ์ง์ **์์ ๋ฅผ ๋ง๋ค์ด**๋ณผ ์๋ ์์ต๋๋ค. ๋ค๋ง ์ด๋ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆด ์ ์์ผ๋ฏ๋ก, ๋จผ์ ๋ฌธ์ ๋ฅผ ๋ช
ํํ ํด๋ฌ๋ผ๊ณ ์์ฒญํ๋ ๊ฒ์ด ๋ ๋์ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
## GitHub ์ ์ฅ์ ๋ณด๊ธฐ { #watch-the-github-repository }
-GitHub์์ FastAPI๋ฅผ "watch"ํ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ "watch" ๋ฒํผ์ ํด๋ฆญ): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ๐
+GitHub์์ FastAPI๋ฅผ "watch"ํ ์ ์์ต๋๋ค (์ค๋ฅธ์ชฝ ์๋จ "watch" ๋ฒํผ์ ํด๋ฆญ): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ๐
"Releases only" ๋์ "Watching"์ ์ ํํ๋ฉด ๋๊ตฐ๊ฐ๊ฐ ์ ์ด์๋ ์ง๋ฌธ์ ๋ง๋ค ๋ ์๋ฆผ์ ๋ฐ๊ฒ ๋ฉ๋๋ค. ๋ํ ์ ์ด์, ๋์ค์ปค์
, PR ๋ฑ๋ง ์๋ฆผ์ ๋ฐ๋๋ก ์ง์ ํ ์๋ ์์ต๋๋ค.
## ์ง๋ฌธํ๊ธฐ { #ask-questions }
-GitHub ์ ์ฅ์์์ <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">์ ์ง๋ฌธ์ ์์ฑ</a>ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
+GitHub ์ ์ฅ์์์ [์ ์ง๋ฌธ์ ์์ฑ](https://github.com/fastapi/fastapi/discussions/new?category=questions)ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
* **์ง๋ฌธ**์ ํ๊ฑฐ๋ **๋ฌธ์ **์ ๋ํด ์ง๋ฌธํฉ๋๋ค.
* ์๋ก์ด **๊ธฐ๋ฅ**์ ์ ์ ํฉ๋๋ค.
## Pull Request ๋ง๋ค๊ธฐ { #create-a-pull-request }
-Pull Requests๋ฅผ ์ด์ฉํ์ฌ ์์ค ์ฝ๋์ [๊ธฐ์ฌ](contributing.md){.internal-link target=_blank}ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
+Pull Requests๋ฅผ ์ด์ฉํ์ฌ ์์ค ์ฝ๋์ [๊ธฐ์ฌ](contributing.md)ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
* ๋ฌธ์์์ ๋ฐ๊ฒฌํ ์คํ๋ฅผ ์์ ํ ๋.
-* FastAPI์ ๋ํ ๊ธ, ๋น๋์ค, ํ์บ์คํธ๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ฐ๊ฒฌํ๋ค๋ฉด <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">์ด ํ์ผ์ ํธ์ง</a>ํ์ฌ ๊ณต์ ํ ๋.
+* FastAPI์ ๋ํ ๊ธ, ๋น๋์ค, ํ์บ์คํธ๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ฐ๊ฒฌํ๋ค๋ฉด [์ด ํ์ผ์ ํธ์ง](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml)ํ์ฌ ๊ณต์ ํ ๋.
* ํด๋น ์น์
์ ์์ ๋ถ๋ถ์ ๋งํฌ๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
-* ์ฌ๋ฌ๋ถ์ ์ธ์ด๋ก [๋ฌธ์ ๋ฒ์ญ์](contributing.md#translations){.internal-link target=_blank} ๋์์ ์ค ๋.
+* ์ฌ๋ฌ๋ถ์ ์ธ์ด๋ก [๋ฌธ์ ๋ฒ์ญ์](contributing.md#translations) ๋์์ ์ค ๋.
* ๋ค๋ฅธ ์ฌ๋์ด ์์ฑํ ๋ฒ์ญ์ ๊ฒํ ํ๋ ๊ฒ๋ ๋์ธ ์ ์์ต๋๋ค.
* ์๋ก์ด ๋ฌธ์ ์น์
์ ์ ์ํ ๋.
* ๊ธฐ์กด ์ด์/๋ฒ๊ทธ๋ฅผ ์์ ํ ๋.
์ง๊ธ ํ ์ ์๋ ์ฃผ์ ์์
์:
-* [GitHub์์ ์ง๋ฌธ์ผ๋ก ๋ค๋ฅธ ์ฌ๋ ๋๊ธฐ](#help-others-with-questions-in-github){.internal-link target=_blank} (์์ ์น์
์ ์ฐธ์กฐํ์ธ์).
-* [Pull Request ๋ฆฌ๋ทฐํ๊ธฐ](#review-pull-requests){.internal-link target=_blank} (์์ ์น์
์ ์ฐธ์กฐํ์ธ์).
+* [GitHub์์ ์ง๋ฌธ์ผ๋ก ๋ค๋ฅธ ์ฌ๋ ๋๊ธฐ](#help-others-with-questions-in-github) (์์ ์น์
์ ์ฐธ์กฐํ์ธ์).
+* [Pull Request ๋ฆฌ๋ทฐํ๊ธฐ](#review-pull-requests) (์์ ์น์
์ ์ฐธ์กฐํ์ธ์).
์ด ๋ ์์
์ด **๊ฐ์ฅ ๋ง์ ์๊ฐ์ ์๋ชจ**ํฉ๋๋ค. ์ด๊ฒ์ด FastAPI๋ฅผ ์ ์ง ๊ด๋ฆฌํ๋ ์ฃผ์ ์์
์
๋๋ค.
## ์ฑํ
์ ์ฐธ์ฌํ๊ธฐ { #join-the-chat }
-๐ฅ <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord ์ฑํ
์๋ฒ</a> ๐ฅ ์ ์ฐธ์ฌํด์ FastAPI ์ปค๋ฎค๋ํฐ์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ์ด์ธ๋ฆฌ์ธ์.
+๐ฅ [Discord ์ฑํ
์๋ฒ](https://discord.gg/VQjSZaeJmf) ๐ฅ ์ ์ฐธ์ฌํด์ FastAPI ์ปค๋ฎค๋ํฐ์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ์ด์ธ๋ฆฌ์ธ์.
/// tip | ํ
-์ง๋ฌธ์ <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions</a>์์ ํ์ธ์. [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๋ก๋ถํฐ ๋์์ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ํจ์ฌ ๋์ต๋๋ค.
+์ง๋ฌธ์ [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/new?category=questions)์์ ํ์ธ์. [FastAPI Experts](fastapi-people.md#fastapi-experts)๋ก๋ถํฐ ๋์์ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ํจ์ฌ ๋์ต๋๋ค.
์ฑํ
์ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ๋ํ๋ฅผ ์ํด์๋ง ์ฌ์ฉํ์ธ์.
GitHub์์๋ ํ
ํ๋ฆฟ์ด ์ฌ๋ฐ๋ฅธ ์ง๋ฌธ์ ์์ฑํ๋๋ก ์๋ดํ์ฌ ๋ ์ฝ๊ฒ ์ข์ ๋ต๋ณ์ ์ป๊ฑฐ๋, ์ง๋ฌธํ๊ธฐ ์ ์ ์ค์ค๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ GitHub์์๋ ์๊ฐ์ด ์กฐ๊ธ ๊ฑธ๋ฆฌ๋๋ผ๋ ์ ๊ฐ ํญ์ ๋ชจ๋ ๊ฒ์ ๋ตํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ฑํ
์์คํ
์์๋ ์ ๊ฐ ๊ฐ์ธ์ ์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค. ๐
-์ฑํ
์์คํ
์์์ ๋ํ ๋ํ GitHub๋งํผ ์ฝ๊ฒ ๊ฒ์ํ ์ ์๊ธฐ ๋๋ฌธ์, ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ๋ํ ์์์ ์ฌ๋ผ์ง ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ GitHub์ ์๋ ๊ฒ๋ง [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}๊ฐ ๋๋ ๊ฒ์ผ๋ก ์ธ์ ๋๋ฏ๋ก, GitHub์์ ๋ ๋ง์ ๊ด์ฌ์ ๋ฐ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
+์ฑํ
์์คํ
์์์ ๋ํ ๋ํ GitHub๋งํผ ์ฝ๊ฒ ๊ฒ์ํ ์ ์๊ธฐ ๋๋ฌธ์, ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ๋ํ ์์์ ์ฌ๋ผ์ง ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ GitHub์ ์๋ ๊ฒ๋ง [FastAPI Expert](fastapi-people.md#fastapi-experts)๊ฐ ๋๋ ๊ฒ์ผ๋ก ์ธ์ ๋๋ฏ๋ก, GitHub์์ ๋ ๋ง์ ๊ด์ฌ์ ๋ฐ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
๋ฐ๋ฉด, ์ฑํ
์์คํ
์๋ ์์ฒ ๋ช
์ ์ฌ์ฉ์๊ฐ ์์ผ๋ฏ๋ก, ๊ฑฐ์ ํญ์ ๋ํ ์๋๋ฅผ ์ฐพ์ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ๐
## ๊ฐ๋ฐ์ ์คํฐ์ ๋๊ธฐ { #sponsor-the-author }
-์ฌ๋ฌ๋ถ์ **์ ํ/ํ์ฌ**๊ฐ **FastAPI**์ ์์กดํ๊ฑฐ๋ ๊ด๋ จ๋์ด ์๊ณ , FastAPI ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก ์๋ฆฌ๊ณ ์ถ๋ค๋ฉด <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>๋ฅผ ํตํด ๊ฐ๋ฐ์(์ )๋ฅผ ์คํฐ์ํ ์ ์์ต๋๋ค. ํฐ์ด์ ๋ฐ๋ผ ๋ฌธ์์ ๋ฐฐ์ง ๊ฐ์ ์ถ๊ฐ ํํ์ ๋ฐ์ ์๋ ์์ต๋๋ค. ๐
+์ฌ๋ฌ๋ถ์ **์ ํ/ํ์ฌ**๊ฐ **FastAPI**์ ์์กดํ๊ฑฐ๋ ๊ด๋ จ๋์ด ์๊ณ , FastAPI ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก ์๋ฆฌ๊ณ ์ถ๋ค๋ฉด [GitHub sponsors](https://github.com/sponsors/tiangolo)๋ฅผ ํตํด ๊ฐ๋ฐ์(์ )๋ฅผ ์คํฐ์ํ ์ ์์ต๋๋ค. ํฐ์ด์ ๋ฐ๋ผ ๋ฌธ์์ ๋ฐฐ์ง ๊ฐ์ ์ถ๊ฐ ํํ์ ๋ฐ์ ์๋ ์์ต๋๋ค. ๐
---
# ์ญ์ฌ, ๋์์ธ ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋ { #history-design-and-future }
-์ผ๋ง ์ , <a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">ํ **FastAPI** ์ฌ์ฉ์๊ฐ ์ด๋ ๊ฒ ๋ฌผ์์ต๋๋ค</a>:
+์ผ๋ง ์ , [ํ **FastAPI** ์ฌ์ฉ์๊ฐ ์ด๋ ๊ฒ ๋ฌผ์์ต๋๋ค](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920):
> ์ด ํ๋ก์ ํธ์ ์ญ์ฌ๋ ๋ฌด์์ธ๊ฐ์? ๋ช ์ฃผ ๋ง์ ์๋ฌด ๋ฐ์๋ ๊ฐ์๊ธฐ ๋ํ๋ ์์ฒญ๋๊ฒ ์ข์์ง ๊ฒ์ฒ๋ผ ๋ณด์ด๋ค์ [...]
**FastAPI**์ ์ญ์ฌ๋ ์๋น ๋ถ๋ถ ๊ทธ ์ด์ ์ ์๋ ๋๊ตฌ๋ค์ ์ญ์ฌ์
๋๋ค.
-[๋์](alternatives.md){.internal-link target=_blank} ์น์
์์ ์ธ๊ธ๋ ๊ฒ์ฒ๋ผ:
+[๋์](alternatives.md) ์น์
์์ ์ธ๊ธ๋ ๊ฒ์ฒ๋ผ:
<blockquote markdown="1">
๊ฐ์ฅ ์ธ๊ธฐ ์๋ Python ํธ์ง๊ธฐ๋ค: PyCharm, VS Code, Jedi ๊ธฐ๋ฐ ํธ์ง๊ธฐ์์ ์ฌ๋ฌ ์์ด๋์ด๋ฅผ ํ
์คํธํ์ต๋๋ค.
-์ฝ 80%์ ์ฌ์ฉ์๋ฅผ ํฌํจํ๋ ์ต๊ทผ <a href="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools" class="external-link" target="_blank">Python Developer Survey</a>์ ๋ฐ๋ฅด๋ฉด ๊ทธ๋ ์ต๋๋ค.
+์ฝ 80%์ ์ฌ์ฉ์๋ฅผ ํฌํจํ๋ ์ต๊ทผ [Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools)์ ๋ฐ๋ฅด๋ฉด ๊ทธ๋ ์ต๋๋ค.
์ฆ, **FastAPI**๋ Python ๊ฐ๋ฐ์์ 80%๊ฐ ์ฌ์ฉํ๋ ํธ์ง๊ธฐ๋ค๋ก ํน๋ณํ ํ
์คํธ๋์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ๋ค๋ฅธ ํธ์ง๊ธฐ๋ ์ ์ฌํ๊ฒ ๋์ํ๋ ๊ฒฝํฅ์ด ์์ผ๋ฏ๋ก, ๊ทธ ๋ชจ๋ ์ด์ ์ ์ฌ์ค์ ๋ชจ๋ ํธ์ง๊ธฐ์์ ๋์ํด์ผ ํฉ๋๋ค.
## ํ์์กฐ๊ฑด { #requirements }
-์ฌ๋ฌ ๋์์ ํ
์คํธํ ํ, ์ฅ์ ๋๋ฌธ์ <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">**Pydantic**</a>์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
+์ฌ๋ฌ ๋์์ ํ
์คํธํ ํ, ์ฅ์ ๋๋ฌธ์ [**Pydantic**](https://docs.pydantic.dev/)์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๊ทธ ํ, JSON Schema๋ฅผ ์์ ํ ์ค์ํ๋๋ก ํ๊ณ , ์ ์ฝ ์กฐ๊ฑด ์ ์ธ์ ์ ์ํ๋ ๋ค์ํ ๋ฐฉ์์ ์ง์ํ๋ฉฐ, ์ฌ๋ฌ ํธ์ง๊ธฐ์์์ ํ
์คํธ๋ฅผ ๋ฐํ์ผ๋ก ํธ์ง๊ธฐ ์ง์(ํ์
๊ฒ์ฌ, ์๋ ์์ฑ)์ ๊ฐ์ ํ๊ธฐ ์ํด ๊ธฐ์ฌํ์ต๋๋ค.
-๊ฐ๋ฐ ๊ณผ์ ์์, ๋ ๋ค๋ฅธ ํต์ฌ ํ์์กฐ๊ฑด์ธ <a href="https://www.starlette.dev/" class="external-link" target="_blank">**Starlette**</a>์๋ ๊ธฐ์ฌํ์ต๋๋ค.
+๊ฐ๋ฐ ๊ณผ์ ์์, ๋ ๋ค๋ฅธ ํต์ฌ ํ์์กฐ๊ฑด์ธ [**Starlette**](https://www.starlette.dev/)์๋ ๊ธฐ์ฌํ์ต๋๋ค.
## ๊ฐ๋ฐ { #development }
-**FastAPI** ์์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์์ํ์ ๋์ฏค์๋, ๋๋ถ๋ถ์ ์กฐ๊ฐ๋ค์ด ์ด๋ฏธ ๊ฐ์ถฐ์ ธ ์์๊ณ , ๋์์ธ์ ์ ์๋์ด ์์์ผ๋ฉฐ, ํ์์กฐ๊ฑด๊ณผ ๋๊ตฌ๋ ์ค๋น๋์ด ์์๊ณ , ํ์ค๊ณผ ๋ช
์ธ์ ๋ํ ์ง์๋ ๋ช
ํํ๊ณ ์ต์ ์ํ์์ต๋๋ค.
+**FastAPI** ์์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์์ํ์ ๋์ฏค์๋, ๋๋ถ๋ถ์ ์กฐ๊ฐ๋ค์ด ์ด๋ฏธ ๊ฐ์ถฐ์ ธ ์์๊ณ , ๋์์ธ์ ์ ์๋์ด ์์๋ฉฐ, ํ์์กฐ๊ฑด๊ณผ ๋๊ตฌ๋ ์ค๋น๋์ด ์์๊ณ , ํ์ค๊ณผ ๋ช
์ธ์ ๋ํ ์ง์๋ ๋ช
ํํ๊ณ ์ต์ ์ํ์์ต๋๋ค.
## ๋ฏธ๋ { #future }
**FastAPI**์ ๋ฏธ๋๋ ๋ฐ์ต๋๋ค.
-๊ทธ๋ฆฌ๊ณ [์ฌ๋ฌ๋ถ์ ๋์](help-fastapi.md){.internal-link target=_blank}์ ํฐ ํ์ด ๋ฉ๋๋ค.
+๊ทธ๋ฆฌ๊ณ [์ฌ๋ฌ๋ถ์ ๋์](help-fastapi.md)์ ํฐ ํ์ด ๋ฉ๋๋ค.
FastAPI ๋ฒ์ `0.122.0` ์ด์ ์๋, ํตํฉ ๋ณด์ ์ ํธ๋ฆฌํฐ๊ฐ ์ธ์ฆ ์คํจ ํ ํด๋ผ์ด์ธํธ์ ์ค๋ฅ๋ฅผ ๋ฐํํ ๋ HTTP ์ํ ์ฝ๋ `403 Forbidden`์ ์ฌ์ฉํ์ต๋๋ค.
-FastAPI ๋ฒ์ `0.122.0`๋ถํฐ๋ ๋ ์ ์ ํ HTTP ์ํ ์ฝ๋ `401 Unauthorized`๋ฅผ ์ฌ์ฉํ๋ฉฐ, HTTP ๋ช
์ธ์ธ <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>๋ฅผ ๋ฐ๋ผ ์๋ต์ ํฉ๋ฆฌ์ ์ธ `WWW-Authenticate` ํค๋๋ฅผ ๋ฐํํฉ๋๋ค.
+FastAPI ๋ฒ์ `0.122.0`๋ถํฐ๋ ๋ ์ ์ ํ HTTP ์ํ ์ฝ๋ `401 Unauthorized`๋ฅผ ์ฌ์ฉํ๋ฉฐ, HTTP ๋ช
์ธ์ธ [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized)๋ฅผ ๋ฐ๋ผ ์๋ต์ ํฉ๋ฆฌ์ ์ธ `WWW-Authenticate` ํค๋๋ฅผ ๋ฐํํฉ๋๋ค.
ํ์ง๋ง ์ด๋ค ์ด์ ๋ก๋ ํด๋ผ์ด์ธํธ๊ฐ ์ด์ ๋์์ ์์กดํ๊ณ ์๋ค๋ฉด, ๋ณด์ ํด๋์ค์์ `make_not_authenticated_error` ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ์ด์ ๋์์ผ๋ก ๋๋๋ฆด ์ ์์ต๋๋ค.
์ฝ๋์ ๋ณด์ ๊ฒฐํจ์ด ์๋ค๋ฉด, ๊ทธ ๊ฒฐํจ์ ์ฌ์ ํ ์กด์ฌํ ๊ฒ์
๋๋ค.
-๋ฌธ์๋ฅผ ์จ๊ธฐ๋ ๊ฒ์ API์ ์ํธ์์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค๋ฉฐ, ํ๋ก๋์
์์ ๋๋ฒ๊น
์ ๋ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ๋จ์ํ <a href="https://en.wikipedia.org/wiki/Security_through_obscurity" class="external-link" target="_blank">Security through obscurity</a>์ ํ ํํ๋ก ๊ฐ์ฃผ๋ ์ ์์ต๋๋ค.
+๋ฌธ์๋ฅผ ์จ๊ธฐ๋ ๊ฒ์ API์ ์ํธ์์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค๋ฉฐ, ํ๋ก๋์
์์ ๋๋ฒ๊น
์ ๋ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ ๋จ์ํ [์ํ๋ฅผ ํตํ ๋ณด์](https://en.wikipedia.org/wiki/Security_through_obscurity)์ ํ ํํ๋ก ๊ฐ์ฃผ๋ ์ ์์ต๋๋ค.
API๋ฅผ ๋ณดํธํ๊ณ ์ถ๋ค๋ฉด, ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ๋ ๋์ ๋ฐฉ๋ฒ๋ค์ด ์์ต๋๋ค:
# Swagger UI ๊ตฌ์ฑ { #configure-swagger-ui }
-์ถ๊ฐ์ ์ธ <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">Swagger UI ๋งค๊ฐ๋ณ์</a>๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
+์ถ๊ฐ์ ์ธ [Swagger UI ๋งค๊ฐ๋ณ์](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
๊ตฌ์ฑ์ ํ๋ ค๋ฉด, `FastAPI()` ์ฑ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ๋๋ `get_swagger_ui_html()` ํจ์์ `swagger_ui_parameters` ์ธ์๋ฅผ ์ ๋ฌํ์ญ์์ค.
## ๊ธฐํ Swagger UI ๋งค๊ฐ๋ณ์ { #other-swagger-ui-parameters }
-์ฌ์ฉํ ์ ์๋ ๋ค๋ฅธ ๋ชจ๋ ๊ตฌ์ฑ ์ต์
์ ํ์ธํ๋ ค๋ฉด, Swagger UI ๋งค๊ฐ๋ณ์์ ๋ํ ๊ณต์ <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">Swagger UI ๋งค๊ฐ๋ณ์ ๋ฌธ์</a>๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
+์ฌ์ฉํ ์ ์๋ ๋ค๋ฅธ ๋ชจ๋ ๊ตฌ์ฑ ์ต์
์ ํ์ธํ๋ ค๋ฉด, ๊ณต์ [Swagger UI ๋งค๊ฐ๋ณ์ ๋ฌธ์](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
## JavaScript ์ ์ฉ ์ค์ { #javascript-only-settings }
### ํ
์คํธํ๊ธฐ { #test-it }
-์ด์ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>์์ ๋ฌธ์์ ์ ์ํ ๋ค ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉด, ์ CDN์์ ์์
์ ๋ถ๋ฌ์ค๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
+์ด์ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)์์ ๋ฌธ์์ ์ ์ํ ๋ค ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉด, ์ CDN์์ ์์
์ ๋ถ๋ฌ์ค๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
## ๋ฌธ์์ฉ JavaScript์ CSS ์์ฒด ํธ์คํ
ํ๊ธฐ { #self-hosting-javascript-and-css-for-docs }
**Swagger UI**๋ ๋ค์ ํ์ผ์ ์ฌ์ฉํฉ๋๋ค:
-* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
-* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
+* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js)
+* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css)
**ReDoc**์ ๋ค์ ํ์ผ์ ์ฌ์ฉํฉ๋๋ค:
-* <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
+* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js)
์ดํ ํ์ผ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
### ์ ์ ํ์ผ ํ
์คํธํ๊ธฐ { #test-the-static-files }
-์ ํ๋ฆฌ์ผ์ด์
์ ์์ํ๊ณ <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>๋ก ์ด๋ํ์ธ์.
+์ ํ๋ฆฌ์ผ์ด์
์ ์์ํ๊ณ [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js)๋ก ์ด๋ํ์ธ์.
**ReDoc**์ฉ ๋งค์ฐ ๊ธด JavaScript ํ์ผ์ด ๋ณด์ผ ๊ฒ์
๋๋ค.
### ์ ์ ํ์ผ UI ํ
์คํธํ๊ธฐ { #test-static-files-ui }
-์ด์ WiFi ์ฐ๊ฒฐ์ ๋๊ณ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>์์ ๋ฌธ์์ ์ ์ํ ๋ค ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํด ๋ณด์ธ์.
+์ด์ WiFi ์ฐ๊ฒฐ์ ๋๊ณ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)์์ ๋ฌธ์์ ์ ์ํ ๋ค ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํด ๋ณด์ธ์.
์ธํฐ๋ท์ด ์์ด๋ API ๋ฌธ์๋ฅผ ๋ณด๊ณ , API์ ์ํธ์์ฉํ ์ ์์ ๊ฒ์
๋๋ค.
์ฌ์ฉ ์ฌ๋ก์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค:
-* JSON์ด ์๋ ์์ฒญ ๋ฐ๋๋ฅผ JSON์ผ๋ก ๋ณํํ๊ธฐ(์: <a href="https://msgpack.org/index.html" class="external-link" target="_blank">`msgpack`</a>).
+* JSON์ด ์๋ ์์ฒญ ๋ฐ๋๋ฅผ JSON์ผ๋ก ๋ณํํ๊ธฐ(์: [`msgpack`](https://msgpack.org/index.html)).
* gzip์ผ๋ก ์์ถ๋ ์์ฒญ ๋ฐ๋ ์์ถ ํด์ ํ๊ธฐ.
* ๋ชจ๋ ์์ฒญ ๋ฐ๋๋ฅผ ์๋์ผ๋ก ๋ก๊น
ํ๊ธฐ.
/// tip | ํ
-์ด ์์๋ ๋์ ๋ฐฉ์ ์์ฐ์ ์ํ ์ฅ๋๊ฐ ์์ ์
๋๋ค. Gzip ์ง์์ด ํ์ํ๋ค๋ฉด ์ ๊ณต๋๋ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+์ด ์์๋ ๋์ ๋ฐฉ์ ์์ฐ์ ์ํ ์ฅ๋๊ฐ ์์ ์
๋๋ค. Gzip ์ง์์ด ํ์ํ๋ค๋ฉด ์ ๊ณต๋๋ [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
๊ทธ๋ฆฌ๊ณ ์ด ๋ ๊ฐ์ง, `scope`์ `receive`๊ฐ ์๋ก์ด `Request` ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ฐ ํ์ํ ๊ฒ๋ค์
๋๋ค.
-`Request`์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">Starlette์ Requests ๋ฌธ์</a>๋ฅผ ํ์ธํ์ธ์.
+`Request`์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด [Starlette์ Requests ๋ฌธ์](https://www.starlette.dev/requests/)๋ฅผ ํ์ธํ์ธ์.
///
/// tip | ํ
-๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด `RequestValidationError`์ ๋ํ ์ปค์คํ
ํธ๋ค๋ฌ์์ `body`๋ฅผ ์ฌ์ฉํ๋ ํธ์ด ์๋ง ํจ์ฌ ๋ ์ฝ์ต๋๋ค([์ค๋ฅ ์ฒ๋ฆฌํ๊ธฐ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
+๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด `RequestValidationError`์ ๋ํ ์ปค์คํ
ํธ๋ค๋ฌ์์ `body`๋ฅผ ์ฌ์ฉํ๋ ํธ์ด ์๋ง ํจ์ฌ ๋ ์ฝ์ต๋๋ค([์ค๋ฅ ์ฒ๋ฆฌํ๊ธฐ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)).
ํ์ง๋ง ์ด ์์๋ ์ฌ์ ํ ์ ํจํ๋ฉฐ, ๋ด๋ถ ์ปดํฌ๋ํธ์ ์ํธ์์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก, ๋์ผํ ์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ์ฌ์ฉํด OpenAPI ์คํค๋ง๋ฅผ ์์ฑํ๊ณ ํ์ํ ๊ฐ ๋ถ๋ถ์ ๋ฎ์ด์ธ ์ ์์ต๋๋ค.
-์๋ฅผ ๋ค์ด, <a href="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo" class="external-link" target="_blank">์ปค์คํ
๋ก๊ณ ๋ฅผ ํฌํจํ๊ธฐ ์ํ ReDoc์ OpenAPI ํ์ฅ</a>์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
+์๋ฅผ ๋ค์ด, [์ปค์คํ
๋ก๊ณ ๋ฅผ ํฌํจํ๊ธฐ ์ํ ReDoc์ OpenAPI ํ์ฅ](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo)์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
### ์ผ๋ฐ์ ์ธ **FastAPI** { #normal-fastapi }
### ํ์ธํ๊ธฐ { #check-it }
-<a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>๋ก ์ด๋ํ๋ฉด ์ปค์คํ
๋ก๊ณ (์ด ์์์์๋ **FastAPI** ๋ก๊ณ )๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค:
+[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)๋ก ์ด๋ํ๋ฉด ์ปค์คํ
๋ก๊ณ (์ด ์์์์๋ **FastAPI** ๋ก๊ณ )๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค:
<img src="/img/tutorial/extending-openapi/image01.png">
## ๋ฐ์ดํฐ ํํฐ๋ง - ๋ณด์ { #filter-data-security }
-๋ฐํํ๋ฉด ์ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๊ณผ๋ํ๊ฒ ๋ฐํํ์ง ์๋๋ก ํ๋ ค๋ฉด, [ํํ ๋ฆฌ์ผ - ์๋ต ๋ชจ๋ธ - ๋ฐํ ํ์
](../tutorial/response-model.md){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+๋ฐํํ๋ฉด ์ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๊ณผ๋ํ๊ฒ ๋ฐํํ์ง ์๋๋ก ํ๋ ค๋ฉด, [ํํ ๋ฆฌ์ผ - ์๋ต ๋ชจ๋ธ - ๋ฐํ ํ์
](../tutorial/response-model.md) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+
+## ์๋ต ์ฑ๋ฅ ์ต์ ํ - ์๋ต ๋ชจ๋ธ - ๋ฐํ ํ์
{ #optimize-response-performance-response-model-return-type }
+
+JSON ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ ๋ ์ฑ๋ฅ์ ์ต์ ํํ๋ ค๋ฉด ๋ฐํ ํ์
๋๋ ์๋ต ๋ชจ๋ธ์ ์ฌ์ฉํ์ธ์. ๊ทธ๋ฌ๋ฉด Pydantic์ด Python์ ๊ฑฐ์น์ง ์๊ณ Rust ์ธก์์ JSON ์ง๋ ฌํ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ [ํํ ๋ฆฌ์ผ - ์๋ต ๋ชจ๋ธ - ๋ฐํ ํ์
](../tutorial/response-model.md) ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
## ๋ฌธ์ํ ํ๊ทธ - OpenAPI { #documentation-tags-openapi }
-*๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ํ๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ , ๋ฌธ์ UI์์ ์ด๋ฅผ ๊ทธ๋ฃนํํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ํ๊ทธ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ํ๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ , ๋ฌธ์ UI์์ ์ด๋ฅผ ๊ทธ๋ฃนํํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ํ๊ทธ](../tutorial/path-operation-configuration.md#tags) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## ๋ฌธ์ํ ์์ฝ ๋ฐ ์ค๋ช
- OpenAPI { #documentation-summary-and-description-openapi }
-*๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์์ฝ๊ณผ ์ค๋ช
์ ์ถ๊ฐํ๊ณ , ๋ฌธ์ UI์ ํ์ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์์ฝ ๋ฐ ์ค๋ช
](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์์ฝ๊ณผ ์ค๋ช
์ ์ถ๊ฐํ๊ณ , ๋ฌธ์ UI์ ํ์ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์์ฝ ๋ฐ ์ค๋ช
](../tutorial/path-operation-configuration.md#summary-and-description) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## ๋ฌธ์ํ ์๋ต ์ค๋ช
- OpenAPI { #documentation-response-description-openapi }
-๋ฌธ์ UI์ ํ์๋๋ ์๋ต์ ์ค๋ช
์ ์ ์ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์๋ต ์ค๋ช
](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+๋ฌธ์ UI์ ํ์๋๋ ์๋ต์ ์ค๋ช
์ ์ ์ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์๋ต ์ค๋ช
](../tutorial/path-operation-configuration.md#response-description) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## ๋ฌธ์ํ *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ง์ ์ค๋จํ๊ธฐ - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
-*๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์ง์ ์ค๋จ(deprecate)์ผ๋ก ํ์ํ๊ณ , ๋ฌธ์ UI์ ๋ณด์ฌ์ฃผ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์ง์ ์ค๋จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+*๊ฒฝ๋ก ์ฒ๋ฆฌ*๋ฅผ ์ง์ ์ค๋จ(deprecate)์ผ๋ก ํ์ํ๊ณ , ๋ฌธ์ UI์ ๋ณด์ฌ์ฃผ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ - ์ง์ ์ค๋จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## ์ด๋ค ๋ฐ์ดํฐ๋ JSON ํธํ์ผ๋ก ๋ณํํ๊ธฐ { #convert-any-data-to-json-compatible }
-์ด๋ค ๋ฐ์ดํฐ๋ JSON ํธํ ํ์์ผ๋ก ๋ณํํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - JSON ํธํ ์ธ์ฝ๋](../tutorial/encoder.md){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+์ด๋ค ๋ฐ์ดํฐ๋ JSON ํธํ ํ์์ผ๋ก ๋ณํํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - JSON ํธํ ์ธ์ฝ๋](../tutorial/encoder.md) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## OpenAPI ๋ฉํ๋ฐ์ดํฐ - ๋ฌธ์ { #openapi-metadata-docs }
-๋ผ์ด์ ์ค, ๋ฒ์ , ์ฐ๋ฝ์ฒ ๋ฑ์ ์ ๋ณด๋ฅผ ํฌํจํด OpenAPI ์คํค๋ง์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+๋ผ์ด์ ์ค, ๋ฒ์ , ์ฐ๋ฝ์ฒ ๋ฑ์ ์ ๋ณด๋ฅผ ํฌํจํด OpenAPI ์คํค๋ง์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## OpenAPI ์ฌ์ฉ์ ์ ์ URL { #openapi-custom-url }
-OpenAPI URL์ ์ปค์คํฐ๋ง์ด์ฆ(๋๋ ์ ๊ฑฐ)ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+OpenAPI URL์ ์ปค์คํฐ๋ง์ด์ฆ(๋๋ ์ ๊ฑฐ)ํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md#openapi-url) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
## OpenAPI ๋ฌธ์ URL { #openapi-docs-urls }
-์๋์ผ๋ก ์์ฑ๋๋ ๋ฌธ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์์ ์ฌ์ฉํ๋ URL์ ์
๋ฐ์ดํธํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
+์๋์ผ๋ก ์์ฑ๋๋ ๋ฌธ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์์ ์ฌ์ฉํ๋ URL์ ์
๋ฐ์ดํธํ๋ ค๋ฉด [ํํ ๋ฆฌ์ผ - ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์ URL](../tutorial/metadata.md#docs-urls) ๋ฌธ์๋ฅผ ์ฝ์ด๋ณด์ธ์.
๋ค์์ **ASGI** ์ง์์ด ์๋ **GraphQL** ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์
๋๋ค. **FastAPI**์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค:
-* <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> ๐
- * <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">FastAPI์ฉ ๋ฌธ์</a> ์ ๊ณต
-* <a href="https://ariadnegraphql.org/" class="external-link" target="_blank">Ariadne</a>
- * <a href="https://ariadnegraphql.org/docs/fastapi-integration" class="external-link" target="_blank">FastAPI์ฉ ๋ฌธ์</a> ์ ๊ณต
-* <a href="https://tartiflette.io/" class="external-link" target="_blank">Tartiflette</a>
- * ASGI ํตํฉ์ ์ ๊ณตํ๊ธฐ ์ํด <a href="https://tartiflette.github.io/tartiflette-asgi/" class="external-link" target="_blank">Tartiflette ASGI</a> ์ฌ์ฉ
-* <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>
- * <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a> ์ฌ์ฉ
+* [Strawberry](https://strawberry.rocks/) ๐
+ * [FastAPI์ฉ ๋ฌธ์](https://strawberry.rocks/docs/integrations/fastapi) ์ ๊ณต
+* [Ariadne](https://ariadnegraphql.org/)
+ * [FastAPI์ฉ ๋ฌธ์](https://ariadnegraphql.org/docs/fastapi-integration) ์ ๊ณต
+* [Tartiflette](https://tartiflette.io/)
+ * ASGI ํตํฉ์ ์ ๊ณตํ๊ธฐ ์ํด [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) ์ฌ์ฉ
+* [Graphene](https://graphene-python.org/)
+ * [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) ์ฌ์ฉ
## Strawberry๋ก GraphQL ์ฌ์ฉํ๊ธฐ { #graphql-with-strawberry }
-**GraphQL**๋ก ์์
ํด์ผ ํ๊ฑฐ๋ ์์
ํ๊ณ ์ถ๋ค๋ฉด, <a href="https://strawberry.rocks/" class="external-link" target="_blank">**Strawberry**</a>๋ฅผ **๊ถ์ฅ**ํฉ๋๋ค. **FastAPI**์ ์ค๊ณ์ ๊ฐ์ฅ ๊ฐ๊น๊ณ , ๋ชจ๋ ๊ฒ์ด **type annotations**์ ๊ธฐ๋ฐํด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
+**GraphQL**๋ก ์์
ํด์ผ ํ๊ฑฐ๋ ์์
ํ๊ณ ์ถ๋ค๋ฉด, [**Strawberry**](https://strawberry.rocks/)๋ฅผ **๊ถ์ฅ**ํฉ๋๋ค. **FastAPI**์ ์ค๊ณ์ ๊ฐ์ฅ ๊ฐ๊น๊ณ , ๋ชจ๋ ๊ฒ์ด **type annotations**์ ๊ธฐ๋ฐํด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ฌ์ฉ ์ฌ๋ก์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํธํ ์๋ ์์ง๋ง, ์ ๊ฒ ๋ฌป๋๋ค๋ฉด ์๋ง **Strawberry**๋ฅผ ๋จผ์ ์๋ํด ๋ณด๋ผ๊ณ ์ ์ํ ๊ฒ์
๋๋ค.
{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}
-<a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry ๋ฌธ์</a>์์ Strawberry์ ๋ํด ๋ ์์๋ณผ ์ ์์ต๋๋ค.
+[Strawberry ๋ฌธ์](https://strawberry.rocks/)์์ Strawberry์ ๋ํด ๋ ์์๋ณผ ์ ์์ต๋๋ค.
-๋ํ <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">FastAPI์์ Strawberry ์ฌ์ฉ</a>์ ๋ํ ๋ฌธ์๋ ํ์ธํด ๋ณด์ธ์.
+๋ํ [FastAPI์์ Strawberry ์ฌ์ฉ](https://strawberry.rocks/docs/integrations/fastapi)์ ๋ํ ๋ฌธ์๋ ํ์ธํด ๋ณด์ธ์.
## Starlette์ ์์ `GraphQLApp` { #older-graphqlapp-from-starlette }
-์ด์ ๋ฒ์ ์ Starlette์๋ <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>๊ณผ ํตํฉํ๊ธฐ ์ํ `GraphQLApp` ํด๋์ค๊ฐ ํฌํจ๋์ด ์์์ต๋๋ค.
+์ด์ ๋ฒ์ ์ Starlette์๋ [Graphene](https://graphene-python.org/)๊ณผ ํตํฉํ๊ธฐ ์ํ `GraphQLApp` ํด๋์ค๊ฐ ํฌํจ๋์ด ์์์ต๋๋ค.
-์ด๊ฒ์ Starlette์์ deprecated ๋์์ง๋ง, ์ด๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ์๋ค๋ฉด ๊ฐ์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ค๋ฃจ๊ณ **๊ฑฐ์ ๋์ผํ ์ธํฐํ์ด์ค**๋ฅผ ๊ฐ์ง <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a>๋ก ์ฝ๊ฒ **๋ง์ด๊ทธ๋ ์ด์
**ํ ์ ์์ต๋๋ค.
+์ด๊ฒ์ Starlette์์ deprecated ๋์์ง๋ง, ์ด๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ์๋ค๋ฉด ๊ฐ์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ค๋ฃจ๊ณ **๊ฑฐ์ ๋์ผํ ์ธํฐํ์ด์ค**๋ฅผ ๊ฐ์ง [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3)๋ก ์ฝ๊ฒ **๋ง์ด๊ทธ๋ ์ด์
**ํ ์ ์์ต๋๋ค.
/// tip | ํ
-GraphQL์ด ํ์ํ๋ค๋ฉด, ์ปค์คํ
ํด๋์ค์ ํ์
๋์ type annotations์ ๊ธฐ๋ฐํ <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a>๋ฅผ ์ฌ์ ํ ํ์ธํด ๋ณด์๊ธธ ๊ถ์ฅํฉ๋๋ค.
+GraphQL์ด ํ์ํ๋ค๋ฉด, ์ปค์คํ
ํด๋์ค์ ํ์
๋์ type annotations์ ๊ธฐ๋ฐํ [Strawberry](https://strawberry.rocks/)๋ฅผ ์ฌ์ ํ ํ์ธํด ๋ณด์๊ธธ ๊ถ์ฅํฉ๋๋ค.
///
## ๋ ์์๋ณด๊ธฐ { #learn-more }
-<a href="https://graphql.org/" class="external-link" target="_blank">๊ณต์ GraphQL ๋ฌธ์</a>์์ **GraphQL**์ ๋ํด ๋ ์์๋ณผ ์ ์์ต๋๋ค.
+[๊ณต์ GraphQL ๋ฌธ์](https://graphql.org/)์์ **GraphQL**์ ๋ํด ๋ ์์๋ณผ ์ ์์ต๋๋ค.
๋ํ ์์์ ์ค๋ช
ํ ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด์๋ ํด๋น ๋งํฌ์์ ๋ ์์ธํ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
/// tip | ํ
-**FastAPI๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ํ์ต**ํ๊ณ ์ถ๋ค๋ฉด(๊ถ์ฅ), ๋์ [ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋](../tutorial/index.md){.internal-link target=_blank}๋ฅผ ์ฅ๋ณ๋ก ์ฝ์ด๋ณด์ธ์.
+**FastAPI๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ํ์ต**ํ๊ณ ์ถ๋ค๋ฉด(๊ถ์ฅ), ๋์ [ํํ ๋ฆฌ์ผ - ์ฌ์ฉ์ ๊ฐ์ด๋](../tutorial/index.md)๋ฅผ ์ฅ๋ณ๋ก ์ฝ์ด๋ณด์ธ์.
///
/// warning | ๊ฒฝ๊ณ
-Pydantic ํ์ **Python 3.14**๋ถํฐ ์ต์ Python ๋ฒ์ ์์ Pydantic v1 ์ง์์ ์ค๋จํ์ต๋๋ค.
+Pydantic ํ์ ์ต์ Python ๋ฒ์ ์์ Pydantic v1 ์ง์์ ์ค๋จํ์ผ๋ฉฐ, ์์ ๋ฒ์ ์ **Python 3.14**์
๋๋ค.
์ฌ๊ธฐ์๋ `pydantic.v1`๋ ํฌํจ๋๋ฉฐ, Python 3.14 ์ด์์์๋ ๋ ์ด์ ์ง์๋์ง ์์ต๋๋ค.
## ๊ณต์ ๊ฐ์ด๋ { #official-guide }
-Pydantic์๋ v1์์ v2๋ก์ ๊ณต์ <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">๋ง์ด๊ทธ๋ ์ด์
๊ฐ์ด๋</a>๊ฐ ์์ต๋๋ค.
+Pydantic์๋ v1์์ v2๋ก์ ๊ณต์ [๋ง์ด๊ทธ๋ ์ด์
๊ฐ์ด๋](https://docs.pydantic.dev/latest/migration/)๊ฐ ์์ต๋๋ค.
์ฌ๊ธฐ์๋ ๋ฌด์์ด ๋ฐ๋์๋์ง, ๊ฒ์ฆ์ด ์ด์ ์ด๋ป๊ฒ ๋ ์ ํํ๊ณ ์๊ฒฉํด์ก๋์ง, ๊ฐ๋ฅํ ์ฃผ์์ฌํญ ๋ฑ๋ ํฌํจ๋์ด ์์ต๋๋ค.
## ํ
์คํธ { #tests }
-์ฑ์ ๋ํ [ํ
์คํธ](../tutorial/testing.md){.internal-link target=_blank}๊ฐ ์๋์ง ํ์ธํ๊ณ , ์ง์์ ํตํฉ(CI)์์ ํ
์คํธ๋ฅผ ์คํํ์ธ์.
+์ฑ์ ๋ํ [ํ
์คํธ](../tutorial/testing.md)๊ฐ ์๋์ง ํ์ธํ๊ณ , ์ง์์ ํตํฉ(CI)์์ ํ
์คํธ๋ฅผ ์คํํ์ธ์.
์ด๋ ๊ฒ ํ๋ฉด ์
๊ทธ๋ ์ด๋๋ฅผ ์งํํ๋ฉด์๋ ๋ชจ๋ ๊ฒ์ด ๊ธฐ๋ํ ๋๋ก ๊ณ์ ๋์ํ๋์ง ํ์ธํ ์ ์์ต๋๋ค.
๋ง์ ๊ฒฝ์ฐ, ์ปค์คํฐ๋ง์ด์ง ์์ด ์ผ๋ฐ์ ์ธ Pydantic ๋ชจ๋ธ์ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด Pydantic v1์์ Pydantic v2๋ก์ ๋ง์ด๊ทธ๋ ์ด์
๊ณผ์ ๋๋ถ๋ถ์ ์๋ํํ ์ ์์ต๋๋ค.
-๊ฐ์ Pydantic ํ์ด ์ ๊ณตํ๋ <a href="https://github.com/pydantic/bump-pydantic" class="external-link" target="_blank">`bump-pydantic`</a>๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+๊ฐ์ Pydantic ํ์ด ์ ๊ณตํ๋ [`bump-pydantic`](https://github.com/pydantic/bump-pydantic)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ๋๊ตฌ๋ ๋ณ๊ฒฝํด์ผ ํ๋ ์ฝ๋์ ๋๋ถ๋ถ์ ์๋์ผ๋ก ๋ฐ๊พธ๋ ๋ฐ ๋์์ ์ค๋๋ค.
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์คํธํ๊ธฐ { #testing-a-database }
-๋ฐ์ดํฐ๋ฒ ์ด์ค, SQL, SQLModel์ ๋ํด์๋ <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel ๋ฌธ์</a>์์ ํ์ตํ ์ ์์ต๋๋ค. ๐ค
+๋ฐ์ดํฐ๋ฒ ์ด์ค, SQL, SQLModel์ ๋ํด์๋ [SQLModel ๋ฌธ์](https://sqlmodel.tiangolo.com/)์์ ํ์ตํ ์ ์์ต๋๋ค. ๐ค
-<a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">FastAPI์์ SQLModel์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ฏธ๋ ํํ ๋ฆฌ์ผ</a>๋ ์์ต๋๋ค. โจ
+[FastAPI์์ SQLModel์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ฏธ๋ ํํ ๋ฆฌ์ผ](https://sqlmodel.tiangolo.com/tutorial/fastapi/)๋ ์์ต๋๋ค. โจ
-ํด๋น ํํ ๋ฆฌ์ผ์๋ <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/" class="external-link" target="_blank">SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์คํธ</a>์ ๋ํ ์น์
๋ ํฌํจ๋์ด ์์ต๋๋ค. ๐
+ํด๋น ํํ ๋ฆฌ์ผ์๋ [SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์คํธ](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/)์ ๋ํ ์น์
๋ ํฌํจ๋์ด ์์ต๋๋ค. ๐
<em>FastAPI ํ๋ ์์ํฌ, ๊ณ ์ฑ๋ฅ, ๊ฐํธํ ํ์ต, ๋น ๋ฅธ ์ฝ๋ ์์ฑ, ์ค๋น๋ ํ๋ก๋์
</em>
</p>
<p align="center">
-<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
+<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
-<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
+<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
-<a href="https://pypi.org/project/fastapi" target="_blank">
+<a href="https://pypi.org/project/fastapi">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
-<a href="https://pypi.org/project/fastapi" target="_blank">
+<a href="https://pypi.org/project/fastapi">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
-**๋ฌธ์**: <a href="https://fastapi.tiangolo.com/ko" target="_blank">https://fastapi.tiangolo.com</a>
+**๋ฌธ์**: [https://fastapi.tiangolo.com/ko](https://fastapi.tiangolo.com/ko)
-**์์ค ์ฝ๋**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
+**์์ค ์ฝ๋**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)
---
* **์ฌ์**: ์ฝ๊ฒ ์ฌ์ฉํ๊ณ ๋ฐฐ์ฐ๋๋ก ์ค๊ณ. ์ ์ ๋ฌธ์ ์ฝ๊ธฐ ์๊ฐ.
* **์งง์**: ์ฝ๋ ์ค๋ณต ์ต์ํ. ๊ฐ ๋งค๊ฐ๋ณ์ ์ ์ธ์ ์ฌ๋ฌ ๊ธฐ๋ฅ. ์ ์ ๋ฒ๊ทธ.
* **๊ฒฌ๊ณ ํจ**: ์ค๋น๋ ํ๋ก๋์
์ฉ ์ฝ๋๋ฅผ ์ป์ผ์ญ์์ค. ์๋ ๋ํํ ๋ฌธ์์ ํจ๊ป.
-* **ํ์ค ๊ธฐ๋ฐ**: API์ ๋ํ (์์ ํ ํธํ๋๋) ๊ฐ๋ฐฉํ ํ์ค ๊ธฐ๋ฐ: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (์ด์ ์ Swagger๋ก ์๋ ค์ก๋) ๋ฐ <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
+* **ํ์ค ๊ธฐ๋ฐ**: API์ ๋ํ (์์ ํ ํธํ๋๋) ๊ฐ๋ฐฉํ ํ์ค ๊ธฐ๋ฐ: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (์ด์ ์ Swagger๋ก ์๋ ค์ก๋) ๋ฐ [JSON Schema](https://json-schema.org/).
<small>* ๋ด๋ถ ๊ฐ๋ฐํ์ ํ๋ก๋์
์ ํ๋ฆฌ์ผ์ด์
์ ๋น๋ํ ํ
์คํธ์ ๊ทผ๊ฑฐํ ์ธก์ </small>
### ํค์คํค ์คํฐ์ { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%}
-<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
+<a href="{{ sponsor.url }}" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
### ๊ณจ๋ ๋ฐ ์ค๋ฒ ์คํฐ์ { #gold-and-silver-sponsors }
{% for sponsor in sponsors.gold -%}
-<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
+<a href="{{ sponsor.url }}" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
-<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
+<a href="{{ sponsor.url }}" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
<!-- /sponsors -->
-<a href="https://fastapi.tiangolo.com/ko/fastapi-people/#sponsors" class="external-link" target="_blank">๋ค๋ฅธ ์คํฐ์</a>
+[๋ค๋ฅธ ์คํฐ์](https://fastapi.tiangolo.com/ko/fastapi-people/#sponsors)
## ์๊ฒฌ๋ค { #opinions }
"_[...] ์ ๋ ์์ฆ **FastAPI**๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ณ ์์ต๋๋ค. [...] ์ฌ์ค ์ฐ๋ฆฌ ํ์ **๋ง์ดํฌ๋ก์ํํธ ML ์๋น์ค** ์ ๋ถ๋ฅผ ๋ฐ๊ฟ ๊ณํ์
๋๋ค. ๊ทธ์ค ์ผ๋ถ๋ ํต์ฌ **Windows**์ ๋ช๋ช์ **Office** ์ ํ๋ค์ด ํตํฉ๋๊ณ ์์ต๋๋ค._"
-<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>๋ง์ดํฌ๋ก์ํํธ</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>๋ง์ดํฌ๋ก์ํํธ</strong> <a href="https://github.com/fastapi/fastapi/pull/26"><small>(ref)</small></a></div>
---
"_**FastAPI** ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฑํํ์ฌ **์์ธก**์ ์ป๊ธฐ ์ํด ์ฟผ๋ฆฌ๋ฅผ ์คํ ํ ์ ์๋ **REST** ์๋ฒ๋ฅผ ์์ฑํ์ต๋๋ค. [Ludwig์ ์ํด]_"
-<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin ๊ทธ๋ฆฌ๊ณ Sai Sumanth Miryala - <strong>์ฐ๋ฒ</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin ๊ทธ๋ฆฌ๊ณ Sai Sumanth Miryala - <strong>์ฐ๋ฒ</strong> <a href="https://eng.uber.com/ludwig-v0-2/"><small>(ref)</small></a></div>
---
"_**Netflix**๋ ์ฐ๋ฆฌ์ ์คํ ์์ค ๋ฐฐํฌํ์ธ **์๊ธฐ ๊ด๋ฆฌ** ์ค์ผ์คํธ๋ ์ด์
ํ๋ ์์ํฌ๋ฅผ ๋ฐํํ ์ ์์ด ๊ธฐ์ฉ๋๋ค: ๋ฐ๋ก **Dispatch**์
๋๋ค! [**FastAPI**๋ก ๋น๋]_"
-<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>๋ทํ๋ฆญ์ค</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>๋ทํ๋ฆญ์ค</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072"><small>(ref)</small></a></div>
---
"_**FastAPI**๊ฐ ๋๋ฌด ์ข์์ ๊ตฌ๋ฆ ์๋ฅผ ๊ฑท๋๋ฏ ํฉ๋๋ค. ์ ๋ง ์ฆ๊ฒ์ต๋๋ค!_"
-<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> ํ์บ์คํธ ํธ์คํธ</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong>[Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832"><small>(ref)</small></a></div>
---
"_์์งํ, ๋น์ ์ด ๋ง๋ ๊ฒ์ ๋งค์ฐ ๊ฒฌ๊ณ ํ๊ณ ์ธ๋ จ๋์ด ๋ณด์
๋๋ค. ์ฌ๋ฌ ๋ฉด์์ **Hug**๊ฐ ์ด๋ ๊ฒ ๋์์ผ๋ฉด ํฉ๋๋ค - ๊ทธ๊ฑธ ๋ง๋ ๋๊ตฐ๊ฐ๋ฅผ ๋ณด๋ ๊ฒ์ ๋ง์ ์๊ฐ์ ์ค๋๋ค._"
-<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> ์ ์์</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>[Hug](https://github.com/hugapi/hug) ์ ์์</strong> <a href="https://news.ycombinator.com/item?id=19455465"><small>(ref)</small></a></div>
---
"_์ฐ๋ฆฌ **API**๋ฅผ **FastAPI**๋ก ๋ฐ๊ฟจ์ต๋๋ค [...] ์๋ง ์ฌ๋ฌ๋ถ๋ ์ข์ํ์ค ๊ฒ์
๋๋ค [...]_"
-<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> ์ค๋ฆฝ์ - <a href="https://spacy.io" target="_blank">spaCy</a> ์ ์์</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong>[Explosion AI](https://explosion.ai) ์ค๋ฆฝ์ - [spaCy](https://spacy.io) ์ ์์</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680"><small>(ref)</small></a></div>
---
"_ํ๋ก๋์
Python API๋ฅผ ๋ง๋ค๊ณ ์ ํ๋ค๋ฉด, ์ ๋ **FastAPI**๋ฅผ ๊ฐ๋ ฅํ ์ถ์ฒํฉ๋๋ค. **์๋ฆ๋ต๊ฒ ์ค๊ณ**๋์๊ณ , **์ฌ์ฉ์ด ๊ฐ๋จ**ํ๋ฉฐ, **ํ์ฅ์ฑ์ด ๋งค์ฐ ๋ฐ์ด๋**๊ณ , ์ฐ๋ฆฌ์ API ์ฐ์ ๊ฐ๋ฐ ์ ๋ต์์ **ํต์ฌ ๊ตฌ์ฑ ์์**๊ฐ ๋์์ผ๋ฉฐ Virtual TAC Engineer ๊ฐ์ ๋ง์ ์๋ํ์ ์๋น์ค๋ฅผ ์ด๋๊ณ ์์ต๋๋ค._"
-<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
+<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/"><small>(ref)</small></a></div>
---
## FastAPI ๋ฏธ๋ ๋คํ๋ฉํฐ๋ฆฌ { #fastapi-mini-documentary }
-2025๋
๋ง์ ๊ณต๊ฐ๋ <a href="https://www.youtube.com/watch?v=mpR8ngthqiE" class="external-link" target="_blank">FastAPI ๋ฏธ๋ ๋คํ๋ฉํฐ๋ฆฌ</a>๊ฐ ์์ต๋๋ค. ์จ๋ผ์ธ์์ ์์ฒญํ ์ ์์ต๋๋ค:
+2025๋
๋ง์ ๊ณต๊ฐ๋ [FastAPI ๋ฏธ๋ ๋คํ๋ฉํฐ๋ฆฌ](https://www.youtube.com/watch?v=mpR8ngthqiE)๊ฐ ์์ต๋๋ค. ์จ๋ผ์ธ์์ ์์ฒญํ ์ ์์ต๋๋ค:
-<a href="https://www.youtube.com/watch?v=mpR8ngthqiE" target="_blank"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
+<a href="https://www.youtube.com/watch?v=mpR8ngthqiE"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
## **Typer**, CLI๋ฅผ ์ํ FastAPI { #typer-the-fastapi-of-clis }
-<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>
+<a href="https://typer.tiangolo.com"><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> ์ฑ์ ๋ง๋ค๊ณ ์๋ค๋ฉด, [**Typer**](https://typer.tiangolo.com/)๋ฅผ ํ์ธํด ๋ณด์ญ์์ค.
**Typer**๋ FastAPI์ ๋์์
๋๋ค. ๊ทธ๋ฆฌ๊ณ **CLI๋ฅผ ์ํ FastAPI**๊ฐ ๋๊ธฐ ์ํด ์๊ฒผ์ต๋๋ค. โจ๏ธ ๐
FastAPI๋ ๊ฑฐ์ธ๋ค์ ์ด๊นจ ์์ ์ ์์ต๋๋ค:
-* ์น ๋ถ๋ถ์ ์ํ <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a>.
-* ๋ฐ์ดํฐ ๋ถ๋ถ์ ์ํ <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>.
+* [Starlette](https://www.starlette.dev/) โ ์น ๋ถ๋ถ์ ๋ด๋นํฉ๋๋ค.
+* [Pydantic](https://docs.pydantic.dev/) โ ๋ฐ์ดํฐ ๋ถ๋ถ์ ๋ด๋นํฉ๋๋ค.
## ์ค์น { #installation }
-<a href="https://fastapi.tiangolo.com/ko/virtual-environments/" class="external-link" target="_blank">๊ฐ์ ํ๊ฒฝ</a>์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์ FastAPI๋ฅผ ์ค์นํ์ธ์:
+[๊ฐ์ ํ๊ฒฝ](https://fastapi.tiangolo.com/ko/virtual-environments/)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์ FastAPI๋ฅผ ์ค์นํ์ธ์:
<div class="termy">
**Note**:
-์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, <a href="https://fastapi.tiangolo.com/ko/async/#in-a-hurry" target="_blank">๋ฌธ์์์ `async`์ `await`</a>์ ๊ดํ _"๊ธํ์ธ์?"_ ์น์
์ ํ์ธํด ๋ณด์ญ์์ค.
+์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, ["๊ธํ์ธ์?"](https://fastapi.tiangolo.com/ko/async/#in-a-hurry) ์น์
์ ํ์ธํด ๋ณด์ญ์์ค.
</details>
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
โญโโโโโโโโโโ FastAPI CLI - Development mode โโโโโโโโโโโโฎ
โ โ
</div>
<details markdown="1">
-<summary><code>fastapi dev main.py</code> ๋ช
๋ น์ ๊ดํ์ฌ...</summary>
+<summary><code>fastapi dev</code> ๋ช
๋ น์ ๊ดํ์ฌ...</summary>
-`fastapi dev` ๋ช
๋ น์ `main.py` ํ์ผ์ ์ฝ๊ณ , ๊ทธ ์์ **FastAPI** ์ฑ์ ๊ฐ์งํ ๋ค์, <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>์ ์ฌ์ฉํด ์๋ฒ๋ฅผ ์์ํฉ๋๋ค.
+`fastapi dev` ๋ช
๋ น์ ์ฌ๋ฌ๋ถ์ `main.py` ํ์ผ์ ์๋์ผ๋ก ์ฝ๊ณ , ๊ทธ ์์ **FastAPI** ์ฑ์ ๊ฐ์งํ ๋ค์, [Uvicorn](https://www.uvicorn.dev)์ ์ฌ์ฉํด ์๋ฒ๋ฅผ ์์ํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก `fastapi dev`๋ ๋ก์ปฌ ๊ฐ๋ฐ์ ์ํด auto-reload๊ฐ ํ์ฑํ๋ ์ํ๋ก ์์๋ฉ๋๋ค.
-์์ธํ ๋ด์ฉ์ <a href="https://fastapi.tiangolo.com/ko/fastapi-cli/" target="_blank">FastAPI CLI ๋ฌธ์</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+์์ธํ ๋ด์ฉ์ [FastAPI CLI ๋ฌธ์](https://fastapi.tiangolo.com/ko/fastapi-cli/)์์ ํ์ธํ ์ ์์ต๋๋ค.
</details>
### ํ์ธํ๊ธฐ { #check-it }
-๋ธ๋ผ์ฐ์ ๋ก <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>๋ฅผ ์ด์ด๋ณด์ญ์์ค.
+๋ธ๋ผ์ฐ์ ๋ก [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery)๋ฅผ ์ด์ด๋ณด์ญ์์ค.
์๋์ JSON ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
### ๋ํํ API ๋ฌธ์ { #interactive-api-docs }
-์ด์ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ก ๊ฐ๋ณด์ญ์์ค.
+์ด์ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ก ๊ฐ๋ณด์ญ์์ค.
-์๋ ๋ํํ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค (<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> ์ ๊ณต):
+์๋ ๋ํํ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค ([Swagger UI](https://github.com/swagger-api/swagger-ui) ์ ๊ณต):

### ๋์ API ๋ฌธ์ { #alternative-api-docs }
-๊ทธ๋ฆฌ๊ณ ์ด์ <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>๋ก ๊ฐ๋ด
์๋ค.
+๊ทธ๋ฆฌ๊ณ ์ด์ [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)๋ก ๊ฐ๋ด
์๋ค.
-๋ค๋ฅธ ์๋ ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค(<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> ์ ๊ณต):
+๋ค๋ฅธ ์๋ ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค([ReDoc](https://github.com/Rebilly/ReDoc) ์ ๊ณต):

### ๋ํํ API ๋ฌธ์ ์
๊ทธ๋ ์ด๋ { #interactive-api-docs-upgrade }
-์ด์ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ก ์ด๋ํฉ๋๋ค.
+์ด์ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ก ์ด๋ํฉ๋๋ค.
* ๋ํํ API ๋ฌธ์๋ ์ ๋ณธ๋ฌธ์ ํฌํจํด ์๋์ผ๋ก ์
๋ฐ์ดํธ๋ฉ๋๋ค:
### ๋์ API ๋ฌธ์ ์
๊ทธ๋ ์ด๋ { #alternative-api-docs-upgrade }
-๊ทธ๋ฆฌ๊ณ ์ด์ , <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>๋ก ์ด๋ํฉ๋๋ค.
+๊ทธ๋ฆฌ๊ณ ์ด์ , [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)๋ก ์ด๋ํฉ๋๋ค.
* ๋์ ๋ฌธ์ ์ญ์ ์ ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ ๋ณธ๋ฌธ์ ๋ฐ์ํฉ๋๋ค:
* ๊ฐ๋ ฅํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด **<dfn title="๋ค๋ฅธ ๋ง๋ก๋: ์ปดํฌ๋ํธ, ๋ฆฌ์์ค, ํ๋ก๋ฐ์ด๋, ์๋น์ค, ์ธ์ ํฐ๋ธ">์์กด์ฑ ์ฃผ์
</dfn>** ์์คํ
.
* **OAuth2** ์ง์์ ํฌํจํ **JWT tokens** ๋ฐ **HTTP Basic**์ ๊ฐ๋ ๋ณด์๊ณผ ์ธ์ฆ.
* (Pydantic ๋๋ถ์) **๊น์ ์ค์ฒฉ JSON ๋ชจ๋ธ**์ ์ ์ธํ๋๋ฐ ๋ ์ง๋ณดํ (ํ์ง๋ง ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ด) ๊ธฐ์ .
-* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> ๋ฐ ๊ธฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ **GraphQL** ํตํฉ.
+* [Strawberry](https://strawberry.rocks) ๋ฐ ๊ธฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ **GraphQL** ํตํฉ.
* (Starlette ๋๋ถ์) ๋ง์ ์ถ๊ฐ ๊ธฐ๋ฅ:
* **์น ์์ผ**
* HTTPX ๋ฐ `pytest`์ ๊ธฐ๋ฐํ ๊ทนํ ์ฌ์ด ํ
์คํธ
### ์ฑ ๋ฐฐํฌํ๊ธฐ(์ ํ ์ฌํญ) { #deploy-your-app-optional }
-์ ํ์ ์ผ๋ก FastAPI ์ฑ์ <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง์ด๋ผ๋ฉด ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํด ๋ณด์ธ์. ๐
+์ ํ์ ์ผ๋ก FastAPI ์ฑ์ [FastAPI Cloud](https://fastapicloud.com)์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง์ด๋ผ๋ฉด ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํด ๋ณด์ธ์. ๐
์ด๋ฏธ **FastAPI Cloud** ๊ณ์ ์ด ์๋ค๋ฉด(๋๊ธฐ์ ๋ช
๋จ์์ ์ด๋ํด ๋๋ ธ์ต๋๋ค ๐), ํ ๋ฒ์ ๋ช
๋ น์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
-๋ฐฐํฌํ๊ธฐ ์ ์, ๋ก๊ทธ์ธ๋์ด ์๋์ง ํ์ธํ์ธ์:
-
-<div class="termy">
-
-```console
-$ fastapi login
-
-You are logged in to FastAPI Cloud ๐
-```
-
-</div>
-
-๊ทธ๋ฐ ๋ค์ ์ฑ์ ๋ฐฐํฌํ์ธ์:
-
<div class="termy">
```console
#### FastAPI Cloud ์๊ฐ { #about-fastapi-cloud }
-**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**๋ **FastAPI** ๋ค์ ์๋ ๋์ผํ ์์ฑ์์ ํ์ด ๋ง๋ค์์ต๋๋ค.
+**[FastAPI Cloud](https://fastapicloud.com)**๋ **FastAPI** ๋ค์ ์๋ ๋์ผํ ์์ฑ์์ ํ์ด ๋ง๋ค์์ต๋๋ค.
์ต์ํ์ ๋
ธ๋ ฅ์ผ๋ก API๋ฅผ **๋น๋**, **๋ฐฐํฌ**, **์ ๊ทผ**ํ๋ ๊ณผ์ ์ ๊ฐ์ํํฉ๋๋ค.
## ์ฑ๋ฅ { #performance }
-๋
๋ฆฝ๋ TechEmpower ๋ฒค์น๋งํฌ์์ Uvicorn์์ ์๋ํ๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ด <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋</a>๋ก Starlette์ Uvicorn(FastAPI์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ)์๋ง ๋ฐ๋๊ณ ์์ต๋๋ค. (*)
+๋
๋ฆฝ๋ TechEmpower ๋ฒค์น๋งํฌ์์ Uvicorn์์ ์๋ํ๋ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ด [์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฅ ๋น ๋ฅธ Python ํ๋ ์์ํฌ ์ค ํ๋](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7)๋ก Starlette์ Uvicorn(FastAPI์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ)์๋ง ๋ฐ๋๊ณ ์์ต๋๋ค. (*)
-์์ธํ ๋ด์ฉ์ <a href="https://fastapi.tiangolo.com/ko/benchmarks/" class="internal-link" target="_blank">๋ฒค์น๋งํฌ</a> ์น์
์ ๋ณด์ญ์์ค.
+์์ธํ ๋ด์ฉ์ [๋ฒค์น๋งํฌ](https://fastapi.tiangolo.com/ko/benchmarks/) ์น์
์ ๋ณด์ญ์์ค.
## ์์กด์ฑ { #dependencies }
### `standard` ์์กด์ฑ { #standard-dependencies }
-FastAPI๋ฅผ `pip install "fastapi[standard]"`๋ก ์ค์นํ๋ฉด `standard` ๊ทธ๋ฃน์ ์ ํ์ ์์กด์ฑ์ด ํจ๊ป ์ค์น๋ฉ๋๋ค.
+`pip install "fastapi[standard]"`๋ก FastAPI๋ฅผ ์ค์นํ๋ฉด `standard` ๊ทธ๋ฃน์ ์ ํ์ ์์กด์ฑ์ด ํจ๊ป ์ค์น๋ฉ๋๋ค.
Pydantic์ด ์ฌ์ฉํ๋:
-* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฌ.
+* [`email-validator`](https://github.com/JoshData/python-email-validator) - ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฌ.
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 <dfn title="HTTP ์์ฒญ์์ ์จ ๋ฌธ์์ด์ ํ์ด์ฌ ๋ฐ์ดํฐ๋ก ๋ณํ">"ํ์ฑ"</dfn> ์ง์์ ์ํ๋ฉด ํ์.
+* [`httpx`](https://www.python-httpx.org) - `TestClient`๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
+* [`jinja2`](https://jinja.palletsprojects.com) - ๊ธฐ๋ณธ ํ
ํ๋ฆฟ ์ค์ ์ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
+* [`python-multipart`](https://github.com/Kludex/python-multipart) - `request.form()`๊ณผ ํจ๊ป form <dfn title="HTTP ์์ฒญ์์ ์จ ๋ฌธ์์ด์ ํ์ด์ฌ ๋ฐ์ดํฐ๋ก ๋ณํ">"ํ์ฑ"</dfn> ์ง์์ ์ํ๋ฉด ํ์.
FastAPI๊ฐ ์ฌ์ฉํ๋:
-* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - ์ ํ๋ฆฌ์ผ์ด์
์ ๋ก๋ํ๊ณ ์ ๊ณตํ๋ ์๋ฒ๋ฅผ ์ํ ๊ฒ์
๋๋ค. ์ฌ๊ธฐ์๋ ๊ณ ์ฑ๋ฅ ์๋น์ ํ์ํ ์ผ๋ถ ์์กด์ฑ(์: `uvloop`)์ด ํฌํจ๋ `uvicorn[standard]`๊ฐ ํฌํจ๋ฉ๋๋ค.
+* [`uvicorn`](https://www.uvicorn.dev) - ์ ํ๋ฆฌ์ผ์ด์
์ ๋ก๋ํ๊ณ ์ ๊ณตํ๋ ์๋ฒ๋ฅผ ์ํ ๊ฒ์
๋๋ค. ์ฌ๊ธฐ์๋ ๊ณ ์ฑ๋ฅ ์๋น์ ํ์ํ ์ผ๋ถ ์์กด์ฑ(์: `uvloop`)์ด ํฌํจ๋ `uvicorn[standard]`๊ฐ ํฌํจ๋ฉ๋๋ค.
* `fastapi-cli[standard]` - `fastapi` ๋ช
๋ น์ ์ ๊ณตํ๊ธฐ ์ํ ๊ฒ์
๋๋ค.
- * ์ฌ๊ธฐ์๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์ ๋ฐฐํฌํ ์ ์๊ฒ ํด์ฃผ๋ `fastapi-cloud-cli`๊ฐ ํฌํจ๋ฉ๋๋ค.
+ * ์ฌ๊ธฐ์๋ [FastAPI Cloud](https://fastapicloud.com)์ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ์ ์๊ฒ ํด์ฃผ๋ `fastapi-cloud-cli`๊ฐ ํฌํจ๋ฉ๋๋ค.
### `standard` ์์กด์ฑ ์์ด { #without-standard-dependencies }
์ถ๊ฐ ์ ํ์ Pydantic ์์กด์ฑ:
-* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - ์ค์ ๊ด๋ฆฌ๋ฅผ ์ํ ๊ฒ์
๋๋ค.
-* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - Pydantic์์ ์ฌ์ฉํ ์ถ๊ฐ ํ์
์ ์ํ ๊ฒ์
๋๋ค.
+* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - ์ค์ ๊ด๋ฆฌ๋ฅผ ์ํ ๊ฒ์
๋๋ค.
+* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - Pydantic์์ ์ฌ์ฉํ ์ถ๊ฐ ํ์
์ ์ํ ๊ฒ์
๋๋ค.
์ถ๊ฐ ์ ํ์ FastAPI ์์กด์ฑ:
-* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - `ORJSONResponse`๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
-* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - `UJSONResponse`๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
+* [`orjson`](https://github.com/ijl/orjson) - `ORJSONResponse`๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
+* [`ujson`](https://github.com/esnme/ultrajson) - `UJSONResponse`๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํ์.
## ๋ผ์ด์ผ์ค { #license }
๋ง์ ์ด๊ธฐ ์ค์ , ๋ณด์, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐ ์ผ๋ถ API ์๋ํฌ์ธํธ๊ฐ ์ด๋ฏธ ์ค๋น๋์ด ์์ผ๋ฏ๋ก, ์ฌ๋ฌ๋ถ์ ์ด ํ
ํ๋ฆฟ์ ์์ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-GitHub ์ ์ฅ์: <a href="https://github.com/tiangolo/full-stack-fastapi-template" class="external-link" target="_blank">Full Stack FastAPI ํ
ํ๋ฆฟ</a>
+GitHub ์ ์ฅ์: [Full Stack FastAPI ํ
ํ๋ฆฟ](https://github.com/tiangolo/full-stack-fastapi-template)
## Full Stack FastAPI ํ
ํ๋ฆฟ - ๊ธฐ์ ์คํ๊ณผ ๊ธฐ๋ฅ๋ค { #full-stack-fastapi-template-technology-stack-and-features }
## Pydantic ๋ชจ๋ธ { #pydantic-models }
-<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>์ ๋ฐ์ดํฐ ๊ฒ์ฆ์ ์ํํ๋ ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
+[Pydantic](https://docs.pydantic.dev/)์ ๋ฐ์ดํฐ ๊ฒ์ฆ์ ์ํํ๋ ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
์์ฑ์ ๊ฐ์ง ํด๋์ค ํํ๋ก ๋ฐ์ดํฐ์ "๋ชจ์(shape)"์ ์ ์ธํฉ๋๋ค.
/// info | ์ ๋ณด
-<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด ๋ฌธ์๋ฅผ ํ์ธํ์ธ์</a>.
+Pydantic์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด [๋ฌธ์๋ฅผ ํ์ธํ์ธ์](https://docs.pydantic.dev/).
///
**FastAPI**๋ ๋ชจ๋ Pydantic์ ๊ธฐ๋ฐ์ ๋๊ณ ์์ต๋๋ค.
-์ด ๋ชจ๋ ๊ฒ์ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](tutorial/index.md){.internal-link target=_blank}์์ ์ค์ ๋ก ๋ง์ด ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค.
+์ด ๋ชจ๋ ๊ฒ์ [์์ต์ - ์ฌ์ฉ์ ์๋ด์](tutorial/index.md)์์ ์ค์ ๋ก ๋ง์ด ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค.
## ๋ฉํ๋ฐ์ดํฐ ์ ๋ํ
์ด์
์ด ์๋ ํ์
ํํธ { #type-hints-with-metadata-annotations }
* OpenAPI๋ฅผ ์ฌ์ฉํด API๋ฅผ **๋ฌธ์ํ**:
* ์๋ ์ํธ์์ฉ ๋ฌธ์ UI์์ ์ฌ์ฉ๋ฉ๋๋ค.
-์ด ๋ชจ๋ ๊ฒ์ด ๋ค์ ์ถ์์ ์ผ๋ก ๋ค๋ฆด ์๋ ์์ต๋๋ค. ๊ฑฑ์ ํ์ง ๋ง์ธ์. [์์ต์ - ์ฌ์ฉ์ ์๋ด์](tutorial/index.md){.internal-link target=_blank}์์ ์ค์ ๋ก ํ์ธํ๊ฒ ๋ ๊ฒ์
๋๋ค.
+์ด ๋ชจ๋ ๊ฒ์ด ๋ค์ ์ถ์์ ์ผ๋ก ๋ค๋ฆด ์๋ ์์ต๋๋ค. ๊ฑฑ์ ํ์ง ๋ง์ธ์. [์์ต์ - ์ฌ์ฉ์ ์๋ด์](tutorial/index.md)์์ ์ค์ ๋ก ํ์ธํ๊ฒ ๋ ๊ฒ์
๋๋ค.
๊ฐ์ฅ ์ค์ํ ์ ์ ํ์ค ํ์ด์ฌ ํ์
์ ํ ๊ณณ์์ ์ฌ์ฉํจ์ผ๋ก์จ(๋ ๋ง์ ํด๋์ค, ๋ฐ์ฝ๋ ์ดํฐ ๋ฑ์ ์ถ๊ฐํ๋ ๋์ ) **FastAPI**๊ฐ ์ฌ๋ฌ๋ถ์ ์ํด ๋ง์ ์ผ์ ํด์ค๋ค๋ ์ฌ์ค์
๋๋ค.
/// info | ์ ๋ณด
-์์ต์๋ฅผ ๋ชจ๋ ๋๋ด๊ณ ํ์
์ ๋ํด ๋ ์์๋ณด๊ธฐ ์ํด ๋ค์ ๋์์๋ค๋ฉด, ์ข์ ์๋ฃ๋ก <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">`mypy`์ "cheat sheet"</a>๊ฐ ์์ต๋๋ค.
+์์ต์๋ฅผ ๋ชจ๋ ๋๋ด๊ณ ํ์
์ ๋ํด ๋ ์์๋ณด๊ธฐ ์ํด ๋ค์ ๋์์๋ค๋ฉด, ์ข์ ์๋ฃ๋ก [`mypy`์ "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)๊ฐ ์์ต๋๋ค.
///
## ๊ธฐ์ ์ ์ธ๋ถ์ฌํญ { #technical-details }
-`BackgroundTasks` ํด๋์ค๋ <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">`starlette.background`</a>์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค.
+`BackgroundTasks` ํด๋์ค๋ [`starlette.background`](https://www.starlette.dev/background/)์์ ์ง์ ๊ฐ์ ธ์ต๋๋ค.
FastAPI์ ์ง์ ์ํฌํธ/ํฌํจ๋์ด ์์ผ๋ฏ๋ก `fastapi`์์ ์ํฌํธํ ์ ์๊ณ , ์ค์๋ก `starlette.background`์์ ๋์์ธ `BackgroundTask`(๋์ `s`๊ฐ ์์)๋ฅผ ์ํฌํธํ๋ ๊ฒ์ ํผํ ์ ์์ต๋๋ค.
FastAPI์์ `BackgroundTask`๋ง ๋จ๋
์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํ์ง๋ง, ์ฝ๋์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ํฌํจํ๋ Starlette `Response`๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค.
-๋ ์์ธํ ๋ด์ฉ์ <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">Starlette์ Background Tasks ๊ณต์ ๋ฌธ์</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+๋ ์์ธํ ๋ด์ฉ์ [Starlette์ Background Tasks ๊ณต์ ๋ฌธ์](https://www.starlette.dev/background/)์์ ํ์ธํ ์ ์์ต๋๋ค.
## ์ฃผ์์ฌํญ { #caveat }
-๋ฌด๊ฑฐ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ๊ณ์ฐ์ ์ํํด์ผ ํ๊ณ , ๋ฐ๋์ ๋์ผํ ํ๋ก์ธ์ค์์ ์คํํ ํ์๊ฐ ์๋ค๋ฉด(์: ๋ฉ๋ชจ๋ฆฌ, ๋ณ์ ๋ฑ์ ๊ณต์ ํ ํ์๊ฐ ์์) <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a> ๊ฐ์ ๋ ํฐ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋์์ด ๋ ์ ์์ต๋๋ค.
+๋ฌด๊ฑฐ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ๊ณ์ฐ์ ์ํํด์ผ ํ๊ณ , ๋ฐ๋์ ๋์ผํ ํ๋ก์ธ์ค์์ ์คํํ ํ์๊ฐ ์๋ค๋ฉด(์: ๋ฉ๋ชจ๋ฆฌ, ๋ณ์ ๋ฑ์ ๊ณต์ ํ ํ์๊ฐ ์์) [Celery](https://docs.celeryq.dev) ๊ฐ์ ๋ ํฐ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋์์ด ๋ ์ ์์ต๋๋ค.
์ด๋ค์ RabbitMQ๋ Redis ๊ฐ์ ๋ฉ์์ง/์์
ํ ๊ด๋ฆฌ์ ๋ฑ ๋ ๋ณต์กํ ์ค์ ์ ํ์๋ก ํ๋ ๊ฒฝํฅ์ด ์์ง๋ง, ์ฌ๋ฌ ํ๋ก์ธ์ค์์, ํนํ ์ฌ๋ฌ ์๋ฒ์์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์คํํ ์ ์์ต๋๋ค.
-ํ์ง๋ง ๋์ผํ **FastAPI** ์ฑ์ ๋ณ์์ ๊ฐ์ฒด์ ์ ๊ทผํด์ผ ํ๊ฑฐ๋(๋๋ ์ด๋ฉ์ผ ์๋ฆผ ์ ์ก์ฒ๋ผ) ์์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์ํํด์ผ ํ๋ค๋ฉด, `BackgroundTasks`๋ฅผ ๊ฐ๋จํ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
+ํ์ง๋ง ๋์ผํ **FastAPI** ์ฑ์ ๋ณ์์ ๊ฐ์ฒด์ ์ ๊ทผํด์ผ ํ๊ฑฐ๋, ์์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
(์: ์ด๋ฉ์ผ ์๋ฆผ ์ ์ก)์ ์ํํด์ผ ํ๋ค๋ฉด, `BackgroundTasks`๋ฅผ ๊ฐ๋จํ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
## ์์ฝ { #recap }
์ด ์์๋ฅผ ๋จ์ํํ๊ธฐ ์ํด ์์๋ก ๋ง๋ ํค๋๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
-ํ์ง๋ง ์ค์ ์ํฉ์์๋ ํตํฉ๋ [Security ์ ํธ๋ฆฌํฐ](security/index.md){.internal-link target=_blank}๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
+ํ์ง๋ง ์ค์ ์ํฉ์์๋ ํตํฉ๋ [Security ์ ํธ๋ฆฌํฐ](security/index.md)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
///
/// tip | ํ
-[*path operation decorator์ dependencies*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์ ๋ง์ฐฌ๊ฐ์ง๋ก, *path operation function*์ ์ด๋ค ๊ฐ๋ ์ ๋ฌ๋์ง ์์ต๋๋ค.
+[*path operation decorator์ dependencies*](dependencies/dependencies-in-path-operation-decorators.md)์ ๋ง์ฐฌ๊ฐ์ง๋ก, *path operation function*์ ์ด๋ค ๊ฐ๋ ์ ๋ฌ๋์ง ์์ต๋๋ค.
///
* ๋ชจ๋ ๋ฏธ๋ฆฌ ์ ์๋ `responses`๋ฅผ ํฌํจํฉ๋๋ค.
* ์ด ๋ชจ๋ *path operations*๋ ์คํ๋๊ธฐ ์ ์ `dependencies` ๋ชฉ๋ก์ด ํ๊ฐ/์คํ๋ฉ๋๋ค.
* ํน์ *path operation*์ dependencies๋ฅผ ์ถ๊ฐ๋ก ์ ์ธํ๋ฉด **๊ทธ๊ฒ๋ค๋ ์คํ๋ฉ๋๋ค**.
- * router dependencies๊ฐ ๋จผ์ ์คํ๋๊ณ , ๊ทธ ๋ค์์ [decorator์ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, ๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ ํ๋ผ๋ฏธํฐ dependencies๊ฐ ์คํ๋ฉ๋๋ค.
- * [`scopes`๊ฐ ์๋ `Security` dependencies](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}๋ ์ถ๊ฐํ ์ ์์ต๋๋ค.
+ * router dependencies๊ฐ ๋จผ์ ์คํ๋๊ณ , ๊ทธ ๋ค์์ [decorator์ `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), ๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ ํ๋ผ๋ฏธํฐ dependencies๊ฐ ์คํ๋ฉ๋๋ค.
+ * [`scopes`๊ฐ ์๋ `Security` dependencies](../advanced/security/oauth2-scopes.md)๋ ์ถ๊ฐํ ์ ์์ต๋๋ค.
/// tip | ํ
ํ์์ฒ๋ผ `FastAPI` ํด๋์ค๋ฅผ importํ๊ณ ์์ฑํฉ๋๋ค.
-๋ํ ๊ฐ `APIRouter`์ dependencies์ ๊ฒฐํฉ๋ [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}๋ ์ ์ธํ ์ ์์ต๋๋ค:
+๋ํ ๊ฐ `APIRouter`์ dependencies์ ๊ฒฐํฉ๋ [global dependencies](dependencies/global-dependencies.md)๋ ์ ์ธํ ์ ์์ต๋๋ค:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
from app.routers import items, users
```
-Python Packages์ Modules์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">Modules์ ๋ํ Python ๊ณต์ ๋ฌธ์</a>๋ฅผ ์ฝ์ด๋ณด์ธ์.
+Python Packages์ Modules์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด [Modules์ ๋ํ Python ๊ณต์ ๋ฌธ์](https://docs.python.org/3/tutorial/modules.html)๋ฅผ ์ฝ์ด๋ณด์ธ์.
///
///
+## `pyproject.toml`์์ `entrypoint` ๊ตฌ์ฑํ๊ธฐ { #configure-the-entrypoint-in-pyproject-toml }
+
+FastAPI `app` ๊ฐ์ฒด๊ฐ `app/main.py`์ ์์ผ๋ฏ๋ก `pyproject.toml` ํ์ผ์์ `entrypoint`๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํ ์ ์์ต๋๋ค:
+
+```toml
+[tool.fastapi]
+entrypoint = "app.main:app"
+```
+
+์ด๋ ๋ค์๊ณผ ๊ฐ์ด importํ๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค:
+
+```python
+from app.main import app
+```
+
+์ด๋ ๊ฒ ํ๋ฉด `fastapi` ๋ช
๋ น์ด๊ฐ ์ฌ๋ฌ๋ถ์ ์ฑ์ด ์ด๋์ ์๋์ง ์ ์ ์์ต๋๋ค.
+
+/// Note | ์ฐธ๊ณ
+
+๋ช
๋ น์ด์ ๊ฒฝ๋ก๋ฅผ ์ง์ ์ ๋ฌํ ์๋ ์์ต๋๋ค:
+
+```console
+$ fastapi dev app/main.py
+```
+
+ํ์ง๋ง `fastapi` ๋ช
๋ น์ด๋ฅผ ์คํํ ๋๋ง๋ค ์ฌ๋ฐ๋ฅธ ๊ฒฝ๋ก๋ฅผ ๊ธฐ์ตํด ์ ๋ฌํด์ผ ํฉ๋๋ค.
+
+๋ํ [VS Code ํ์ฅ](../editor-support.md)์ด๋ [FastAPI Cloud](https://fastapicloud.com) ๊ฐ์ ๋ค๋ฅธ ๋๊ตฌ๋ค์ด ์ด๋ฅผ ์ฐพ์ง ๋ชปํ ์๋ ์์ผ๋ฏ๋ก, `pyproject.toml`์ `entrypoint`๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
+
+///
+
## ์๋ API ๋ฌธ์ ํ์ธํ๊ธฐ { #check-the-automatic-api-docs }
์ด์ ์ฑ์ ์คํํ์ธ์:
<div class="termy">
```console
-$ fastapi dev app/main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
-๊ทธ๋ฆฌ๊ณ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>์์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
+๊ทธ๋ฆฌ๊ณ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)์์ ๋ฌธ์๋ฅผ ์ฌ์ธ์.
์ฌ๋ฐ๋ฅธ ๊ฒฝ๋ก(๋ฐ prefix)์ ์ฌ๋ฐ๋ฅธ ํ๊ทธ๋ฅผ ์ฌ์ฉํด, ๋ชจ๋ submodule์ ๊ฒฝ๋ก๋ฅผ ํฌํจํ ์๋ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
`str`, `int`, `float` ๋ฑ๊ณผ ๊ฐ์ ์ผ๋ฐ์ ์ธ ๋จ์ผ ํ์
๊ณผ๋ ๋ณ๊ฐ๋ก, `str`์ ์์ํ๋ ๋ ๋ณต์กํ ๋จ์ผ ํ์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ์ต์
์ ๋ณด๋ ค๋ฉด <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydantic์ Type Overview</a>๋ฅผ ํ์ธํ์ธ์. ๋ค์ ์ฅ์์ ๋ช ๊ฐ์ง ์์ ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
+์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ์ต์
์ ๋ณด๋ ค๋ฉด [Pydantic์ Type Overview](https://docs.pydantic.dev/latest/concepts/types/)๋ฅผ ํ์ธํ์ธ์. ๋ค์ ์ฅ์์ ๋ช ๊ฐ์ง ์์ ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด `Image` ๋ชจ๋ธ์๋ `url` ํ๋๊ฐ ์์ผ๋ฏ๋ก, ์ด๋ฅผ `str` ๋์ Pydantic์ `HttpUrl` ์ธ์คํด์ค๋ก ์ ์ธํ ์ ์์ต๋๋ค:
## `PUT`์ผ๋ก ๊ต์ฒด ์
๋ฐ์ดํธํ๊ธฐ { #update-replacing-with-put }
-ํญ๋ชฉ์ ์
๋ฐ์ดํธํ๋ ค๋ฉด <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> ์์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+ํญ๋ชฉ์ ์
๋ฐ์ดํธํ๋ ค๋ฉด [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) ์์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
`jsonable_encoder`๋ฅผ ์ฌ์ฉํด ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ์ ์ฅํ ์ ์๋ ๋ฐ์ดํฐ๋ก ๋ณํํ ์ ์์ต๋๋ค(์: NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ ์). ์๋ฅผ ๋ค์ด `datetime`์ `str`๋ก ๋ณํํ๋ ๊ฒฝ์ฐ์
๋๋ค.
## `PATCH`๋ก ๋ถ๋ถ ์
๋ฐ์ดํธํ๊ธฐ { #partial-updates-with-patch }
-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> ์์
์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ *๋ถ๋ถ์ ์ผ๋ก* ์
๋ฐ์ดํธํ ์๋ ์์ต๋๋ค.
+[HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) ์์
์ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ *๋ถ๋ถ์ ์ผ๋ก* ์
๋ฐ์ดํธํ ์๋ ์์ต๋๋ค.
์ด๋ ์
๋ฐ์ดํธํ๋ ค๋ ๋ฐ์ดํฐ๋ง ๋ณด๋ด๊ณ , ๋๋จธ์ง๋ ๊ทธ๋๋ก ๋๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ฐ๋ผ์ ๋ชจ๋ ์์ฑ์ ์๋ตํ ์ ์๋ ๋ถ๋ถ ์
๋ฐ์ดํธ๋ฅผ ๋ฐ์ผ๋ ค๋ฉด, ๋ชจ๋ ์์ฑ์ด optional๋ก ํ์๋(๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ง๊ฑฐ๋ `None`์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๊ฐ์ง๋) ๋ชจ๋ธ์ด ํ์ํฉ๋๋ค.
-**์
๋ฐ์ดํธ**๋ฅผ ์ํ โ๋ชจ๋ ๊ฐ์ด optional์ธโ ๋ชจ๋ธ๊ณผ, **์์ฑ**์ ์ํ โํ์ ๊ฐ์ด ์๋โ ๋ชจ๋ธ์ ๊ตฌ๋ถํ๋ ค๋ฉด [์ถ๊ฐ ๋ชจ๋ธ](extra-models.md){.internal-link target=_blank}์ ์ค๋ช
๋ ์์ด๋์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+**์
๋ฐ์ดํธ**๋ฅผ ์ํ โ๋ชจ๋ ๊ฐ์ด optional์ธโ ๋ชจ๋ธ๊ณผ, **์์ฑ**์ ์ํ โํ์ ๊ฐ์ด ์๋โ ๋ชจ๋ธ์ ๊ตฌ๋ถํ๋ ค๋ฉด [์ถ๊ฐ ๋ชจ๋ธ](extra-models.md)์ ์ค๋ช
๋ ์์ด๋์ด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
์ฌ๋ฌ๋ถ์ API๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ **์๋ต** ๋ณธ๋ฌธ์ ๋ณด๋ด์ผ ํฉ๋๋ค. ํ์ง๋ง ํด๋ผ์ด์ธํธ๋ ํญ์ **์์ฒญ ๋ณธ๋ฌธ**์ ๋ณด๋ผ ํ์๋ ์๊ณ , ๋๋ก๋ (์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ ํจ๊ป) ์ด๋ค ๊ฒฝ๋ก๋ง ์์ฒญํ๊ณ ๋ณธ๋ฌธ์ ๋ณด๋ด์ง ์์ ์๋ ์์ต๋๋ค.
-**์์ฒญ** ๋ณธ๋ฌธ์ ์ ์ธํ๊ธฐ ์ํด์ ๋ชจ๋ ๊ฐ๋ ฅํจ๊ณผ ์ด์ ์ ๊ฐ์ถ <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
+**์์ฒญ** ๋ณธ๋ฌธ์ ์ ์ธํ๊ธฐ ์ํด์ ๋ชจ๋ ๊ฐ๋ ฅํจ๊ณผ ์ด์ ์ ๊ฐ์ถ [Pydantic](https://docs.pydantic.dev/) ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
/// info | ์ ๋ณด
* ๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ์ ํจํ์ง ์๋ค๋ฉด, ์ ํํ ์ด๋ค ๊ฒ์ด ๊ทธ๋ฆฌ๊ณ ์ด๋์์ ๋ฐ์ดํฐ๊ฐ ์ ๋ชป ๋์๋์ง ์ง์ํ๋ ์น์ ํ๊ณ ๋ช
๋ฃํ ์๋ฌ๋ฅผ ๋ฐํํ ๊ฒ์
๋๋ค.
* ๋งค๊ฐ๋ณ์ `item`์ ํฌํจ๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
* ํจ์ ๋ด์์ ๋งค๊ฐ๋ณ์๋ฅผ `Item` ํ์
์ผ๋ก ์ ์ธํ๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ์ดํธ๋ฆฌ๋ทฐํธ์ ๊ทธ์ ๋ํ ํ์
์ ๋ํ ํธ์ง๊ธฐ ์ง์(์์ฑ ๋ฑ)์ ๋ํ ๋ฐ์ ์ ์์ต๋๋ค.
-* ์ฌ๋ฌ๋ถ์ ๋ชจ๋ธ์ ์ํ <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> ์ ์๋ฅผ ์์ฑํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ์ ํฉํ๋ค๋ฉด ์ฌ๋ฌ๋ถ์ด ์ฌ์ฉํ๊ณ ์ถ์ ๊ณณ ์ด๋์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+* ์ฌ๋ฌ๋ถ์ ๋ชจ๋ธ์ ์ํ [JSON Schema](https://json-schema.org) ์ ์๋ฅผ ์์ฑํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ ์ ํฉํ๋ค๋ฉด ์ฌ๋ฌ๋ถ์ด ์ฌ์ฉํ๊ณ ์ถ์ ๊ณณ ์ด๋์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
* ์ด๋ฌํ ์คํค๋ง๋, ์์ฑ๋ OpenAPI ์คํค๋ง ์ผ๋ถ๊ฐ ๋ ๊ฒ์ด๋ฉฐ, ์๋ ๋ฌธ์ํ <abbr title="User Interfaces - ์ฌ์ฉ์ ์ธํฐํ์ด์ค">UIs</abbr>์ ์ฌ์ฉ๋ฉ๋๋ค.
## ์๋ ๋ฌธ์ํ { #automatic-docs }
์ด๋ฅผ ์ง์ํ๊ธฐ ์ํด Pydantic ์์ฒด์์ ๋ช๋ช ๋ณ๊ฒฝ์ ์ด ์์์ต๋๋ค.
-์ด์ ์คํฌ๋ฆฐ์ท์ <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>๋ฅผ ์ฐ์ ๊ฒ์
๋๋ค.
+์ด์ ์คํฌ๋ฆฐ์ท์ [Visual Studio Code](https://code.visualstudio.com)๋ก ์ฐ์ ๊ฒ์
๋๋ค.
-ํ์ง๋ง ๋๊ฐ์ ํธ์ง๊ธฐ ์ง์์ <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>์ ๋๋ถ๋ถ์ ๋ค๋ฅธ ํ์ด์ฌ ํธ์ง๊ธฐ์์๋ ๋ฐ์ ์ ์์ต๋๋ค:
+ํ์ง๋ง ๋๊ฐ์ ํธ์ง๊ธฐ ์ง์์ [PyCharm](https://www.jetbrains.com/pycharm/)์ ๋๋ถ๋ถ์ ๋ค๋ฅธ ํ์ด์ฌ ํธ์ง๊ธฐ์์๋ ๋ฐ์ ์ ์์ต๋๋ค:
<img src="/img/tutorial/body/image05.png">
/// tip | ํ
-๋ง์ฝ <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>๋ฅผ ํธ์ง๊ธฐ๋ก ์ฌ์ฉํ๋ค๋ฉด, <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+๋ง์ฝ [PyCharm](https://www.jetbrains.com/pycharm/)๋ฅผ ํธ์ง๊ธฐ๋ก ์ฌ์ฉํ๋ค๋ฉด, [Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/)์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค์ ์ฌํญ์ ํฌํจํด Pydantic ๋ชจ๋ธ์ ๋ํ ํธ์ง๊ธฐ ์ง์์ ํฅ์์ํต๋๋ค:
## Pydantic์์ด { #without-pydantic }
-๋ง์ฝ Pydantic ๋ชจ๋ธ์ ์ฌ์ฉํ๊ณ ์ถ์ง ์๋ค๋ฉด, **Body** ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
+๋ง์ฝ Pydantic ๋ชจ๋ธ์ ์ฌ์ฉํ๊ณ ์ถ์ง ์๋ค๋ฉด, **Body** ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body) ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
# CORS (๊ต์ฐจ-์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ ) { #cors-cross-origin-resource-sharing }
-<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS ๋๋ "Cross-Origin Resource Sharing"</a>๋, ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋์ ํต์ ํ๋ JavaScript ์ฝ๋๊ฐ ์๊ณ , ๋ฐฑ์๋๊ฐ ํ๋ก ํธ์๋์ ๋ค๋ฅธ "์ถ์ฒ(origin)"์ ์๋ ์ํฉ์ ์๋ฏธํฉ๋๋ค.
+[CORS ๋๋ "Cross-Origin Resource Sharing"](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)๋, ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋์ ํต์ ํ๋ JavaScript ์ฝ๋๊ฐ ์๊ณ , ๋ฐฑ์๋๊ฐ ํ๋ก ํธ์๋์ ๋ค๋ฅธ "์ถ์ฒ(origin)"์ ์๋ ์ํฉ์ ์๋ฏธํฉ๋๋ค.
## ์ถ์ฒ { #origin }
* `allow_origins` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ๋ณด๋ผ ์ ์๋๋ก ํ์ฉํด์ผ ํ๋ ์ถ์ฒ์ ๋ฆฌ์คํธ์
๋๋ค. ์: `['https://example.org', 'https://www.example.org']`. ๋ชจ๋ ์ถ์ฒ๋ฅผ ํ์ฉํ๋ ค๋ฉด `['*']`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
* `allow_origin_regex` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ๋ณด๋ผ ์ ์๋๋ก ํ์ฉํด์ผ ํ๋ ์ถ์ฒ์ ๋งค์นญํ ์ ๊ทํํ์ ๋ฌธ์์ด์
๋๋ค. ์: `'https://.*\.example\.org'`.
* `allow_methods` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ํ์ฉ๋์ด์ผ ํ๋ HTTP ๋ฉ์๋์ ๋ฆฌ์คํธ์
๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `['GET']`์
๋๋ค. ๋ชจ๋ ํ์ค ๋ฉ์๋๋ฅผ ํ์ฉํ๋ ค๋ฉด `['*']`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-* `allow_headers` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ๋ํด ์ง์๋์ด์ผ ํ๋ HTTP ์์ฒญ ํค๋์ ๋ฆฌ์คํธ์
๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `[]`์
๋๋ค. ๋ชจ๋ ํค๋๋ฅผ ํ์ฉํ๋ ค๋ฉด `['*']`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. `Accept`, `Accept-Language`, `Content-Language`, `Content-Type` ํค๋๋ <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">๋จ์ CORS ์์ฒญ</a>์ ๋ํด ํญ์ ํ์ฉ๋ฉ๋๋ค.
+* `allow_headers` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ๋ํด ์ง์๋์ด์ผ ํ๋ HTTP ์์ฒญ ํค๋์ ๋ฆฌ์คํธ์
๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `[]`์
๋๋ค. ๋ชจ๋ ํค๋๋ฅผ ํ์ฉํ๋ ค๋ฉด `['*']`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. `Accept`, `Accept-Language`, `Content-Language`, `Content-Type` ํค๋๋ [๋จ์ CORS ์์ฒญ](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests)์ ๋ํด ํญ์ ํ์ฉ๋ฉ๋๋ค.
* `allow_credentials` - ๊ต์ฐจ-์ถ์ฒ ์์ฒญ์ ๋ํด ์ฟ ํค๋ฅผ ์ง์ํด์ผ ํจ์ ๋ํ๋
๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `False`์
๋๋ค.
- `allow_credentials`๊ฐ `True`๋ก ์ค์ ๋ ๊ฒฝ์ฐ `allow_origins`, `allow_methods`, `allow_headers` ์ค ์ด๋ ๊ฒ๋ `['*']`๋ก ์ค์ ํ ์ ์์ต๋๋ค. ๋ชจ๋ <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards" class="external-link" rel="noopener" target="_blank">๋ช
์์ ์ผ๋ก ์ง์ </a>๋์ด์ผ ํฉ๋๋ค.
+ `allow_credentials`๊ฐ `True`๋ก ์ค์ ๋ ๊ฒฝ์ฐ `allow_origins`, `allow_methods`, `allow_headers` ์ค ์ด๋ ๊ฒ๋ `['*']`๋ก ์ค์ ํ ์ ์์ต๋๋ค. ๋ชจ๋ [๋ช
์์ ์ผ๋ก ์ง์ ](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards)๋์ด์ผ ํฉ๋๋ค.
* `expose_headers` - ๋ธ๋ผ์ฐ์ ์์ ์ ๊ทผ ๊ฐ๋ฅํด์ผ ํ๋ ๋ชจ๋ ์๋ต ํค๋๋ฅผ ๋ํ๋
๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `[]`์
๋๋ค.
* `max_age` - ๋ธ๋ผ์ฐ์ ๊ฐ CORS ์๋ต์ ์บ์ํ๋ ์ต๋ ์๊ฐ์ ์ด ๋จ์๋ก ์ค์ ํฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ `600`์
๋๋ค.
## ๋ ๋ง์ ์ ๋ณด { #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>์ ๋ํ ๋ ๋ง์ ์ ๋ณด๋ [Mozilla CORS ๋ฌธ์](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
/// info | ์ ๋ณด
-์์ธํ ๋ด์ฉ์ <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">๊ณต์ Python ๋ฌธ์</a>๋ฅผ ํ์ธํ์ธ์.
+์์ธํ ๋ด์ฉ์ [๊ณต์ Python ๋ฌธ์](https://docs.python.org/3/library/__main__.html)๋ฅผ ํ์ธํ์ธ์.
///
์ด ์์์์ `X-Key`์ `X-Token`์ด๋ผ๋ ์ปค์คํ
ํค๋๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ์ต๋๋ค.
-๊ทธ๋ฌ๋ ์ค์ ๋ก ๋ณด์์ ๊ตฌํํ ๋๋ ํตํฉ๋ [๋ณด์ ์ ํธ๋ฆฌํฐ (๋ค์ ์ฑํฐ)](../security/index.md){.internal-link target=_blank}๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ง์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
+๊ทธ๋ฌ๋ ์ค์ ๋ก ๋ณด์์ ๊ตฌํํ ๋๋ ํตํฉ๋ [๋ณด์ ์ ํธ๋ฆฌํฐ (๋ค์ ์ฑํฐ)](../security/index.md)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ง์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
///
## *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๋ชจ์์ ๋ํ ์์กด์ฑ { #dependencies-for-a-group-of-path-operations }
-๋์ค์ ์ฌ๋ฌ ํ์ผ์ ๊ฐ์ง๊ณ ์์ ์ ์๋ ๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์กฐํํ๋ ๋ฒ([๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ๋ค](../../tutorial/bigger-applications.md){.internal-link target=_blank})์ ์ฝ์ ๋, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๋ชจ์์ ๋ํ ๋จ์ผ `dependencies` ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ธํ๋ ๋ฒ์ ๋ํด์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์
๋๋ค.
+๋์ค์ ์ฌ๋ฌ ํ์ผ์ ๊ฐ์ง๊ณ ์์ ์ ์๋ ๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์กฐํํ๋ ๋ฒ([๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ๋ค](../../tutorial/bigger-applications.md))์ ์ฝ์ ๋, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๋ชจ์์ ๋ํ ๋จ์ผ `dependencies` ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ธํ๋ ๋ฒ์ ๋ํด์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์
๋๋ค.
## ์ ์ญ ์์กด์ฑ { #global-dependencies }
์ด๋ฅผ ๊ตฌํํ๋ ค๋ฉด `return` ๋์ `yield`๋ฅผ ์ฌ์ฉํ๊ณ , ์ถ๊ฐ๋ก ์คํํ ๋จ๊ณ (์ฝ๋)๋ฅผ ๊ทธ ๋ค์ ์์ฑํ์ธ์.
-/// tip | ํ
+/// tip
๊ฐ ์์กด์ฑ๋ง๋ค `yield`๋ ํ ๋ฒ๋ง ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๋ค์๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ํจ์:
-* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> ๋๋
-* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
+* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) ๋๋
+* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager)
๋ **FastAPI**์ ์์กด์ฑ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
-/// tip | ํ
+/// tip
`async` ํจ์์ ์ผ๋ฐ ํจ์ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ
-ํ์ด์ฌ์ <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">Context Managers</a> ๋๋ถ์ ์ด ๊ธฐ๋ฅ์ด ์๋ํฉ๋๋ค.
+ํ์ด์ฌ์ [Context Managers](https://docs.python.org/3/library/contextlib.html) ๋๋ถ์ ์ด ๊ธฐ๋ฅ์ด ์๋ํฉ๋๋ค.
**FastAPI**๋ ์ด๋ฅผ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๋ฌ์ฑํฉ๋๋ค.
์๋ฅผ ๋ค์ด, `HTTPException` ๊ฐ์ ๋ค๋ฅธ ์์ธ๋ฅผ ๋ฐ์์ํฌ ์ ์์ต๋๋ค.
-/// tip | ํ
+/// tip
์ด๋ ๋ค์ ๊ณ ๊ธ ๊ธฐ์ ์ด๋ฉฐ, ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ค์ ๋ก๋ ํ์ํ์ง ์์ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, *๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์* ๋ฑ ๋๋จธ์ง ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ๋ด๋ถ์์ ์์ธ (`HTTPException` ํฌํจ)๋ฅผ ๋ฐ์์ํฌ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
-์์ธ๋ฅผ ์ก๊ณ ๊ทธ์ ๊ธฐ๋ฐํด ์ฌ์ฉ์ ์ ์ ์๋ต์ ์์ฑํ๋ ค๋ฉด, [์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}๋ฅผ ์์ฑํ์ธ์.
+์์ธ๋ฅผ ์ก๊ณ ๊ทธ์ ๊ธฐ๋ฐํด ์ฌ์ฉ์ ์ ์ ์๋ต์ ์์ฑํ๋ ค๋ฉด, [์ฌ์ฉ์ ์ ์ ์์ธ ์ฒ๋ฆฌ๊ธฐ](../handling-errors.md#install-custom-exception-handlers)๋ฅผ ์์ฑํ์ธ์.
## `yield`์ `except`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ { #dependencies-with-yield-and-except }
end
```
-/// info | ์ ๋ณด
+/// info
ํด๋ผ์ด์ธํธ์๋ **ํ๋์ ์๋ต**๋ง ์ ์ก๋ฉ๋๋ค. ์ด๋ ์ค๋ฅ ์๋ต ์ค ํ๋์ผ ์๋ ์๊ณ , *๊ฒฝ๋ก ์ฒ๋ฆฌ*์์ ์์ฑ๋ ์๋ต์ผ ์๋ ์์ต๋๋ค.
///
-/// tip | ํ
+/// tip
*๊ฒฝ๋ก ์ฒ๋ฆฌ ํจ์*์ ์ฝ๋์์ ์ด๋ค ์์ธ๋ฅผ ๋ฐ์์ํค๋ฉด `HTTPException`์ ํฌํจํด `yield`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ํด๋น ์์ธ(๋๋ ์ ์์ธ)๋ฅผ `yield`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ์์ ๋ค์ ๋ฐ์์์ผ, ์ ๋๋ก ์ฒ๋ฆฌ๋๋๋ก ํด์ผ ํฉ๋๋ค.
`yield`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ์ ์๊ฐ์ด ์ง๋๋ฉด์ ์๋ก ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ค๋ฃจ๊ณ ์ผ๋ถ ๋ฌธ์ ๋ฅผ ์์ ํ๊ธฐ ์ํด ๋ฐ์ ํด ์์ต๋๋ค.
-FastAPI์ ์ฌ๋ฌ ๋ฒ์ ์์ ๋ฌด์์ด ๋ฐ๋์๋์ง ๋ณด๊ณ ์ถ๋ค๋ฉด, ๊ณ ๊ธ ๊ฐ์ด๋์ [๊ณ ๊ธ ์์กด์ฑ - `yield`, `HTTPException`, `except` ๋ฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์ฌ์ฉํ๋ ์์กด์ฑ](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}์์ ๋ ์์ธํ ์ฝ์ ์ ์์ต๋๋ค.
+FastAPI์ ์ฌ๋ฌ ๋ฒ์ ์์ ๋ฌด์์ด ๋ฐ๋์๋์ง ๋ณด๊ณ ์ถ๋ค๋ฉด, ๊ณ ๊ธ ๊ฐ์ด๋์ [๊ณ ๊ธ ์์กด์ฑ - `yield`, `HTTPException`, `except` ๋ฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์ฌ์ฉํ๋ ์์กด์ฑ](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)์์ ๋ ์์ธํ ์ฝ์ ์ ์์ต๋๋ค.
## ์ปจํ
์คํธ ๊ด๋ฆฌ์ { #context-managers }
### "์ปจํ
์คํธ ๊ด๋ฆฌ์"๋ { #what-are-context-managers }
"์ปจํ
์คํธ ๊ด๋ฆฌ์"๋ Python์์ `with` ๋ฌธ์์ ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์๋ฏธํฉ๋๋ค.
-์๋ฅผ ๋ค์ด, <a href="https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files" class="external-link" target="_blank">`with`๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ฝ์ ์ ์์ต๋๋ค</a>:
+์๋ฅผ ๋ค์ด, [with๋ฅผ ์ฌ์ฉํด ํ์ผ์ ์ฝ์ ์ ์์ต๋๋ค](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files):
```Python
with open("./somefile.txt") as f:
### `yield`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ์์ ์ปจํ
์คํธ ๊ด๋ฆฌ์ ์ฌ์ฉํ๊ธฐ { #using-context-managers-in-dependencies-with-yield }
-/// warning | ๊ฒฝ๊ณ
+/// warning
์ด๊ฒ์ ์ด๋ ์ ๋ "๊ณ ๊ธ" ๊ฐ๋
์
๋๋ค.
///
-Python์์๋ ๋ค์์ ํตํด ์ปจํ
์คํธ ๊ด๋ฆฌ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank"> ๋ ๊ฐ์ง ๋ฉ์๋๊ฐ ์๋ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค: `__enter__()` and `__exit__()`</a>.
+Python์์๋ [๋ ๊ฐ์ง ๋ฉ์๋: `__enter__()`์ `__exit__()`๊ฐ ์๋ ํด๋์ค๋ฅผ ์์ฑํ์ฌ](https://docs.python.org/3/reference/datamodel.html#context-managers) ์ปจํ
์คํธ ๊ด๋ฆฌ์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
**FastAPI**์ `yield`๊ฐ ์๋ ์์กด์ฑ ๋ด์์
`with` ๋๋ `async with`๋ฌธ์ ์ฌ์ฉํ์ฌ ์ด๋ค์ ํ์ฉํ ์ ์์ต๋๋ค:
{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
-/// tip | ํ
+/// tip
์ปจํ
์คํธ ๊ด๋ฆฌ์๋ฅผ ์์ฑํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
-* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> ๋๋
-* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
+* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) ๋๋
+* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager)
์ด๋ค์ ๋จ์ผ `yield`๊ฐ ์๋ ํจ์๋ฅผ ๊พธ๋ฏธ๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค.
๋ช๋ช ์ ํ์ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒด์ ์์กด์ฑ์ ์ถ๊ฐํ๊ณ ์ถ์ ์ ์์ต๋๋ค.
-[*๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `dependencies` ์ถ๊ฐํ๊ธฐ](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์ ์ ์ฌํ ๋ฐฉ๋ฒ์ผ๋ก `FastAPI` ์ ํ๋ฆฌ์ผ์ด์
์ ๊ทธ๊ฒ๋ค์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
+[*๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `dependencies` ์ถ๊ฐํ๊ธฐ](dependencies-in-path-operation-decorators.md)์ ์ ์ฌํ ๋ฐฉ๋ฒ์ผ๋ก `FastAPI` ์ ํ๋ฆฌ์ผ์ด์
์ ๊ทธ๊ฒ๋ค์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๊ทธ๋ฐ ๊ฒฝ์ฐ์, ์ ํ๋ฆฌ์ผ์ด์
์ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์ ์ฉ๋ ๊ฒ์
๋๋ค:
{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
-๊ทธ๋ฆฌ๊ณ [*๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `dependencies` ์ถ๊ฐํ๊ธฐ](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ์น์
์ ๋ชจ๋ ์์ด๋์ด๋ ์ฌ์ ํ ์ ์ฉ๋์ง๋ง, ์ด ๊ฒฝ์ฐ์๋ ์ฑ์ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์ ์ฉ๋ฉ๋๋ค.
+๊ทธ๋ฆฌ๊ณ [*๊ฒฝ๋ก ์ฒ๋ฆฌ ๋ฐ์ฝ๋ ์ดํฐ*์ `dependencies` ์ถ๊ฐํ๊ธฐ](dependencies-in-path-operation-decorators.md) ์น์
์ ๋ชจ๋ ์์ด๋์ด๋ ์ฌ์ ํ ์ ์ฉ๋์ง๋ง, ์ด ๊ฒฝ์ฐ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ชจ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์ ์ฉ๋ฉ๋๋ค.
## *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๊ทธ๋ฃน์ ๋ํ ์์กด์ฑ { #dependencies-for-groups-of-path-operations }
-๋์ค์ ์ฌ๋ฌ ํ์ผ์ ํฌํจํ ์๋ ์๋ ๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์กฐํํ๋ ๋ฒ([๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ๋ค](../../tutorial/bigger-applications.md){.internal-link target=_blank})์ ์ฝ์ ๋, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๊ทธ๋ฃน์ ๋ํ ๋จ์ผ `dependencies` ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ธํ๋ ๋ฒ์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์
๋๋ค.
+๋์ค์ ์ฌ๋ฌ ํ์ผ์ ํฌํจํ ์๋ ์๋ ๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์กฐํํ๋ ๋ฒ([๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
- ์ฌ๋ฌ ํ์ผ๋ค](../../tutorial/bigger-applications.md))์ ์ฝ์ ๋, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ๊ทธ๋ฃน์ ๋ํ ๋จ์ผ `dependencies` ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ธํ๋ ๋ฒ์ ๋ฐฐ์ฐ๊ฒ ๋ ๊ฒ์
๋๋ค.
์๋ ๋ฒ์ ์ ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ, `Annotated`๋ฅผ ์ฌ์ฉํ๋ ค ํ๋ฉด ์๋ฌ๋ฅผ ๋ง์ดํ๊ฒ ๋ ๊ฒ์
๋๋ค.
-`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1๋ก [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}๋ฅผ ํ์คํ๊ฒ ํ์ธ์.
+`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1๋ก [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../../deployment/versions.md#upgrading-the-fastapi-versions)๋ฅผ ํ์คํ๊ฒ ํ์ธ์.
///
/// note | ์ฐธ๊ณ
-์ ๋ชจ๋ฅด์๊ฒ ๋ค๋ฉด, [Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank} ๋ฌธ์์์ `async`์ `await`์ ๋ํด ํ์ธํ ์ ์์ต๋๋ค.
+์ ๋ชจ๋ฅด์๊ฒ ๋ค๋ฉด, [Async: *"In a hurry?"*](../../async.md#in-a-hurry) ๋ฌธ์์์ `async`์ `await`์ ๋ํด ํ์ธํ ์ ์์ต๋๋ค.
///
์๋ฅผ ๋ค๋ฉด, `datetime` ๊ฐ์ฒด๋ JSON๊ณผ ํธํ๋์ง ์์ผ๋ฏ๋ก ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ด๋ฅผ ๋ฐ์ง ์์ต๋๋ค.
-๋ฐ๋ผ์ `datetime` ๊ฐ์ฒด๋ <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO ํ์</a>์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ `str`๋ก ๋ณํ๋์ด์ผ ํฉ๋๋ค.
+๋ฐ๋ผ์ `datetime` ๊ฐ์ฒด๋ [ISO ํ์](https://en.wikipedia.org/wiki/ISO_8601)์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ `str`๋ก ๋ณํ๋์ด์ผ ํฉ๋๋ค.
๊ฐ์ ๋ฐฉ์์ผ๋ก ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ Pydantic ๋ชจ๋ธ(์์ฑ์ด ์๋ ๊ฐ์ฒด)์ ๋ฐ์ง ์๊ณ , `dict`๋ง์ ๋ฐ์ต๋๋ค.
์ด ์์์์๋ Pydantic ๋ชจ๋ธ์ `dict`๋ก, `datetime`์ `str`๋ก ๋ณํํฉ๋๋ค.
-์ด๋ ๊ฒ ํธ์ถํ ๊ฒฐ๊ณผ๋ ํ์ด์ฌ ํ์ค์ธ <a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>๋ก ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค.
+์ด๋ ๊ฒ ํธ์ถํ ๊ฒฐ๊ณผ๋ ํ์ด์ฌ ํ์ค์ธ [`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps)๋ก ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค.
JSON ํ์(๋ฌธ์์ด)์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ ํฐ `str`์ ๋ฐํํ์ง ์์ต๋๋ค. JSON๊ณผ ๋ชจ๋ ํธํ๋๋ ๊ฐ๊ณผ ํ์ ๊ฐ์ด ์๋ ํ์ด์ฌ ํ์ค ๋ฐ์ดํฐ ๊ตฌ์กฐ(์: `dict`)๋ฅผ ๋ฐํํฉ๋๋ค.
* `datetime.timedelta`:
* ํ์ด์ฌ์ `datetime.timedelta`.
* ์์ฒญ๊ณผ ์๋ต์์ ์ ์ฒด ์ด(seconds)์ `float`๋ก ํํ๋ฉ๋๋ค.
- * Pydantic์ "ISO 8601 time diff encoding"์ผ๋ก ํํํ๋ ๊ฒ ๋ํ ํ์ฉํฉ๋๋ค. <a href="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers" class="external-link" target="_blank">๋ ๋ง์ ์ ๋ณด๋ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์</a>.
+ * Pydantic์ "ISO 8601 time diff encoding"์ผ๋ก ํํํ๋ ๊ฒ ๋ํ ํ์ฉํฉ๋๋ค. [๋ ๋ง์ ์ ๋ณด๋ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers).
* `frozenset`:
* ์์ฒญ๊ณผ ์๋ต์์ `set`์ ๋์ผํ๊ฒ ์ทจ๊ธ๋ฉ๋๋ค:
* ์์ฒญ ์, ๋ฆฌ์คํธ๋ฅผ ์ฝ์ด ์ค๋ณต์ ์ ๊ฑฐํ๊ณ `set`๋ก ๋ณํํฉ๋๋ค.
* `Decimal`:
* ํ์ค ํ์ด์ฌ์ `Decimal`.
* ์์ฒญ๊ณผ ์๋ต์์ `float`์ ๋์ผํ๊ฒ ๋ค๋ค์ง๋๋ค.
-* ์ฌ๊ธฐ์์ ๋ชจ๋ ์ ํจํ Pydantic ๋ฐ์ดํฐ ์๋ฃํ์ ํ์ธํ ์ ์์ต๋๋ค: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic ๋ฐ์ดํฐ ์๋ฃํ</a>.
+* ์ฌ๊ธฐ์์ ๋ชจ๋ ์ ํจํ Pydantic ๋ฐ์ดํฐ ์๋ฃํ์ ํ์ธํ ์ ์์ต๋๋ค: [Pydantic ๋ฐ์ดํฐ ์๋ฃํ](https://docs.pydantic.dev/latest/usage/types/types/).
## ์์ { #example }
์ ๋ ์ฌ์ฉ์์ ๋น๋ฐ๋ฒํธ๋ฅผ ํ๋ฌธ์ผ๋ก ์ ์ฅํ์ง ๋ง์ธ์. ํญ์ ์ดํ์ ๊ฒ์ฆ ๊ฐ๋ฅํ "์์ ํ ํด์(secure hash)"๋ก ์ ์ฅํ์ธ์.
-๋ง์ฝ ์ด๊ฒ ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, [๋ณด์ ์ฅ](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}์์ "password hash"๊ฐ ๋ฌด์์ธ์ง ๋ฐฐ์ธ ์ ์์ต๋๋ค.
+๋ง์ฝ ์ด๊ฒ ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, [๋ณด์ ์ฅ](security/simple-oauth2.md#password-hashing)์์ "password hash"๊ฐ ๋ฌด์์ธ์ง ๋ฐฐ์ธ ์ ์์ต๋๋ค.
///
OpenAPI์์๋ ์ด๋ฅผ `anyOf`๋ก ์ ์ํฉ๋๋ค.
-์ด๋ฅผ ์ํด ํ์ค Python ํ์
ํํธ์ธ <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
+์ด๋ฅผ ์ํด ํ์ค Python ํ์
ํํธ์ธ [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union)์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
/// note
-<a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a>์ ์ ์ํ ๋๋ ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๋จผ์ ํฌํจํ๊ณ , ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๊ทธ ๋ค์ ๋์ดํด์ผ ํฉ๋๋ค. ์๋ ์์ ์์๋ `Union[PlaneItem, CarItem]`์์ ๋ ๊ตฌ์ฒด์ ์ธ `PlaneItem`์ด `CarItem`๋ณด๋ค ์์ ์์นํฉ๋๋ค.
+[`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions)์ ์ ์ํ ๋๋ ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๋จผ์ ํฌํจํ๊ณ , ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๊ทธ ๋ค์ ๋์ดํด์ผ ํฉ๋๋ค. ์๋ ์์ ์์๋ `Union[PlaneItem, CarItem]`์์ ๋ ๊ตฌ์ฒด์ ์ธ `PlaneItem`์ด `CarItem`๋ณด๋ค ์์ ์์นํฉ๋๋ค.
///
<div class="termy">
```console
-$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
+$ <font color="#4E9A06">fastapi</font> dev
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server ๐
### ํ์ธํ๊ธฐ { #check-it }
-๋ธ๋ผ์ฐ์ ๋ก <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>๋ฅผ ์ฌ์ธ์.
+๋ธ๋ผ์ฐ์ ๋ก [http://127.0.0.1:8000](http://127.0.0.1:8000)๋ฅผ ์ฌ์ธ์.
์๋์ ๊ฐ์ JSON ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
### ๋ํํ API ๋ฌธ์ { #interactive-api-docs }
-์ด์ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ก ๊ฐ๋ด
๋๋ค.
+์ด์ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ก ๊ฐ๋ด
๋๋ค.
-์๋ ๋ํํ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค (<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> ์ ๊ณต):
+์๋ ๋ํํ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค ([Swagger UI](https://github.com/swagger-api/swagger-ui) ์ ๊ณต):

### ๋์ API ๋ฌธ์ { #alternative-api-docs }
-๊ทธ๋ฆฌ๊ณ ์ด์ , <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>๋ก ๊ฐ๋ด
๋๋ค.
+๊ทธ๋ฆฌ๊ณ ์ด์ , [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)๋ก ๊ฐ๋ด
๋๋ค.
-๋์ ์๋ ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค (<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> ์ ๊ณต):
+๋์ ์๋ ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค ([ReDoc](https://github.com/Rebilly/ReDoc) ์ ๊ณต):

#### API "์คํค๋ง" { #api-schema }
-<a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a>๋ API์ ์คํค๋ง๋ฅผ ์ด๋ป๊ฒ ์ ์ํ๋์ง ์ง์ํ๋ ๊ท๊ฒฉ์
๋๋ค.
+์ด ๊ฒฝ์ฐ, [OpenAPI](https://github.com/OAI/OpenAPI-Specification)๋ ์ฌ๋ฌ๋ถ์ API ์คํค๋ง๋ฅผ ์ด๋ป๊ฒ ์ ์ํ๋์ง ์ง์ํ๋ ๊ท๊ฒฉ์
๋๋ค.
์ด ์คํค๋ง ์ ์๋ API ๊ฒฝ๋ก, ๊ฐ๋ฅํ ๋งค๊ฐ๋ณ์ ๋ฑ์ ํฌํจํฉ๋๋ค.
๊ฐ๊ณต๋์ง ์์ OpenAPI ์คํค๋ง๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๊ถ๊ธํ๋ค๋ฉด, FastAPI๋ ์๋์ผ๋ก ์ฌ๋ฌ๋ถ์ ๋ชจ๋ API์ ๋ํ ์ค๋ช
๊ณผ ํจ๊ป JSON (์คํค๋ง)๋ฅผ ์์ฑํฉ๋๋ค.
-์ฌ๊ธฐ์์ ์ง์ ๋ณผ ์ ์์ต๋๋ค: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
+์ฌ๊ธฐ์์ ์ง์ ๋ณผ ์ ์์ต๋๋ค: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json).
๋ค์๊ณผ ๊ฐ์ด ์์ํ๋ JSON์ ํ์ธํ ์ ์์ต๋๋ค:
API์ ํต์ ํ๋ ํด๋ผ์ด์ธํธ(ํ๋ก ํธ์๋, ๋ชจ๋ฐ์ผ, IoT ์ ํ๋ฆฌ์ผ์ด์
๋ฑ)๋ฅผ ์ํด ์ฝ๋๋ฅผ ์๋์ผ๋ก ์์ฑํ๋ ๋ฐ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+### `pyproject.toml`์ ์ฑ `entrypoint` ๊ตฌ์ฑํ๊ธฐ { #configure-the-app-entrypoint-in-pyproject-toml }
+
+๋ค์๊ณผ ๊ฐ์ด `pyproject.toml` ํ์ผ์์ ์ฑ์ด ์์นํ ๊ณณ์ ๊ตฌ์ฑํ ์ ์์ต๋๋ค:
+
+```toml
+[tool.fastapi]
+entrypoint = "main:app"
+```
+
+ํด๋น `entrypoint`๋ `fastapi` ๋ช
๋ น์ด์ ๋ค์๊ณผ ๊ฐ์ด ์ฑ์ ์ํฌํธํ๋ผ๊ณ ์๋ ค์ค๋๋ค:
+
+```python
+from main import app
+```
+
+์ฝ๋ ๊ตฌ์กฐ๊ฐ ๋ค์๊ณผ ๊ฐ๋ค๋ฉด:
+
+```
+.
+โโโ backend
+โย ย โโโ main.py
+โย ย โโโ __init__.py
+```
+
+๊ทธ๋ผ `entrypoint`๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํฉ๋๋ค:
+
+```toml
+[tool.fastapi]
+entrypoint = "backend.main:app"
+```
+
+์ด๋ ๋ค์๊ณผ ๋์ผํฉ๋๋ค:
+
+```python
+from backend.main import app
+```
+
+### `fastapi dev`์ ๊ฒฝ๋ก ์ง์ ํ๊ธฐ { #fastapi-dev-with-path }
+
+`fastapi dev` ๋ช
๋ น์ด์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ ์๋ ์์ผ๋ฉฐ, ๊ทธ๋ฌ๋ฉด ์ฌ์ฉํ FastAPI app ๊ฐ์ฒด๋ฅผ ์ถ์ ํฉ๋๋ค:
+
+```console
+$ fastapi dev main.py
+```
+
+ํ์ง๋ง ๋งค๋ฒ `fastapi` ๋ช
๋ น์ด๋ฅผ ํธ์ถํ ๋๋ง๋ค ์ฌ๋ฐ๋ฅธ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค.
+
+๋ํ ๋ค๋ฅธ ๋๊ตฌ๋ค, ์๋ฅผ ๋ค์ด [VS Code ํ์ฅ](../editor-support.md)์ด๋ [FastAPI Cloud](https://fastapicloud.com)๊ฐ ์ด๋ฅผ ์ฐพ์ง ๋ชปํ ์ ์์ผ๋ฏ๋ก, `pyproject.toml`์ `entrypoint`๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
+
### ์ฑ ๋ฐฐํฌํ๊ธฐ(์ ํ ์ฌํญ) { #deploy-your-app-optional }
-์ ํ์ ์ผ๋ก FastAPI ์ฑ์ <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํ์ง ์์๋ค๋ฉด, ๋ฑ๋กํ๋ฌ ๊ฐ์ธ์. ๐
+์ ํ์ ์ผ๋ก FastAPI ์ฑ์ [FastAPI Cloud](https://fastapicloud.com)์ ๋ฐฐํฌํ ์ ์์ต๋๋ค. ์์ง ๋๊ธฐ์ ๋ช
๋จ์ ๋ฑ๋กํ์ง ์์๋ค๋ฉด, ๋ฑ๋กํ๋ฌ ๊ฐ์ธ์. ๐
์ด๋ฏธ **FastAPI Cloud** ๊ณ์ ์ด ์๋ค๋ฉด(๋๊ธฐ์ ๋ช
๋จ์์ ์ด๋ํด ๋๋ ธ์ต๋๋ค ๐), ํ ๋ฒ์ ๋ช
๋ น์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
`FastAPI`๋ `Starlette`๋ฅผ ์ง์ ์์ํ๋ ํด๋์ค์
๋๋ค.
-`FastAPI`๋ก <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a>์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+`FastAPI`๋ก [Starlette](https://www.starlette.dev/)์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
/// note | ์ฐธ๊ณ
-์ฐจ์ด์ ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด [Async: *"๋ฐ์์ ๊ฒฝ์ฐ"*](../async.md#in-a-hurry){.internal-link target=_blank}๋ฅผ ํ์ธํ์ธ์.
+์ฐจ์ด์ ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด [Async: *"๋ฐ์์ ๊ฒฝ์ฐ"*](../async.md#in-a-hurry)๋ฅผ ํ์ธํ์ธ์.
///
### 6 ๋จ๊ณ: ๋ฐฐํฌํ๊ธฐ { #step-6-deploy-it }
-ํ ๋ฒ์ ๋ช
๋ น์ผ๋ก **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**์ ์ฑ์ ๋ฐฐํฌํฉ๋๋ค: `fastapi deploy`. ๐
+ํ ๋ฒ์ ๋ช
๋ น์ผ๋ก **[FastAPI Cloud](https://fastapicloud.com)**์ ์ฑ์ ๋ฐฐํฌํฉ๋๋ค: `fastapi deploy`. ๐
#### FastAPI Cloud ์๊ฐ { #about-fastapi-cloud }
-**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**๋ **FastAPI** ๋ค์ ์๋ ๋์ผํ ์์ฑ์์ ํ์ด ๋ง๋ค์์ต๋๋ค.
+**[FastAPI Cloud](https://fastapicloud.com)**๋ **FastAPI** ๋ค์ ์๋ ๋์ผํ ์์ฑ์์ ํ์ด ๋ง๋ค์์ต๋๋ค.
์ต์ํ์ ๋
ธ๋ ฅ์ผ๋ก API๋ฅผ **๋น๋**, **๋ฐฐํฌ**, **์ ๊ทผ**ํ๋ ๊ณผ์ ์ ๊ฐ์ํํฉ๋๋ค.
## ์ปค์คํ
์์ธ ํธ๋ค๋ฌ ์ค์นํ๊ธฐ { #install-custom-exception-handlers }
-<a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">Starlette์ ๋์ผํ ์์ธ ์ ํธ๋ฆฌํฐ</a>๋ฅผ ์ฌ์ฉํด ์ปค์คํ
์์ธ ํธ๋ค๋ฌ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
+[Starlette์ ๋์ผํ ์์ธ ์ ํธ๋ฆฌํฐ](https://www.starlette.dev/exceptions/)๋ฅผ ์ฌ์ฉํด ์ปค์คํ
์์ธ ํธ๋ค๋ฌ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ(๋๋ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)์ด `raise`ํ ์ ์๋ ์ปค์คํ
์์ธ `UnicornException`์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ด
์๋ค.
<div class="termy">
```console
-$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
+$ <font color="#4E9A06">fastapi</font> dev
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server ๐
์ฒซ ๋จ๊ณ๋ FastAPI๋ฅผ ์ค์นํ๋ ๊ฒ์
๋๋ค.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, **FastAPI๋ฅผ ์ค์น**ํ์ธ์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, **FastAPI๋ฅผ ์ค์น**ํ์ธ์:
<div class="termy">
/// note | ์ฐธ๊ณ
-`pip install "fastapi[standard]"`๋ก ์ค์นํ๋ฉด `fastapi-cloud-cli`๋ฅผ ํฌํจํ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ ์ ํ์ standard ์์กด์ฑ์ด ํจ๊ป ์ค์น๋๋ฉฐ, ์ด๋ฅผ ์ฌ์ฉํด <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
+`pip install "fastapi[standard]"`๋ก ์ค์นํ๋ฉด `fastapi-cloud-cli`๋ฅผ ํฌํจํ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ ์ ํ์ standard ์์กด์ฑ์ด ํจ๊ป ์ค์น๋๋ฉฐ, ์ด๋ฅผ ์ฌ์ฉํด [FastAPI Cloud](https://fastapicloud.com)์ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
์ด๋ฌํ ์ ํ์ ์์กด์ฑ์ด ํ์ ์๋ค๋ฉด `pip install fastapi`๋ก ๋์ ์ค์นํ ์ ์์ต๋๋ค.
///
+/// tip | ํ
+
+FastAPI๋ VS Code(๋ฐ Cursor)์ฉ [๊ณต์ ํ์ฅ ํ๋ก๊ทธ๋จ](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)์ด ์์ต๋๋ค. ๊ฒฝ๋ก ์ฒ๋ฆฌ ํ์๊ธฐ, ๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ฒ์, ํ
์คํธ์์์ CodeLens ํ์(ํ
์คํธ์์ ์ ์๋ก ๋ฐ๋ก ์ด๋), FastAPI Cloud ๋ฐฐํฌ์ ๋ก๊ทธ ๋ฑ ๋ง์ ๊ธฐ๋ฅ์ ์๋ํฐ์์ ๋ฐ๋ก ์ ๊ณตํฉ๋๋ค.
+
+///
+
## ๊ณ ๊ธ ์ฌ์ฉ์ ์๋ด์ { #advanced-user-guide }
์ด **์์ต์ - ์ฌ์ฉ์ ์๋ด์**๋ฅผ ์ฝ์ ๋ค์ ๋์ค์ ์ฝ์ ์ ์๋ **๊ณ ๊ธ ์ฌ์ฉ์ ์๋ด์**๋ ์์ต๋๋ค.
| `version` | `string` | API์ ๋ฒ์ ์
๋๋ค. OpenAPI์ ๋ฒ์ ์ด ์๋, ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฒ์ ์ ๋ํ๋
๋๋ค. ์: `2.5.0`. |
| `terms_of_service` | `str` | API ์ด์ฉ ์ฝ๊ด์ URL์
๋๋ค. ์ ๊ณตํ๋ ๊ฒฝ์ฐ URL ํ์์ด์ด์ผ ํฉ๋๋ค. |
| `contact` | `dict` | ๋
ธ์ถ๋ API์ ๋ํ ์ฐ๋ฝ์ฒ ์ ๋ณด์
๋๋ค. ์ฌ๋ฌ ํ๋๋ฅผ ํฌํจํ ์ ์์ต๋๋ค. <details><summary><code>contact</code> ํ๋</summary><table><thead><tr><th>๋งค๊ฐ๋ณ์</th><th>ํ์
</th><th>์ค๋ช
</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>์ฐ๋ฝ์ฒ ์ธ๋ฌผ/์กฐ์ง์ ์๋ณ๋ช
์
๋๋ค.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>์ฐ๋ฝ์ฒ ์ ๋ณด๊ฐ ๋ด๊ธด URL์
๋๋ค. URL ํ์์ด์ด์ผ ํฉ๋๋ค.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>์ฐ๋ฝ์ฒ ์ธ๋ฌผ/์กฐ์ง์ ์ด๋ฉ์ผ ์ฃผ์์
๋๋ค. ์ด๋ฉ์ผ ์ฃผ์ ํ์์ด์ด์ผ ํฉ๋๋ค.</td></tr></tbody></table></details> |
-| `license_info` | `dict` | ๋
ธ์ถ๋ API์ ๋ผ์ด์ ์ค ์ ๋ณด์
๋๋ค. ์ฌ๋ฌ ํ๋๋ฅผ ํฌํจํ ์ ์์ต๋๋ค. <details><summary><code>license_info</code> ํ๋</summary><table><thead><tr><th>๋งค๊ฐ๋ณ์</th><th>ํ์
</th><th>์ค๋ช
</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ํ์</strong> (<code>license_info</code>๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ). API์ ์ฌ์ฉ๋ ๋ผ์ด์ ์ค ์ด๋ฆ์
๋๋ค.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>API์ ๋ํ <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a> ๋ผ์ด์ ์ค ํํ์
๋๋ค. <code>identifier</code> ํ๋๋ <code>url</code> ํ๋์ ์ํธ ๋ฐฐํ์ ์
๋๋ค. <small>OpenAPI 3.1.0, FastAPI 0.99.0๋ถํฐ ์ฌ์ฉ ๊ฐ๋ฅ.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>API์ ์ฌ์ฉ๋ ๋ผ์ด์ ์ค์ URL์
๋๋ค. URL ํ์์ด์ด์ผ ํฉ๋๋ค.</td></tr></tbody></table></details> |
+| `license_info` | `dict` | ๋
ธ์ถ๋ API์ ๋ผ์ด์ ์ค ์ ๋ณด์
๋๋ค. ์ฌ๋ฌ ํ๋๋ฅผ ํฌํจํ ์ ์์ต๋๋ค. <details><summary><code>license_info</code> ํ๋</summary><table><thead><tr><th>๋งค๊ฐ๋ณ์</th><th>ํ์
</th><th>์ค๋ช
</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>ํ์</strong> (<code>license_info</code>๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ). API์ ์ฌ์ฉ๋ ๋ผ์ด์ ์ค ์ด๋ฆ์
๋๋ค.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>API์ ๋ํ [SPDX](https://spdx.org/licenses/) ๋ผ์ด์ ์ค ํํ์
๋๋ค. <code>identifier</code> ํ๋๋ <code>url</code> ํ๋์ ์ํธ ๋ฐฐํ์ ์
๋๋ค. <small>OpenAPI 3.1.0, FastAPI 0.99.0๋ถํฐ ์ฌ์ฉ ๊ฐ๋ฅ.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>API์ ์ฌ์ฉ๋ ๋ผ์ด์ ์ค์ URL์
๋๋ค. URL ํ์์ด์ด์ผ ํฉ๋๋ค.</td></tr></tbody></table></details> |
๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ ์ ์์ต๋๋ค:
## ํ๊ทธ์ ๋ํ ๋ฉํ๋ฐ์ดํฐ { #metadata-for-tags }
-`openapi_tags` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฝ๋ก ์ฒ๋ฆฌ์ ๊ทธ๋ฃนํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ฌ๋ฌ ํ๊ทธ์ ์ถ๊ฐ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
+`openapi_tags` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฝ๋ก ์ฒ๋ฆฌ๋ฅผ ๊ทธ๋ฃนํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ฌ๋ฌ ํ๊ทธ์ ์ถ๊ฐ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ์๋ ์์ต๋๋ค.
๋ฆฌ์คํธ๋ ๊ฐ ํ๊ทธ์ ๋ํด ํ๋์ ๋์
๋๋ฆฌ๋ฅผ ํฌํจํฉ๋๋ค.
/// info | ์ ๋ณด
-ํ๊ทธ์ ๋ํ ์์ธํ ๋ด์ฉ์ [๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ](path-operation-configuration.md#tags){.internal-link target=_blank}์์ ์ฝ์ด๋ณด์ธ์.
+ํ๊ทธ์ ๋ํ ์์ธํ ๋ด์ฉ์ [๊ฒฝ๋ก ์ฒ๋ฆฌ ๊ตฌ์ฑ](path-operation-configuration.md#tags)์์ ์ฝ์ด๋ณด์ธ์.
///
# ๋ฏธ๋ค์จ์ด { #middleware }
-รซยฏยธรซ\93ยครฌ\9bยจรฌ\96ยดรซยฅยผ **FastAPI** รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
+รซยฏยธรซ\93ยครฌ\9bยจรฌ\96ยดรซยฅยผ **FastAPI** รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
"๋ฏธ๋ค์จ์ด"๋ ํน์ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์ํด ์ฒ๋ฆฌ๋๊ธฐ ์ , ๋ชจ๋ **์์ฒญ**์ ๋ํด์ ๋์ํ๋ ํจ์์
๋๋ค. ๋ํ ๋ชจ๋ **์๋ต**์ด ๋ฐํ๋๊ธฐ ์ ์๋ ๋์ผํ๊ฒ ๋์ํฉ๋๋ค.
-* รซยฏยธรซ\93ยครฌ\9bยจรฌ\96ยดรซ\8a\94 รฌ\9d\91รฌ\9aยฉ รญ\94\84รซยก\9cรชยทยธรซ\9eยจ์ผ๋ก ์ค๋ ๊ฐ **์์ฒญ**์ ๊ฐ์ ธ์ต๋๋ค.
+* รซยฏยธรซ\93ยครฌ\9bยจรฌ\96ยดรซ\8a\94 รฌ\95ย รญ\94\8cรซยฆยฌรฌยผ\80รฌ\9dยดรฌ\85\98์ผ๋ก ์ค๋ ๊ฐ **์์ฒญ**์ ๊ฐ์ ธ์ต๋๋ค.
* ๊ทธ๋ฐ ๋ค์ ํด๋น **์์ฒญ**์ ๋ํด ๋ฌด์ธ๊ฐ๋ฅผ ํ๊ฑฐ๋ ํ์ํ ์ฝ๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
* ๊ทธ๋ฐ ๋ค์ **์์ฒญ**์ ๋๋จธ์ง ์ ํ๋ฆฌ์ผ์ด์
(์ด๋ค *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ)์ ํตํด ์ฒ๋ฆฌ๋๋๋ก ์ ๋ฌํฉ๋๋ค.
* ๊ทธ๋ฐ ๋ค์ ์ ํ๋ฆฌ์ผ์ด์
(์ด๋ค *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ)์ด ์์ฑํ **์๋ต**์ ๊ฐ์ ธ์ต๋๋ค.
`yield`๋ฅผ ์ฌ์ฉํ๋ ์์กด์ฑ์ด ์๋ค๋ฉด, exit ์ฝ๋๋ ๋ฏธ๋ค์จ์ด *ํ์* ์คํ๋ฉ๋๋ค.
-๋ฐฑ๊ทธ๋ผ์ด๋ ์์
(๋ค์์ ๋ณด๊ฒ ๋ [๋ฐฑ๊ทธ๋ผ์ด๋ ์์
](background-tasks.md){.internal-link target=_blank} ์น์
์์ ๋ค๋ฃน๋๋ค)์ด ์๋ค๋ฉด, ๋ชจ๋ ๋ฏธ๋ค์จ์ด *ํ์* ์คํ๋ฉ๋๋ค.
+๋ฐฑ๊ทธ๋ผ์ด๋ ์์
(๋ค์์ ๋ณด๊ฒ ๋ [๋ฐฑ๊ทธ๋ผ์ด๋ ์์
](background-tasks.md) ์น์
์์ ๋ค๋ฃน๋๋ค)์ด ์๋ค๋ฉด, ๋ชจ๋ ๋ฏธ๋ค์จ์ด *ํ์* ์คํ๋ฉ๋๋ค.
///
/// tip | ํ
-์ฌ์ฉ์ ์ ์ ๋
์ ํค๋๋ <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">`X-` ์ ๋์ฌ๋ฅผ ์ฌ์ฉ</a>ํ์ฌ ์ถ๊ฐํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
+์ฌ์ฉ์ ์ ์ ๋
์ ํค๋๋ [`X-` ์ ๋์ฌ๋ฅผ ์ฌ์ฉ](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)ํ์ฌ ์ถ๊ฐํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์.
-ํ์ง๋ง ๋ธ๋ผ์ฐ์ ์์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณผ ์ ์๊ฒ ํ๋ ค๋ ์ฌ์ฉ์ ์ ์ ํค๋๊ฐ ์๋ค๋ฉด, <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette์ CORS ๋ฌธ์</a>์ ๋ฌธ์ํ๋ `expose_headers` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํด CORS ์ค์ ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
+ํ์ง๋ง ๋ธ๋ผ์ฐ์ ์์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณผ ์ ์๊ฒ ํ๋ ค๋ ์ฌ์ฉ์ ์ ์ ํค๋๊ฐ ์๋ค๋ฉด, [CORS (Cross-Origin Resource Sharing)](cors.md) ์ค์ ์ [Starlette์ CORS ๋ฌธ์](https://www.starlette.dev/middleware/#corsmiddleware)์ ๋ฌธ์ํ๋ `expose_headers` ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํด ์ถ๊ฐํด์ผ ํฉ๋๋ค.
///
/// tip | ํ
-์ฌ๊ธฐ์๋ ์ด๋ฌํ ์ฌ์ฉ ์ฌ๋ก์์ ๋ ์ ํํ ์ ์๊ธฐ ๋๋ฌธ์ `time.time()` ๋์ <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a>๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๐ค
+์ฌ๊ธฐ์๋ ์ด๋ฌํ ์ฌ์ฉ ์ฌ๋ก์์ ๋ ์ ํํ ์ ์๊ธฐ ๋๋ฌธ์ `time.time()` ๋์ [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๐ค
///
## ๋ค๋ฅธ ๋ฏธ๋ค์จ์ด { #other-middlewares }
-๋ค๋ฅธ ๋ฏธ๋ค์จ์ด์ ๋ํ ๋ ๋ง์ ์ ๋ณด๋ ๋์ค์ [์๋ จ๋ ์ฌ์ฉ์ ์๋ด์: ํฅ์๋ ๋ฏธ๋ค์จ์ด](../advanced/middleware.md){.internal-link target=_blank}์์ ํ์ธํ ์ ์์ต๋๋ค.
+๋ค๋ฅธ ๋ฏธ๋ค์จ์ด์ ๋ํ ๋ ๋ง์ ์ ๋ณด๋ ๋์ค์ [์๋ จ๋ ์ฌ์ฉ์ ์๋ด์: ํฅ์๋ ๋ฏธ๋ค์จ์ด](../advanced/middleware.md)์์ ํ์ธํ ์ ์์ต๋๋ค.
๋ค์ ์น์
์์ ๋ฏธ๋ค์จ์ด๋ก <abbr title="Cross-Origin Resource Sharing - ๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ ">CORS</abbr>๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค.
์ค๋ช
์ ๋ณดํต ๊ธธ์ด์ง๊ณ ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ์๊ธฐ ๋๋ฌธ์, *๊ฒฝ๋ก ์ฒ๋ฆฌ* ์ค๋ช
์ ํจ์ <dfn title="๋ฌธ์ํ์ ์ฌ์ฉ๋๋ ํจ์ ๋ด๋ถ ์ฒซ ํํ์์ ์ฌ๋ฌ ์ค ๋ฌธ์์ด(์ด๋ค ๋ณ์์๋ ํ ๋น๋์ง ์์)">๋
์คํธ๋ง</dfn>์ ์ ์ธํ ์ ์์ผ๋ฉฐ, **FastAPI**๋ ๊ทธ๊ณณ์์ ์ด๋ฅผ ์ฝ์ต๋๋ค.
-๋
์คํธ๋ง์๋ <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>์ ์์ฑํ ์ ์์ผ๋ฉฐ, (๋
์คํธ๋ง์ ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๊ณ ๋ คํ์ฌ) ์ฌ๋ฐ๋ฅด๊ฒ ํด์๋๊ณ ํ์๋ฉ๋๋ค.
+๋
์คํธ๋ง์๋ [Markdown](https://en.wikipedia.org/wiki/Markdown)์ ์์ฑํ ์ ์์ผ๋ฉฐ, (๋
์คํธ๋ง์ ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๊ณ ๋ คํ์ฌ) ์ฌ๋ฐ๋ฅด๊ฒ ํด์๋๊ณ ํ์๋ฉ๋๋ค.
{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *}
๋ ์ค๋๋ ๋ฒ์ ์ด ์๋ค๋ฉด `Annotated`๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
-`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1๊น์ง [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}๋ฅผ ๊ผญ ํ์ธ์.
+`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1๊น์ง [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../deployment/versions.md#upgrading-the-fastapi-versions)๋ฅผ ๊ผญ ํ์ธ์.
///
ํจ์์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก `*`๋ฅผ ์ ๋ฌํ์ธ์.
-ํ์ด์ฌ์ `*`์ผ๋ก ์๋ฌด๊ฒ๋ ํ์ง ์์ง๋ง, ๋ค๋ฐ๋ฅด๋ ๋ชจ๋ ๋งค๊ฐ๋ณ์๋ ํค์๋ ์ธ์(ํค-๊ฐ ์)๋ก ํธ์ถ๋์ด์ผ ํจ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>๋ก๋ ์๋ ค์ ธ ์์ต๋๋ค. ๊ธฐ๋ณธ๊ฐ์ด ์๋๋ผ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
+ํ์ด์ฌ์ `*`์ผ๋ก ์๋ฌด๊ฒ๋ ํ์ง ์์ง๋ง, ๋ค๋ฐ๋ฅด๋ ๋ชจ๋ ๋งค๊ฐ๋ณ์๋ ํค์๋ ์ธ์(ํค-๊ฐ ์)๋ก ํธ์ถ๋์ด์ผ ํจ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ <abbr title="์ถ์ฒ: K-ey W-ord Arg-uments - ํค์๋ ์ธ์"><code>kwargs</code></abbr>๋ก๋ ์๋ ค์ ธ ์์ต๋๋ค. ๊ธฐ๋ณธ๊ฐ์ด ์๋๋ผ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
์ซ์ ๊ฒ์ฆ์ `float` ๊ฐ์๋ ๋์ํฉ๋๋ค.
-์ฌ๊ธฐ์์ <abbr title="greater than"><code>gt</code></abbr>๋ฅผ, <abbr title="greater than or equal"><code>ge</code></abbr>๋ฟ๋ง ์๋๋ผ ์ ์ธํ ์ ์๋ค๋ ์ ์ด ์ค์ํด์ง๋๋ค. ์๋ฅผ ๋ค์ด ๊ฐ์ด `1`๋ณด๋ค ์๋๋ผ๋, ๋ฐ๋์ `0`๋ณด๋ค ์ปค์ผ ํ๋ค๊ณ ์๊ตฌํ ์ ์์ต๋๋ค.
+์ฌ๊ธฐ์์ <abbr title="greater than - ๋ณด๋ค ํผ"><code>gt</code></abbr>๋ฅผ, <abbr title="greater than or equal - ํฌ๊ฑฐ๋ ๊ฐ์"><code>ge</code></abbr>๋ฟ๋ง ์๋๋ผ ์ ์ธํ ์ ์๋ค๋ ์ ์ด ์ค์ํด์ง๋๋ค. ์๋ฅผ ๋ค์ด ๊ฐ์ด `1`๋ณด๋ค ์๋๋ผ๋, ๋ฐ๋์ `0`๋ณด๋ค ์ปค์ผ ํ๋ค๊ณ ์๊ตฌํ ์ ์์ต๋๋ค.
์ฆ, `0.5`๋ ์ ํจํ ๊ฐ์
๋๋ค. ๊ทธ๋ฌ๋ `0.0` ๋๋ `0`์ ๊ทธ๋ ์ง ์์ต๋๋ค.
-<abbr title="less than"><code>lt</code></abbr> ์ญ์ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
+<abbr title="less than - ๋ณด๋ค ์์"><code>lt</code></abbr> ์ญ์ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
## ์์ฝ { #recap }
-`Query`, `Path`(์์ง ๋ณด์ง ๋ชปํ ๋ค๋ฅธ ๊ฒ๋ค๋)๋ฅผ ์ฌ์ฉํ๋ฉด [์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ ๋ฌธ์์ด ๊ฒ์ฆ](query-params-str-validations.md){.internal-link target=_blank}์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์์ด ๊ฒ์ฆ์ ์ ์ธํ ์ ์์ต๋๋ค.
+`Query`, `Path`(์์ง ๋ณด์ง ๋ชปํ ๋ค๋ฅธ ๊ฒ๋ค๋)๋ฅผ ์ฌ์ฉํ๋ฉด [์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์์ ๋ฌธ์์ด ๊ฒ์ฆ](query-params-str-validations.md)์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉํ๋ฐ์ดํฐ์ ๋ฌธ์์ด ๊ฒ์ฆ์ ์ ์ธํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ซ์ ๊ฒ์ฆ ๋ํ ์ ์ธํ ์ ์์ต๋๋ค:
๊ฒฝ๋ก ๋งค๊ฐ๋ณ์ `item_id`์ ๊ฐ์ ํจ์์ `item_id` ์ธ์๋ก ์ ๋ฌ๋ฉ๋๋ค.
-๊ทธ๋์ ์ด ์์ ๋ฅผ ์คํํ๊ณ <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>๋ก ์ด๋ํ๋ฉด, ๋ค์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+๊ทธ๋์ ์ด ์์ ๋ฅผ ์คํํ๊ณ [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo)๋ก ์ด๋ํ๋ฉด, ๋ค์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{"item_id":"foo"}
## ๋ฐ์ดํฐ <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>์ ์ด๋ฉด, ๋ค์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
+์ด ์์ ๋ฅผ ์คํํ๊ณ [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3)์ ์ด๋ฉด, ๋ค์ ์๋ต์ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{"item_id":3}
## ๋ฐ์ดํฐ ๊ฒ์ฆ { #data-validation }
-ํ์ง๋ง ๋ธ๋ผ์ฐ์ ์์ <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>๋ก ์ด๋ํ๋ฉด, ๋ค์๊ณผ ๊ฐ์ HTTP ์ค๋ฅ๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
+ํ์ง๋ง ๋ธ๋ผ์ฐ์ ์์ [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo)๋ก ์ด๋ํ๋ฉด, ๋ค์๊ณผ ๊ฐ์ HTTP ์ค๋ฅ๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
```JSON
{
๊ฒฝ๋ก ๋งค๊ฐ๋ณ์ `item_id`๊ฐ `int`๊ฐ ์๋ `"foo"` ๊ฐ์ ๊ฐ์ก๊ธฐ ๋๋ฌธ์
๋๋ค.
-`int` ๋์ `float`์ ์ ๊ณตํ๋ฉด(์: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>) ๋์ผํ ์ค๋ฅ๊ฐ ๋ํ๋ฉ๋๋ค.
+`int` ๋์ `float`์ ์ ๊ณตํ๋ฉด(์: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2)) ๋์ผํ ์ค๋ฅ๊ฐ ๋ํ๋ฉ๋๋ค.
/// check | ํ์ธ
## ๋ฌธ์ํ { #documentation }
-๊ทธ๋ฆฌ๊ณ ๋ธ๋ผ์ฐ์ ์์ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>๋ฅผ ์ด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ์๋ ๋ํ์ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
+๊ทธ๋ฆฌ๊ณ ๋ธ๋ผ์ฐ์ ์์ [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)๋ฅผ ์ด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ์๋ ๋ํ์ API ๋ฌธ์๋ฅผ ๋ณผ ์ ์์ต๋๋ค:
<img src="/img/tutorial/path-params/image01.png">
## ํ์ค ๊ธฐ๋ฐ์ ์ด์ , ๋์ฒด ๋ฌธ์ { #standards-based-benefits-alternative-documentation }
-๊ทธ๋ฆฌ๊ณ ์์ฑ๋ ์คํค๋ง๋ <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a> ํ์ค์์ ๋์จ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ํธํ๋๋ ๋๊ตฌ๊ฐ ๋ง์ด ์์ต๋๋ค.
+๊ทธ๋ฆฌ๊ณ ์์ฑ๋ ์คํค๋ง๋ [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) ํ์ค์์ ๋์จ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ํธํ๋๋ ๋๊ตฌ๊ฐ ๋ง์ด ์์ต๋๋ค.
-์ด ๋๋ถ์ **FastAPI** ์์ฒด์์ <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>๋ก ์ ์ํ ์ ์๋ (ReDoc์ ์ฌ์ฉํ๋) ๋์ฒด API ๋ฌธ์๋ฅผ ์ ๊ณตํฉ๋๋ค:
+์ด ๋๋ถ์ **FastAPI** ์์ฒด์์ [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)๋ก ์ ์ํ ์ ์๋ (ReDoc์ ์ฌ์ฉํ๋) ๋์ฒด API ๋ฌธ์๋ฅผ ์ ๊ณตํฉ๋๋ค:
<img src="/img/tutorial/path-params/image02.png">
## Pydantic { #pydantic }
-๋ชจ๋ ๋ฐ์ดํฐ ๊ฒ์ฆ์ <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>์ ์ํด ๋ด๋ถ์ ์ผ๋ก ์ํ๋๋ฏ๋ก ์ด๋ก ์ธํ ์ด์ ์ ๋ชจ๋ ์ป์ ์ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ๊ด๋ฆฌ๋ฅผ ์ ๋ฐ๊ณ ์์์ ๋๋ ์ ์์ต๋๋ค.
+๋ชจ๋ ๋ฐ์ดํฐ ๊ฒ์ฆ์ [Pydantic](https://docs.pydantic.dev/)์ ์ํด ๋ด๋ถ์ ์ผ๋ก ์ํ๋๋ฏ๋ก ์ด๋ก ์ธํ ์ด์ ์ ๋ชจ๋ ์ป์ ์ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ๊ด๋ฆฌ๋ฅผ ์ ๋ฐ๊ณ ์์์ ๋๋ ์ ์์ต๋๋ค.
`str`, `float`, `bool`, ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ์ฌ๋ฌ ๋ณต์กํ ๋ฐ์ดํฐ ํ์
์ ์ธ์ ํ ์ ์์ต๋๋ค.
## ์ฌ์ ์ ์ ๊ฐ { #predefined-values }
-๋ง์ฝ *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์*๋ฅผ ๋ฐ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ ์์ง๋ง, ๊ฐ๋ฅํ ์ ํจํ *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์* ๊ฐ๋ค์ ๋ฏธ๋ฆฌ ์ ์ํ๊ณ ์ถ๋ค๋ฉด ํ์ด์ฌ ํ์ค <abbr title="์ด๊ฑฐํ">`Enum`</abbr>์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+๋ง์ฝ *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์*๋ฅผ ๋ฐ๋ *๊ฒฝ๋ก ์ฒ๋ฆฌ*๊ฐ ์์ง๋ง, ๊ฐ๋ฅํ ์ ํจํ *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์* ๊ฐ๋ค์ ๋ฏธ๋ฆฌ ์ ์ํ๊ณ ์ถ๋ค๋ฉด ํ์ด์ฌ ํ์ค <abbr title="Enumeration - ์ด๊ฑฐํ">`Enum`</abbr>์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
### `Enum` ํด๋์ค ์์ฑ { #create-an-enum-class }
### *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์* ์ ์ธ { #declare-a-path-parameter }
-์์ฑํ ์ด๊ฑฐํ ํด๋์ค(`ModelName`)๋ฅผ ์ฌ์ฉํ๋ ํ์
์ด๋
ธํ
์ด์
์ผ๋ก *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์*๋ฅผ ๋ง๋ญ๋๋ค:
+์์ฑํ ์ด๊ฑฐํ ํด๋์ค(`ModelName`)๋ฅผ ์ฌ์ฉํ๋ ํ์
์ด๋
ธํ
์ด์
์ผ๋ก *๊ฒฝ๋ก ๋งค๊ฐ๋ณ์๋ฅผ* ๋ง๋ญ๋๋ค:
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
์ด์ ๋ฒ์ ์ ์ฌ์ฉํ๋ฉด `Annotated`๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
-`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1 ๋ฒ์ ์ผ๋ก [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}๋ฅผ ์งํํ์ธ์.
+`Annotated`๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ต์ 0.95.1 ๋ฒ์ ์ผ๋ก [FastAPI ๋ฒ์ ์
๊ทธ๋ ์ด๋](../deployment/versions.md#upgrading-the-fastapi-versions)๋ฅผ ์งํํ์ธ์.
///
## `q` ๋งค๊ฐ๋ณ์์ ํ์
์ `Annotated` ์ฌ์ฉํ๊ธฐ { #use-annotated-in-the-type-for-the-q-parameter }
-์ด์ ์ [Python ํ์
์๊ฐ](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}์์ `Annotated`๋ฅผ ์ฌ์ฉํด ๋งค๊ฐ๋ณ์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ์ ์๋ค๊ณ ๋ง์๋๋ฆฐ ๊ฒ์ ๊ธฐ์ตํ์๋์?
+์ด์ ์ [Python ํ์
์๊ฐ](../python-types.md#type-hints-with-metadata-annotations)์์ `Annotated`๋ฅผ ์ฌ์ฉํด ๋งค๊ฐ๋ณ์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ์ ์๋ค๊ณ ๋ง์๋๋ฆฐ ๊ฒ์ ๊ธฐ์ตํ์๋์?
์ด์ FastAPI์์ ์ฌ์ฉํ ์ฐจ๋ก์
๋๋ค. ๐
`Annotated`๋ฅผ ์ฌ์ฉํ์ง ์๊ณ **(์ด์ ) ๊ธฐ๋ณธ๊ฐ ์คํ์ผ**์ ์ฌ์ฉํ๋ฉด, FastAPI ์์ด **๋ค๋ฅธ ๊ณณ์์** ํจ์๋ฅผ ํธ์ถํ ๋๋ ์ ๋๋ก ๋์ํ๋๋ก ํจ์์ ์ธ์๋ฅผ ์ ๋ฌํด์ผ ํ๋ค๋ ๊ฒ์ **๊ธฐ์ต**ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๊ฐ์ด ๊ธฐ๋์ ๋ค๋ฅด๊ฒ ๋ฉ๋๋ค(์: `str` ๋์ `QueryInfo` ๊ฐ์ ๊ฒ). ๊ทธ๋ฆฌ๊ณ ํธ์ง๊ธฐ๋ ๊ฒฝ๊ณ ํ์ง ์๊ณ Python๋ ๊ทธ ํจ์๋ฅผ ์คํํ ๋๋ ๋ถํํ์ง ์์ผ๋ฉฐ, ์ค์ง ๋ด๋ถ ๋์์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๋๋ง ๋ฌธ์ ๊ฐ ๋๋ฌ๋ฉ๋๋ค.
-`Annotated`๋ ํ๋ ์ด์์ ๋ฉํ๋ฐ์ดํฐ ์ด๋
ธํ
์ด์
์ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์, ์ด์ <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a> ๊ฐ์ ๋ค๋ฅธ ๋๊ตฌ์์๋ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๐
+`Annotated`๋ ํ๋ ์ด์์ ๋ฉํ๋ฐ์ดํฐ ์ด๋
ธํ
์ด์
์ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์, ์ด์ [Typer](https://typer.tiangolo.com/) ๊ฐ์ ๋ค๋ฅธ ๋๊ตฌ์์๋ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๐
## ๊ฒ์ฆ ๋ ์ถ๊ฐํ๊ธฐ { #add-more-validations }
๊ทธ๋ฐ ๊ฒฝ์ฐ์๋ ์ผ๋ฐ์ ์ธ ๊ฒ์ฆ(์: ๊ฐ์ด `str`์ธ์ง ๊ฒ์ฆํ ๋ค) ์ดํ์ ์ ์ฉ๋๋ **์ปค์คํ
๊ฒ์ฆ ํจ์**๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
-`Annotated` ์์์ <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">Pydantic์ `AfterValidator`</a>๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
+`Annotated` ์์์ [Pydantic์ `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator)๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
/// tip | ํ
-Pydantic์๋ <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a>์ ๊ฐ์ ๋ค๋ฅธ ๊ฒ๋ค๋ ์์ต๋๋ค. ๐ค
+Pydantic์๋ [BeforeValidator](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator)์ ๊ฐ์ ๋ค๋ฅธ ๊ฒ๋ค๋ ์์ต๋๋ค. ๐ค
///
/// tip
-[๊ฒฝ๋ก ๋งค๊ฐ๋ณ์](path-params.md#predefined-values){.internal-link target=_blank}์ ๋ง์ฐฌ๊ฐ์ง๋ก `Enum`์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+[๊ฒฝ๋ก ๋งค๊ฐ๋ณ์](path-params.md#predefined-values)์ ๋ง์ฐฌ๊ฐ์ง๋ก `Enum`์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
/// info | ์ ๋ณด
-์
๋ก๋๋ ํ์ผ์ ์ ๋ฌ๋ฐ๊ธฐ ์ํด ๋จผ์ <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>๋ฅผ ์ค์นํด์ผํฉ๋๋ค.
+์
๋ก๋๋ ํ์ผ์ ์ ๋ฌ๋ฐ๊ธฐ ์ํด ๋จผ์ [`python-multipart`](https://github.com/Kludex/python-multipart)๋ฅผ ์ค์นํด์ผํฉ๋๋ค.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์, ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ์ค์นํ์ธ์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์, ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ์ค์นํ์ธ์:
```console
$ pip install python-multipart
* ์ต๋ ํฌ๊ธฐ ์ ํ๊น์ง๋ง ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ฉฐ, ์ด๋ฅผ ์ด๊ณผํ๋ ๊ฒฝ์ฐ ๋์คํฌ์ ์ ์ฅ๋ฉ๋๋ค.
* ๋ฐ๋ผ์ ์ด๋ฏธ์ง, ๋์์, ํฐ ์ด์ง์ฝ๋์ ๊ฐ์ ๋์ฉ๋ ํ์ผ๋ค์ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ชจํ์ง ์๊ณ ์ฒ๋ฆฌํ๊ธฐ์ ์ ํฉํฉ๋๋ค.
* ์
๋ก๋ ๋ ํ์ผ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
-* <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `async` ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค.
-* file-like object๋ฅผ ํ์๋กํ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ง์ ์ ์ผ๋ก ์ ๋ฌํ ์ ์๋ ํ์ด์ฌ <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
+* [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค.
+* file-like object๋ฅผ ํ์๋กํ๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ง์ ์ ์ผ๋ก ์ ๋ฌํ ์ ์๋ ํ์ด์ฌ [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
### `UploadFile` { #uploadfile }
* `filename` : ๋ฌธ์์ด(`str`)๋ก ๋ ์
๋ก๋๋ ํ์ผ์ ํ์ผ๋ช
์
๋๋ค (์: `myimage.jpg`).
* `content_type` : ๋ฌธ์์ด(`str`)๋ก ๋ ํ์ผ ํ์(MIME type / media type)์
๋๋ค (์:ย `image/jpeg`).
-* `file` : <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> object)์
๋๋ค. ์ด๊ฒ์ "file-like" ๊ฐ์ฒด๋ฅผ ํ์๋กํ๋ ๋ค๋ฅธ ํจ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ง์ ์ ์ผ๋ก ์ ๋ฌํ ์ ์๋ ์ค์ง์ ์ธ ํ์ด์ฌ ํ์ผ ๊ฐ์ฒด์
๋๋ค.
+* `file` : [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) object)์
๋๋ค. ์ด๊ฒ์ "file-like" ๊ฐ์ฒด๋ฅผ ํ์๋กํ๋ ๋ค๋ฅธ ํจ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ง์ ์ ์ผ๋ก ์ ๋ฌํ ์ ์๋ ์ค์ง์ ์ธ ํ์ด์ฌ ํ์ผ ๊ฐ์ฒด์
๋๋ค.
`UploadFile` ์๋ ๋ค์์ `async` ๋ฉ์๋๋ค์ด ์์ต๋๋ค. ์ด๋ค์ ๋ด๋ถ์ ์ธ `SpooledTemporaryFile` ์ ์ฌ์ฉํ์ฌ ํด๋นํ๋ ํ์ผ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
ํ์ง๋ง ํ์ผ์ด ํฌํจ๋ ๊ฒฝ์ฐ, `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>๋ฅผ ์ฐธ๊ณ ํ๊ธฐ ๋ฐ๋๋๋ค.
+์ธ์ฝ๋ฉ๊ณผ ํผ ํ๋์ ๋ํด ๋ ์๊ณ ์ถ๋ค๋ฉด, [<abbr title="Mozilla Developer Network - ๋ชจ์ง๋ผ ๊ฐ๋ฐ์ ๋คํธ์ํฌ">MDN</abbr> ์น ๋ฌธ์์ `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)๋ฅผ ์ฐธ๊ณ ํ๊ธฐ ๋ฐ๋๋๋ค.
///
/// info | ์ ๋ณด
-ํผ์ ์ฌ์ฉํ๋ ค๋ฉด, ๋จผ์ <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>๋ฅผ ์ค์นํ์ธ์.
+ํผ์ ์ฌ์ฉํ๋ ค๋ฉด, ๋จผ์ [`python-multipart`](https://github.com/Kludex/python-multipart)๋ฅผ ์ค์นํ์ธ์.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, ์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ด ์ค์นํ์ธ์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, ์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ด ์ค์นํ์ธ์:
```console
$ pip install python-multipart
`File` ๊ณผ `Form` ์ ์ฌ์ฉํ์ฌ ํ์ผ๊ณผ ํผ ํ๋๋ฅผ ๋์์ ์ ์ํ ์ ์์ต๋๋ค.
-/// info | ์ ๋ณด
+/// info
-์
๋ก๋๋ ํ์ผ ๋ฐ/๋๋ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ผ๋ ค๋ฉด ๋จผ์ <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
+์
๋ก๋๋ ํ์ผ ๋ฐ/๋๋ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ผ๋ ค๋ฉด ๋จผ์ [`python-multipart`](https://github.com/Kludex/python-multipart)๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์ ์ค์นํด์ผ ํฉ๋๋ค. ์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์ ์ค์นํด์ผ ํฉ๋๋ค. ์:
```console
$ pip install python-multipart
๋ํ ์ผ๋ถ ํ์ผ์ `bytes`๋ก, ์ผ๋ถ ํ์ผ์ `UploadFile`๋ก ์ ์ธํ ์ ์์ต๋๋ค.
-/// warning | ๊ฒฝ๊ณ
+/// warning
๋ค์์ `File`๊ณผ `Form` ๋งค๊ฐ๋ณ์๋ฅผ ํ *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์ ์ธํ๋ ๊ฒ์ด ๊ฐ๋ฅํ์ง๋ง, ์์ฒญ์ ๋ณธ๋ฌธ์ด `application/json`๊ฐ ์๋ `multipart/form-data`๋ก ์ธ์ฝ๋ฉ๋๊ธฐ ๋๋ฌธ์ JSON์ผ๋ก ๋ฐ๊ธฐ๋ฅผ ๊ธฐ๋ํ๋ `Body` ํ๋๋ฅผ ํจ๊ป ์ ์ธํ ์๋ ์์ต๋๋ค.
/// info | ์ ๋ณด
-ํผ์ ์ฌ์ฉํ๋ ค๋ฉด, ๋จผ์ <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>๋ฅผ ์ค์นํ์ธ์.
+ํผ์ ์ฌ์ฉํ๋ ค๋ฉด, ๋จผ์ [`python-multipart`](https://github.com/Kludex/python-multipart)๋ฅผ ์ค์นํ์ธ์.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, ์๋์ ๊ฐ์ด ์ค์นํ ์ ์์ต๋๋ค:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ์ค์นํ์ธ์:
```console
$ pip install python-multipart
/// tip | ํ
-ํผ ๋ณธ๋ฌธ์ ์ ์ธํ ๋, รญ\8fยผรฌ\9dยด รฌ\97\86รฌ\9cยผรซยฉยด รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รชยฐ\80 รฌยฟยผรซยฆยฌ รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซ\82\98 รซยณยธรซยฌยธ(JSON) รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซยก\9c รญ\95ยดรฌ\84\9d(interpret)รซ\90\98รชยธยฐ รซ\95\8cรซยฌยธรฌ\97\90 `Form`รฌ\9d\84 รซยช\85รฌ\8b\9cรฌย \81รฌ\9cยผรซยก\9c รฌ\82ยฌรฌ\9aยฉรญ\95ยดรฌ\95ยผ รญ\95ยฉรซ\8b\88รซ\8bยค.
+ํผ ๋ณธ๋ฌธ์ ์ ์ธํ ๋รซ\8a\94 `Form`รฌ\9d\84 รซยช\85รฌ\8b\9cรฌย \81รฌ\9cยผรซยก\9c รฌ\82ยฌรฌ\9aยฉรญ\95ยดรฌ\95ยผ รญ\95ยฉรซ\8b\88รซ\8bยค. รชยทยธรซย \87รฌยง\80 รฌ\95\8aรฌ\9cยผรซยฉยด รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รชยฐ\80 รฌยฟยผรซยฆยฌ รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซ\82\98 รซยณยธรซยฌยธ(JSON) รซยงยครชยฐ\9cรซยณ\80รฌ\88\98รซยก\9c รญ\95ยดรฌ\84\9dรซ\90ยฉรซ\8b\88รซ\8bยค.
///
๊ทธ๋ฌ๋ ํผ์ ํ์ผ์ด ํฌํจ๋ ๊ฒฝ์ฐ, `multipart/form-data`๋ก ์ธ์ฝ๋ฉํฉ๋๋ค. ๋ค์ ์ฅ์์ ํ์ผ ์ฒ๋ฆฌ์ ๋ํด ์ฝ์ ๊ฒ๋๋ค.
-์ด๋ฌํ ์ธ์ฝ๋ฉ ๋ฐ ํผ ํ๋์ ๋ํด ๋ ์ฝ๊ณ ์ถ๋ค๋ฉด, <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>.
+์ด๋ฌํ ์ธ์ฝ๋ฉ ๋ฐ ํผ ํ๋์ ๋ํด ๋ ์ฝ๊ณ ์ถ๋ค๋ฉด, [`POST`์ ๋ํ <abbr title="Mozilla Developer Network - Mozilla ๊ฐ๋ฐ์ ๋คํธ์ํฌ">MDN</abbr> ์น ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
///
* OpenAPI *๊ฒฝ๋ก ์ฒ๋ฆฌ*์ ์๋ต์ **JSON Schema**๋ฅผ ์ถ๊ฐํฉ๋๋ค.
* ์ด๋ **์๋ ๋ฌธ์**์์ ์ฌ์ฉ๋ฉ๋๋ค.
* ๋ํ ์๋ ํด๋ผ์ด์ธํธ ์ฝ๋ ์์ฑ ๋๊ตฌ์์๋ ์ฌ์ฉ๋ฉ๋๋ค.
+* ๋ฐํ๋ ๋ฐ์ดํฐ๋ฅผ Pydantic์ ์ฌ์ฉํด JSON์ผ๋ก **์ง๋ ฌํ**ํฉ๋๋ค. Pydantic์ **Rust**๋ก ์์ฑ๋์ด ์์ด **ํจ์ฌ ๋ ๋น ๋ฆ
๋๋ค**.
ํ์ง๋ง ๊ฐ์ฅ ์ค์ํ ๊ฒ์:
/// info | ์ ๋ณด
-`EmailStr`์ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email-validator`</a>๋ฅผ ์ค์นํ์ธ์.
+`EmailStr`์ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ [`email-validator`](https://github.com/JoshData/python-email-validator)๋ฅผ ์ค์นํ์ธ์.
-[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์ ์ค์นํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ , ํ์ฑํํ ๋ค์ ์ค์นํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
```console
$ pip install email-validator
### ์๋ต์ ์ง์ ๋ฐํํ๊ธฐ { #return-a-response-directly }
-๊ฐ์ฅ ํํ ๊ฒฝ์ฐ๋ [๊ณ ๊ธ ๋ฌธ์์์ ๋์ค์ ์ค๋ช
ํ๋ ๋๋ก Response๋ฅผ ์ง์ ๋ฐํํ๋ ๊ฒ](../advanced/response-directly.md){.internal-link target=_blank}์
๋๋ค.
+๊ฐ์ฅ ํํ ๊ฒฝ์ฐ๋ [๊ณ ๊ธ ๋ฌธ์์์ ๋์ค์ ์ค๋ช
ํ๋ ๋๋ก Response๋ฅผ ์ง์ ๋ฐํํ๋ ๊ฒ](../advanced/response-directly.md)์
๋๋ค.
{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
-`exclude_defaults` ๋ฐ `exclude_none`์ ๋ํด <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydantic ๋ฌธ์</a>์ ์ค๋ช
๋ ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
+`exclude_defaults` ๋ฐ `exclude_none`์ ๋ํด [Pydantic ๋ฌธ์](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict)์ ์ค๋ช
๋ ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
/// info | ์ ๋ณด
-`status_code` ๋ ํ์ด์ฌ์ <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a> ์ ๊ฐ์ `IntEnum` ์ ์
๋ ฅ๋ฐ์ ์๋ ์์ต๋๋ค.
+`status_code` ๋ ํ์ด์ฌ์ [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) ์ ๊ฐ์ `IntEnum` ์ ์
๋ ฅ๋ฐ์ ์๋ ์์ต๋๋ค.
///
/// note | ์ฐธ๊ณ
-รซยง\8cรฌ\95ยฝ HTTP รฌ\83\81รญ\83\9c รฌยฝ\94รซ\93\9cรชยฐ\80 รซยฌยดรฌ\97\87รฌ\9dยธรฌยง\80 รฌ\9dยดรซยฏยธ รฌ\95\8cรชยณย รฌ\9e\88รซ\8bยครซยฉยด, รซ\8bยครฌ\9d\8c รฌ\84ยก์
์ผ๋ก ๋์ด๊ฐ์ธ์.
+รซยง\8cรฌ\95ยฝ HTTP รฌ\83\81รญ\83\9c รฌยฝ\94รซ\93\9cรชยฐ\80 รซยฌยดรฌ\97\87รฌ\9dยธรฌยง\80 รฌ\9dยดรซยฏยธ รฌ\95\8cรชยณย รฌ\9e\88รซ\8bยครซยฉยด, รซ\8bยครฌ\9d\8c รฌ\84ยน์
์ผ๋ก ๋์ด๊ฐ์ธ์.
///
/// 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>๋ฅผ ํ์ธํ์ธ์.
+๊ฐ ์ํ ์ฝ๋์ ์ด๋ค ์ฝ๋๊ฐ ์ด๋ค ์ฉ๋์ธ์ง ๋ ์๊ณ ์ถ๋ค๋ฉด [<abbr title="Mozilla Developer Network - ๋ชจ์ง๋ผ ๊ฐ๋ฐ์ ๋คํธ์ํฌ">MDN</abbr>์ HTTP ์ํ ์ฝ๋์ ๊ดํ ๋ฌธ์](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)๋ฅผ ํ์ธํ์ธ์.
///
## ๊ธฐ๋ณธ๊ฐ ๋ณ๊ฒฝ { #changing-the-default }
-๋์ค์ [๊ณ ๊ธ ์ฌ์ฉ์ ์ง์นจ์](../advanced/response-change-status-code.md){.internal-link target=_blank}์์, ์ฌ๊ธฐ์ ์ ์ธํ๋ ๊ธฐ๋ณธ๊ฐ๊ณผ ๋ค๋ฅธ ์ํ ์ฝ๋๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
+๋์ค์ [๊ณ ๊ธ ์ฌ์ฉ์ ์ง์นจ์](../advanced/response-change-status-code.md)์์, ์ฌ๊ธฐ์ ์ ์ธํ๋ ๊ธฐ๋ณธ๊ฐ๊ณผ ๋ค๋ฅธ ์ํ ์ฝ๋๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ ์ฑ์ด ๋ฐ์ ์ ์๋ ๋ฐ์ดํฐ ์์ ๋ฅผ ์ ์ธํ ์ ์์ต๋๋ค.
-์ฌ๊ธฐ ์ด๋ฅผ ์ํ ๋ช๊ฐ์ง ๋ฐฉ์์ด ์์ต๋๋ค.
+์ฌ๊ธฐ ์ด๋ฅผ ์ํ ๋ช ๊ฐ์ง ๋ฐฉ์์ด ์์ต๋๋ค.
## Pydantic ๋ชจ๋ธ ์ ์ถ๊ฐ JSON ์คํค๋ง ๋ฐ์ดํฐ { #extra-json-schema-data-in-pydantic-models }
์ถ๊ฐ ์ ๋ณด๋ ์๋ ๊ทธ๋๋ก ํด๋น ๋ชจ๋ธ์ **JSON ์คํค๋ง** ๊ฒฐ๊ณผ์ ์ถ๊ฐ๋๊ณ , API ๋ฌธ์์์ ์ฌ์ฉํฉ๋๋ค.
-<a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydantic ๋ฌธ์: Configuration</a>์ ์ค๋ช
๋ ๊ฒ์ฒ๋ผ `dict`๋ฅผ ๋ฐ๋ `model_config` ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+[Pydantic ๋ฌธ์: Configuration](https://docs.pydantic.dev/latest/api/config/)์ ์ค๋ช
๋ ๊ฒ์ฒ๋ผ `dict`๋ฅผ ๋ฐ๋ `model_config` ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
`"json_schema_extra"`๋ฅผ ์์ฑ๋ JSON ์คํค๋ง์์ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๋ณ๋์ ๋ฐ์ดํฐ์ `examples`๋ฅผ ํฌํจํ๋ `dict`์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค.
OpenAPI๋ ๋ํ `example`๊ณผ `examples` ํ๋๋ฅผ ๋ช
์ธ์์ ๋ค๋ฅธ ๋ถ๋ถ์ ์ถ๊ฐํ์ต๋๋ค:
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`Parameter Object` (๋ช
์ธ์์ ์๋)</a>๋ FastAPI์ ๋ค์ ๊ธฐ๋ฅ์์ ์ฐ์์ต๋๋ค:
+* [`Parameter Object` (๋ช
์ธ์์ ์๋)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object)๋ FastAPI์ ๋ค์ ๊ธฐ๋ฅ์์ ์ฐ์์ต๋๋ค:
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
-* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">`Request Body Object`, `Media Type Object` (๋ช
์ธ์์ ์๋)์ `content` ํ๋์ ์๋</a>๋ FastAPI์ ๋ค์ ๊ธฐ๋ฅ์์ ์ฐ์์ต๋๋ค:
+* [`Request Body Object`, `Media Type Object` (๋ช
์ธ์์ ์๋)์ `content` ํ๋์ ์๋](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object)๋ FastAPI์ ๋ค์ ๊ธฐ๋ฅ์์ ์ฐ์์ต๋๋ค:
* `Body()`
* `File()`
* `Form()`
### JSON ์คํค๋ง์ `examples` ํ๋ { #json-schemas-examples-field }
-ํ์ง๋ง, ํ์ JSON ์คํค๋ง๋ <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> ํ๋๋ฅผ ๋ช
์ธ์์ ์ ๋ฒ์ ์ ์ถ๊ฐํ์ต๋๋ค.
+ํ์ง๋ง, ํ์ JSON ์คํค๋ง๋ [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5) ํ๋๋ฅผ ๋ช
์ธ์์ ์ ๋ฒ์ ์ ์ถ๊ฐํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ก์ด OpenAPI 3.1.0์ ์ด ์๋ก์ด `examples` ํ๋๊ฐ ํฌํจ๋ ์ต์ ๋ฒ์ (JSON ์คํค๋ง 2020-12)์ ๊ธฐ๋ฐ์ผ๋ก ํ์ต๋๋ค.
/// info | ์ ๋ณด
-<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> ํจํค์ง๋ `pip install "fastapi[standard]"` ๋ช
๋ น์ ์คํํ๋ฉด **FastAPI**์ ํจ๊ป ์๋์ผ๋ก ์ค์น๋ฉ๋๋ค.
+[`python-multipart`](https://github.com/Kludex/python-multipart) ํจํค์ง๋ `pip install "fastapi[standard]"` ๋ช
๋ น์ ์คํํ๋ฉด **FastAPI**์ ํจ๊ป ์๋์ผ๋ก ์ค์น๋ฉ๋๋ค.
ํ์ง๋ง `pip install fastapi` ๋ช
๋ น์ ์ฌ์ฉํ๋ฉด `python-multipart` ํจํค์ง๊ฐ ๊ธฐ๋ณธ์ผ๋ก ํฌํจ๋์ง ์์ต๋๋ค.
-์๋์ผ๋ก ์ค์นํ๋ ค๋ฉด, [๊ฐ์ ํ๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank}์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, ์๋๋ก ์ค์นํ์ธ์:
+์๋์ผ๋ก ์ค์นํ๋ ค๋ฉด, [๊ฐ์ ํ๊ฒฝ](../../virtual-environments.md)์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์, ์๋๋ก ์ค์นํ์ธ์:
```console
$ pip install python-multipart
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
## ํ์ธํ๊ธฐ { #check-it }
-๋ํํ ๋ฌธ์๋ก ์ด๋ํ์ธ์: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+๋ํํ ๋ฌธ์๋ก ์ด๋ํ์ธ์: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).
๋ค์๊ณผ ๋น์ทํ ํ๋ฉด์ด ๋ณด์ผ ๊ฒ์
๋๋ค:
์๋ URL์ ์ฌ์ฉํ๋ฏ๋ก, ์๋ฅผ ๋ค์ด API๊ฐ `https://example.com/`์ ์๋ค๋ฉด `https://example.com/token`์ ๊ฐ๋ฆฌํต๋๋ค. ํ์ง๋ง API๊ฐ `https://example.com/api/v1/`์ ์๋ค๋ฉด `https://example.com/api/v1/token`์ ๊ฐ๋ฆฌํต๋๋ค.
-์๋ URL์ ์ฌ์ฉํ๋ ๊ฒ์ [ํ๋ก์ ๋ค์์](../../advanced/behind-a-proxy.md){.internal-link target=_blank} ๊ฐ์ ๊ณ ๊ธ ์ฌ์ฉ ์ฌ๋ก์์๋ ์ ํ๋ฆฌ์ผ์ด์
์ด ๊ณ์ ๋์ํ๋๋ก ๋ณด์ฅํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
+์๋ URL์ ์ฌ์ฉํ๋ ๊ฒ์ [ํ๋ก์ ๋ค์์](../../advanced/behind-a-proxy.md) ๊ฐ์ ๊ณ ๊ธ ์ฌ์ฉ ์ฌ๋ก์์๋ ์ ํ๋ฆฌ์ผ์ด์
์ด ๊ณ์ ๋์ํ๋๋ก ๋ณด์ฅํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
///
1์ฃผ์ผ ๋ค์๋ ํ ํฐ์ด ๋ง๋ฃ๋๊ณ ์ฌ์ฉ์๋ ์ธ๊ฐ๋์ง ์์ผ๋ฏ๋ก ์ ํ ํฐ์ ๋ฐ๊ธฐ ์ํด ๋ค์ ๋ก๊ทธ์ธํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์(๋๋ ์ 3์)๊ฐ ๋ง๋ฃ ์๊ฐ์ ๋ฐ๊พธ๊ธฐ ์ํด ํ ํฐ์ ์์ ํ๋ ค๊ณ ํ๋ฉด, ์๋ช
์ด ์ผ์นํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์์์ฑ ์ ์์ต๋๋ค.
-JWT ํ ํฐ์ ์ง์ ๋ค๋ค๋ณด๊ณ ๋์ ๋ฐฉ์์ ํ์ธํด๋ณด๊ณ ์ถ๋ค๋ฉด <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>๋ฅผ ํ์ธํ์ญ์์ค.
+JWT ํ ํฐ์ ์ง์ ๋ค๋ค๋ณด๊ณ ๋์ ๋ฐฉ์์ ํ์ธํด๋ณด๊ณ ์ถ๋ค๋ฉด [https://jwt.io](https://jwt.io/)๋ฅผ ํ์ธํ์ญ์์ค.
## `PyJWT` ์ค์น { #install-pyjwt }
Python์์ JWT ํ ํฐ์ ์์ฑํ๊ณ ๊ฒ์ฆํ๋ ค๋ฉด `PyJWT`๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
-[๊ฐ์ํ๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank}์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์ `pyjwt`๋ฅผ ์ค์นํ์ญ์์ค:
+[๊ฐ์ํ๊ฒฝ](../../virtual-environments.md)์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์ `pyjwt`๋ฅผ ์ค์นํ์ญ์์ค:
<div class="termy">
RSA๋ ECDSA ๊ฐ์ ์ ์ ์๋ช
์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ๊ณํ์ด๋ผ๋ฉด, cryptography ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ์ธ `pyjwt[crypto]`๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
-์์ธํ ๋ด์ฉ์ <a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT Installation docs</a>์์ ํ์ธํ ์ ์์ต๋๋ค.
+์์ธํ ๋ด์ฉ์ [PyJWT ์ค์น ๋ฌธ์](https://pyjwt.readthedocs.io/en/latest/installation.html)์์ ํ์ธํ ์ ์์ต๋๋ค.
///
์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ์ "Argon2"์
๋๋ค.
-[๊ฐ์ํ๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank}์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์ Argon2์ ํจ๊ป pwdlib๋ฅผ ์ค์นํ์ญ์์ค:
+[๊ฐ์ํ๊ฒฝ](../../virtual-environments.md)์ ๋ง๋ค๊ณ ํ์ฑํํ ๋ค์ Argon2์ ํจ๊ป pwdlib๋ฅผ ์ค์นํ์ญ์์ค:
<div class="termy">
## ํ์ธํ๊ธฐ { #check-it }
-์๋ฒ๋ฅผ ์คํํ๊ณ ๋ฌธ์๋ก ์ด๋ํ์ญ์์ค: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+์๋ฒ๋ฅผ ์คํํ๊ณ ๋ฌธ์๋ก ์ด๋ํ์ญ์์ค: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).
๋ค์๊ณผ ๊ฐ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๊ฐ ๋ณด์ผ ๊ฒ์
๋๋ค:
/// info | ์ ๋ณด
-`**user_dict`์ ๋ํ ์์ธํ ์ค๋ช
์ [**์ถ๊ฐ ๋ชจ๋ธ** ๋ฌธ์](../extra-models.md#about-user-in-dict){.internal-link target=_blank}๋ฅผ ๋ค์ ํ์ธํด๋ณด์ธ์.
+`**user_dict`์ ๋ํ ์์ธํ ์ค๋ช
์ [**์ถ๊ฐ ๋ชจ๋ธ** ๋ฌธ์](../extra-models.md#about-user-in-dict)๋ฅผ ๋ค์ ํ์ธํด๋ณด์ธ์.
///
## ํ์ธํ๊ธฐ { #see-it-in-action }
-๋ํํ ๋ฌธ์ ์ด๊ธฐ: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+๋ํํ ๋ฌธ์ ์ด๊ธฐ: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).
### ์ธ์ฆํ๊ธฐ { #authenticate }
**FastAPI**์์ SQL(๊ด๊ณํ) ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ์ ํ์๊ฐ ์๋๋๋ค. ํ์ง๋ง ์ฌ๋ฌ๋ถ์ด ์ํ๋ **์ด๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ** ์ฌ์ฉํ ์ ์์ต๋๋ค.
-์ฌ๊ธฐ์๋ <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel</a>์ ์ฌ์ฉํ๋ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
+์ฌ๊ธฐ์๋ [SQLModel](https://sqlmodel.tiangolo.com/)์ ์ฌ์ฉํ๋ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
-**SQLModel**์ <a href="https://www.sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a>์ Pydantic์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋์์ต๋๋ค. **SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค**๋ฅผ ์ฌ์ฉํด์ผ ํ๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์๋ฒฝํ ์ด์ธ๋ฆฌ๋๋ก **FastAPI**์ ๊ฐ์ ์ ์์๊ฐ ๋ง๋ ๋๊ตฌ์
๋๋ค.
+**SQLModel**์ [SQLAlchemy](https://www.sqlalchemy.org/)์ Pydantic์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋์์ต๋๋ค. **SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค**๋ฅผ ์ฌ์ฉํด์ผ ํ๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์๋ฒฝํ ์ด์ธ๋ฆฌ๋๋ก **FastAPI**์ ๊ฐ์ ์ ์์๊ฐ ๋ง๋ ๋๊ตฌ์
๋๋ค.
/// tip | ํ
/// tip | ํ
-ํ๋ก ํธ์๋์ ๋ ๋ง์ ๋๊ตฌ๋ฅผ ํฌํจํ์ฌ **FastAPI**์ **PostgreSQL**์ ํฌํจํ ๊ณต์ ํ๋ก์ ํธ ์์ฑ๊ธฐ๊ฐ ์์ต๋๋ค: <a href="https://github.com/fastapi/full-stack-fastapi-template" class="external-link" target="_blank">https://github.com/fastapi/full-stack-fastapi-template</a>
+ํ๋ก ํธ์๋์ ๋ ๋ง์ ๋๊ตฌ๋ฅผ ํฌํจํ์ฌ **FastAPI**์ **PostgreSQL**์ ํฌํจํ ๊ณต์ ํ๋ก์ ํธ ์์ฑ๊ธฐ๊ฐ ์์ต๋๋ค: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template)
///
-์ด ํํ ๋ฆฌ์ผ์ ๋งค์ฐ ๊ฐ๋จํ๊ณ ์งง์ต๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ณธ ๊ฐ๋
, SQL, ๋๋ ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋ํด ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด, <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel ๋ฌธ์</a>๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+์ด ํํ ๋ฆฌ์ผ์ ๋งค์ฐ ๊ฐ๋จํ๊ณ ์งง์ต๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ณธ ๊ฐ๋
, SQL, ๋๋ ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋ํด ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด, [SQLModel ๋ฌธ์](https://sqlmodel.tiangolo.com/)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
## `SQLModel` ์ค์นํ๊ธฐ { #install-sqlmodel }
-๋จผ์ , [๊ฐ์ ํ๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, `sqlmodel`์ ์ค์นํ์ธ์:
+๋จผ์ , [๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ์์ฑํ๊ณ ํ์ฑํํ ๋ค์, `sqlmodel`์ ์ค์นํ์ธ์:
<div class="termy">
* `Field(primary_key=True)`๋ SQLModel์ `id`๊ฐ SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ **๊ธฐ๋ณธ ํค**์์ ์๋ ค์ค๋๋ค (SQL ๊ธฐ๋ณธ ํค์ ๋ํ ์์ธํ ๋ด์ฉ์ SQLModel ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์).
- **์ฐธ๊ณ :** ๊ธฐ๋ณธ ํค ํ๋์ `int | None`์ ์ฌ์ฉํ๋ ์ด์ ๋, Python ์ฝ๋์์ *`id` ์์ด ๊ฐ์ฒด๋ฅผ ์์ฑ*ํ ์ ์๊ฒ ํ๊ธฐ ์ํด์์
๋๋ค(`id=None`). ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ *์ ์ฅํ ๋ ์์ฑํด ์ค ๊ฒ*์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค. SQLModel์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ `id`๋ฅผ ์ ๊ณตํ๋ค๋ ๊ฒ์ ์ดํดํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง์์ *ํด๋น ์ด์ null์ด ์๋ `INTEGER`*๋ก ์ ์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ <a href="https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id" class="external-link" target="_blank">๊ธฐ๋ณธ ํค์ ๋ํ SQLModel ๋ฌธ์</a>๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+ **์ฐธ๊ณ :** ๊ธฐ๋ณธ ํค ํ๋์ `int | None`์ ์ฌ์ฉํ๋ ์ด์ ๋, Python ์ฝ๋์์ *`id` ์์ด ๊ฐ์ฒด๋ฅผ ์์ฑ*ํ ์ ์๊ฒ ํ๊ธฐ ์ํด์์
๋๋ค(`id=None`). ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ *์ ์ฅํ ๋ ์์ฑํด ์ค ๊ฒ*์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค. SQLModel์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ `id`๋ฅผ ์ ๊ณตํ๋ค๋ ๊ฒ์ ์ดํดํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง์์ *ํด๋น ์ด์ null์ด ์๋ `INTEGER`*๋ก ์ ์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ [๊ธฐ๋ณธ ํค์ ๋ํ SQLModel ๋ฌธ์](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
* `Field(index=True)`๋ SQLModel์ ํด๋น ์ด์ ๋ํด **SQL ์ธ๋ฑ์ค**๋ฅผ ์์ฑํ๋๋ก ์ง์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ด ์ด๋ก ํํฐ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋ ๋ ๋น ๋ฅด๊ฒ ์กฐํํ ์ ์์ต๋๋ค.
/// tip | ํ
-SQLModel์ Alembic์ ๊ฐ์ธ๋ ๋ง์ด๊ทธ๋ ์ด์
์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํ ์์ ์
๋๋ค. ํ์ง๋ง ํ์ฌ <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a>์ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+SQLModel์ Alembic์ ๊ฐ์ธ๋ ๋ง์ด๊ทธ๋ ์ด์
์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํ ์์ ์
๋๋ค. ํ์ง๋ง ํ์ฌ [Alembic](https://alembic.sqlalchemy.org/en/latest/)์ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
<div class="termy">
```console
-$ fastapi dev main.py
+$ fastapi dev
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
## ์์ฝ { #recap }
-<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a>์ ์ฌ์ฉํ์ฌ SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๊ณ , *๋ฐ์ดํฐ ๋ชจ๋ธ* ๋ฐ *ํ
์ด๋ธ ๋ชจ๋ธ*๋ก ์ฝ๋๋ฅผ ๊ฐ์ํํ ์ ์์ต๋๋ค.
+[**SQLModel**](https://sqlmodel.tiangolo.com/)์ ์ฌ์ฉํ์ฌ SQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๊ณ , *๋ฐ์ดํฐ ๋ชจ๋ธ* ๋ฐ *ํ
์ด๋ธ ๋ชจ๋ธ*๋ก ์ฝ๋๋ฅผ ๊ฐ์ํํ ์ ์์ต๋๋ค.
-๋ ๋ง์ ๋ด์ฉ์ ๋ฐฐ์ฐ๋ ค๋ฉด **SQLModel** ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์. **FastAPI**์ ํจ๊ป SQLModel์ ์ฌ์ฉํ๋ ๋ ๊ธด ๋ฏธ๋ <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">ํํ ๋ฆฌ์ผ</a>๋ ์์ต๋๋ค. ๐
+๋ ๋ง์ ๋ด์ฉ์ ๋ฐฐ์ฐ๋ ค๋ฉด **SQLModel** ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์. **FastAPI**์ ํจ๊ป SQLModel์ ์ฌ์ฉํ๋ ๋ ๊ธด ๋ฏธ๋ [ํํ ๋ฆฌ์ผ](https://sqlmodel.tiangolo.com/tutorial/fastapi/)๋ ์์ต๋๋ค. ๐
๋ง์ดํธ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์์ ํ ๋
๋ฆฝ์ ์ด๋ฏ๋ก `APIRouter`๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ๋ ๋ค๋ฆ
๋๋ค. ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
์ OpenAPI ๋ฐ ๋ฌธ์์๋ ๋ง์ดํธ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ด์ฉ ๋ฑ์ด ํฌํจ๋์ง ์์ต๋๋ค.
-์์ธํ ๋ด์ฉ์ [๊ณ ๊ธ ์ฌ์ฉ์ ๊ฐ์ด๋](../advanced/index.md){.internal-link target=_blank}์์ ํ์ธํ ์ ์์ต๋๋ค.
+์์ธํ ๋ด์ฉ์ [๊ณ ๊ธ ์ฌ์ฉ์ ๊ฐ์ด๋](../advanced/index.md)์์ ํ์ธํ ์ ์์ต๋๋ค.
## ์ธ๋ถ์ฌํญ { #details }
## ์ถ๊ฐ ์ ๋ณด { #more-info }
-์์ธํ ๋ด์ฉ๊ณผ ์ต์
์ <a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">Starlette์ ์ ์ ํ์ผ ๋ฌธ์</a>๋ฅผ ํ์ธํ์ธ์.
+์์ธํ ๋ด์ฉ๊ณผ ์ต์
์ [Starlette์ ์ ์ ํ์ผ ๋ฌธ์](https://www.starlette.dev/staticfiles/)๋ฅผ ํ์ธํ์ธ์.
# ํ
์คํ
{ #testing }
-<a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a> ๋๋ถ์ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ ํ
์คํธํ๋ ์ผ์ ์ฝ๊ณ ์ฆ๊ฑฐ์ด ์ผ์ด ๋์์ต๋๋ค.
+[Starlette](https://www.starlette.dev/testclient/) ๋๋ถ์ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ ํ
์คํธํ๋ ์ผ์ ์ฝ๊ณ ์ฆ๊ฑฐ์ด ์ผ์ด ๋์์ต๋๋ค.
-์ด๋ <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ์ด๋ Requests๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์น์ํ๊ณ ์ง๊ด์ ์
๋๋ค.
+์ด๋ [HTTPX](https://www.python-httpx.org)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ์ด๋ Requests๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์น์ํ๊ณ ์ง๊ด์ ์
๋๋ค.
-์ด๋ฅผ ์ฌ์ฉํ๋ฉด **FastAPI**์์ <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a>๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+์ด๋ฅผ ์ฌ์ฉํ๋ฉด **FastAPI**์์ [pytest](https://docs.pytest.org/)๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
## `TestClient` ์ฌ์ฉํ๊ธฐ { #using-testclient }
/// info | ์ ๋ณด
-`TestClient` ์ฌ์ฉํ๋ ค๋ฉด, ์ฐ์ <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
+`TestClient` ์ฌ์ฉํ๋ ค๋ฉด, ์ฐ์ [`httpx`](https://www.python-httpx.org)๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค.
-[virtual environment](../virtual-environments.md){.internal-link target=_blank}๋ฅผ ๋ง๋ค๊ณ , ํ์ฑํ ์ํจ ๋ค์ ์ค์นํ์ธ์. ์์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ๋ง๋ค๊ณ , ํ์ฑํํ ๋ค ์ค์นํ์ธ์. ์์:
```console
$ pip install httpx
/// tip | ํ
-FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ ์ธ์๋ ํ
์คํธ์์ `async` ํจ์๋ฅผ ํธ์ถํ๊ณ ์ถ๋ค๋ฉด (์: ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํจ์), ์ฌํ ํํ ๋ฆฌ์ผ์ [Async Tests](../advanced/async-tests.md){.internal-link target=_blank}๋ฅผ ์ฐธ์กฐํ์ธ์.
+FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ ์ธ์๋ ํ
์คํธ์์ `async` ํจ์๋ฅผ ํธ์ถํ๊ณ ์ถ๋ค๋ฉด (์: ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํจ์), ์ฌํ ํํ ๋ฆฌ์ผ์ [๋น๋๊ธฐ ํ
์คํธ](../advanced/async-tests.md)๋ฅผ ์ฐธ์กฐํ์ธ์.
///
### **FastAPI** app ํ์ผ { #fastapi-app-file }
-[Bigger Applications](bigger-applications.md){.internal-link target=_blank}์ ๋ฌ์ฌ๋ ํ์ผ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ผ๋ก ๊ฐ์ ํด๋ด
์๋ค.
+[๋ ํฐ ์ ํ๋ฆฌ์ผ์ด์
](bigger-applications.md)์ ๋ฌ์ฌ๋ ํ์ผ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ผ๋ก ๊ฐ์ ํด๋ด
์๋ค.
```
.
* *ํค๋*๋ฅผ ์ ๋ฌํ๋ ค๋ฉด, `headers` ํ๋ผ๋ฏธํฐ์ `dict`๋ฅผ ์ ๋ฌํ๋ค.
* *์ฟ ํค*๋ฅผ ์ ๋ฌํ๋ ค๋ฉด, `cookies` ํ๋ผ๋ฏธํฐ์ `dict`๋ฅผ ์ ๋ฌํ๋ค.
-๋ฐฑ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๋ณด๋ด๋์ง ์ ๋ณด๋ฅผ ๋ ์ป์ผ๋ ค๋ฉด (`httpx` ํน์ `TestClient`๋ฅผ ์ด์ฉํด์) <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX documentation</a>๋ฅผ ํ์ธํ์ธ์.
+๋ฐฑ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๋ณด๋ด๋์ง ์ ๋ณด๋ฅผ ๋ ์ป์ผ๋ ค๋ฉด (`httpx` ํน์ `TestClient`๋ฅผ ์ด์ฉํด์) [HTTPX ๋ฌธ์](https://www.python-httpx.org)๋ฅผ ํ์ธํ์ธ์.
/// info | ์ ๋ณด
`TestClient`๋ Pydantic ๋ชจ๋ธ์ด ์๋๋ผ JSON์ผ๋ก ๋ณํ๋ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ต๋๋ค.
-๋ง์ฝ ํ
์คํธ ์ค Pydantic ๋ชจ๋ธ์ ๊ฐ์ง๊ณ ์๊ณ ํ
์คํธ ์ค์ ์ ํ๋ฆฌ์ผ์ด์
์ผ๋ก ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ณ ์ถ๋ค๋ฉด, [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}์ ์ค๋ช
๋์ด ์๋ `jsonable_encoder`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+๋ง์ฝ ํ
์คํธ ์ค Pydantic ๋ชจ๋ธ์ ๊ฐ์ง๊ณ ์๊ณ ํ
์คํธ ์ค์ ์ ํ๋ฆฌ์ผ์ด์
์ผ๋ก ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ณ ์ถ๋ค๋ฉด, [JSON ํธํ ์ธ์ฝ๋](encoder.md)์ ์ค๋ช
๋์ด ์๋ `jsonable_encoder`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
///
๊ทธ ํ์๋ `pytest`๋ฅผ ์ค์นํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
-[virtual environment](../virtual-environments.md){.internal-link target=_blank}๋ฅผ ๋ง๋ค๊ณ , ํ์ฑํ ์ํจ ๋ค์ ์ค์นํ์ธ์. ์์:
+[๊ฐ์ ํ๊ฒฝ](../virtual-environments.md)์ ๋ง๋ค๊ณ , ํ์ฑํ ์ํจ ๋ค์ ์ค์นํ์ธ์. ์์:
<div class="termy">
์ด ํ์ด์ง์์๋ **๊ฐ์ ํ๊ฒฝ**์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์๋ ๋ฐฉ์์ ์๋ ค๋๋ฆฝ๋๋ค.
-Python ์ค์น๊น์ง ํฌํจํด **๋ชจ๋ ๊ฒ์ ๊ด๋ฆฌํด์ฃผ๋ ๋๊ตฌ**๋ฅผ ๋์
ํ ์ค๋น๊ฐ ๋์๋ค๋ฉด <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>๋ฅผ ์ฌ์ฉํด ๋ณด์ธ์.
+Python ์ค์น๊น์ง ํฌํจํด **๋ชจ๋ ๊ฒ์ ๊ด๋ฆฌํด์ฃผ๋ ๋๊ตฌ**๋ฅผ ๋์
ํ ์ค๋น๊ฐ ๋์๋ค๋ฉด [uv](https://github.com/astral-sh/uv)๋ฅผ ์ฌ์ฉํด ๋ณด์ธ์.
///
//// tab | `uv`
-<a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>๊ฐ ์ค์น๋์ด ์๋ค๋ฉด, ์ด๋ฅผ ์ฌ์ฉํด ๊ฐ์ ํ๊ฒฝ์ ์์ฑํ ์ ์์ต๋๋ค.
+[`uv`](https://github.com/astral-sh/uv)๊ฐ ์ค์น๋์ด ์๋ค๋ฉด, ์ด๋ฅผ ์ฌ์ฉํด ๊ฐ์ ํ๊ฒฝ์ ์์ฑํ ์ ์์ต๋๋ค.
<div class="termy">
//// tab | Windows Bash
-๋๋ Windows์์ Bash(์: <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>)๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
+๋๋ Windows์์ Bash(์: [Git Bash](https://gitforwindows.org/))๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
<div class="termy">
/// tip
-<a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, `pip` ๋์ `uv`๋ก ์ค์นํ๊ฒ ๋๋ฏ๋ก `pip`์ ์
๊ทธ๋ ์ด๋ํ ํ์๊ฐ ์์ต๋๋ค. ๐
+[`uv`](https://github.com/astral-sh/uv)๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, `pip` ๋์ `uv`๋ก ์ค์นํ๊ฒ ๋๋ฏ๋ก `pip`์ ์
๊ทธ๋ ์ด๋ํ ํ์๊ฐ ์์ต๋๋ค. ๐
///
/// tip
-<a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>๋ก ๊ฐ์ ํ๊ฒฝ์ ๋ง๋ค์๋ค๋ฉด, ์ด๋ฏธ ์๋์ผ๋ก ์ฒ๋ฆฌ๋์ด ์์ผ๋ฏ๋ก ์ด ๋จ๊ณ๋ ๊ฑด๋๋ฐ์ด๋ ๋ฉ๋๋ค. ๐
+[`uv`](https://github.com/astral-sh/uv)๋ก ๊ฐ์ ํ๊ฒฝ์ ๋ง๋ค์๋ค๋ฉด, ์ด๋ฏธ ์๋์ผ๋ก ์ฒ๋ฆฌ๋์ด ์์ผ๋ฏ๋ก ์ด ๋จ๊ณ๋ ๊ฑด๋๋ฐ์ด๋ ๋ฉ๋๋ค. ๐
///
//// tab | `uv`
-<a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>๊ฐ ์๋ค๋ฉด:
+[`uv`](https://github.com/astral-sh/uv)๊ฐ ์๋ค๋ฉด:
<div class="termy">
//// tab | `uv`
-<a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>๊ฐ ์๋ค๋ฉด:
+[`uv`](https://github.com/astral-sh/uv)๊ฐ ์๋ค๋ฉด:
<div class="termy">
์๋ฅผ ๋ค๋ฉด:
-* <a href="https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment" class="external-link" target="_blank">VS Code</a>
-* <a href="https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html" class="external-link" target="_blank">PyCharm</a>
+* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment)
+* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html)
/// tip
## ๊ฐ์ ํ๊ฒฝ์ ์ ์ฌ์ฉํ๋์ { #why-virtual-environments }
-FastAPI๋ก ์์
ํ๋ ค๋ฉด <a href="https://www.python.org/" class="external-link" target="_blank">Python</a>์ ์ค์นํด์ผ ํฉ๋๋ค.
+FastAPI๋ก ์์
ํ๋ ค๋ฉด [Python](https://www.python.org/)์ ์ค์นํด์ผ ํฉ๋๋ค.
๊ทธ ๋ค์ FastAPI์ ์ฌ์ฉํ๋ ค๋ ๋ค๋ฅธ **ํจํค์ง**๋ฅผ **์ค์น**ํด์ผ ํฉ๋๋ค.
</div>
-FastAPI ์ฝ๋๋ฅผ ๋ด์ ์์ถ ํ์ผ์ ๋ค์ด๋ก๋ํฉ๋๋ค. ๋ณดํต <a href="https://pypi.org/project/fastapi/" class="external-link" target="_blank">PyPI</a>์์ ๋ฐ์ต๋๋ค.
+FastAPI ์ฝ๋๋ฅผ ๋ด์ ์์ถ ํ์ผ์ ๋ค์ด๋ก๋ํฉ๋๋ค. ๋ณดํต [PyPI](https://pypi.org/project/fastapi/)์์ ๋ฐ์ต๋๋ค.
๋ํ FastAPI๊ฐ ์์กดํ๋ ๋ค๋ฅธ ํจํค์ง๋ค์ ํ์ผ๋ **๋ค์ด๋ก๋**ํฉ๋๋ค.
//// tab | Windows Bash
-๋๋ Windows์์ Bash(์: <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>)๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
+๋๋ Windows์์ Bash(์: [Git Bash](https://gitforwindows.org/))๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ:
<div class="termy">
////
-๋ค์ ๋ช
๋ น์ด๋ค์์ ์ฌ์ฉํ ์ ์๋ ๋ช๋ช [ํ๊ฒฝ ๋ณ์](environment-variables.md){.internal-link target=_blank}๋ฅผ ์์ฑํ๊ฑฐ๋ ์์ ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
+๋ค์ ๋ช
๋ น์ด๋ค์์ ์ฌ์ฉํ ์ ์๋ ๋ช๋ช [ํ๊ฒฝ ๋ณ์](environment-variables.md)๋ฅผ ์์ฑํ๊ฑฐ๋ ์์ ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๊ทธ ๋ณ์ ์ค ํ๋๊ฐ `PATH` ๋ณ์์
๋๋ค.
/// tip
-`PATH` ํ๊ฒฝ ๋ณ์์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด [ํ๊ฒฝ ๋ณ์](environment-variables.md#path-environment-variable){.internal-link target=_blank} ์น์
์ ์ฐธ๊ณ ํ์ธ์.
+`PATH` ํ๊ฒฝ ๋ณ์์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด [ํ๊ฒฝ ๋ณ์](environment-variables.md#path-environment-variable) ์น์
์ ์ฐธ๊ณ ํ์ธ์.
///
๊ฐ์ ํ๊ฒฝ, ํจํค์ง ์์กด์ฑ(requirements), ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์๋ ๋ง์ **๋์**์ด ์์ต๋๋ค.
-์ค๋น๊ฐ ๋์๊ณ **ํ๋ก์ ํธ ์ ์ฒด**, ํจํค์ง ์์กด์ฑ, ๊ฐ์ ํ๊ฒฝ ๋ฑ์ **๊ด๋ฆฌ**ํ๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>๋ฅผ ์ฌ์ฉํด ๋ณด์๊ธธ ๊ถํฉ๋๋ค.
+์ค๋น๊ฐ ๋์๊ณ **ํ๋ก์ ํธ ์ ์ฒด**, ํจํค์ง ์์กด์ฑ, ๊ฐ์ ํ๊ฒฝ ๋ฑ์ **๊ด๋ฆฌ**ํ๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด [uv](https://github.com/astral-sh/uv)๋ฅผ ์ฌ์ฉํด ๋ณด์๊ธธ ๊ถํฉ๋๋ค.
`uv`๋ ๋ง์ ์ผ์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด: