]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
๐ŸŒ Update translations for ko (add-missing) (#14699)
authorSebastiรกn Ramรญrez <tiangolo@gmail.com>
Fri, 16 Jan 2026 11:54:01 +0000 (03:54 -0800)
committerGitHub <noreply@github.com>
Fri, 16 Jan 2026 11:54:01 +0000 (12:54 +0100)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
34 files changed:
docs/ko/docs/_llm-test.md [new file with mode: 0644]
docs/ko/docs/advanced/additional-responses.md [new file with mode: 0644]
docs/ko/docs/advanced/behind-a-proxy.md [new file with mode: 0644]
docs/ko/docs/advanced/dataclasses.md [new file with mode: 0644]
docs/ko/docs/advanced/generate-clients.md [new file with mode: 0644]
docs/ko/docs/advanced/middleware.md [new file with mode: 0644]
docs/ko/docs/advanced/openapi-callbacks.md [new file with mode: 0644]
docs/ko/docs/advanced/openapi-webhooks.md [new file with mode: 0644]
docs/ko/docs/advanced/path-operation-advanced-configuration.md [new file with mode: 0644]
docs/ko/docs/advanced/security/http-basic-auth.md [new file with mode: 0644]
docs/ko/docs/advanced/security/index.md [new file with mode: 0644]
docs/ko/docs/advanced/security/oauth2-scopes.md [new file with mode: 0644]
docs/ko/docs/advanced/settings.md [new file with mode: 0644]
docs/ko/docs/alternatives.md [new file with mode: 0644]
docs/ko/docs/deployment/concepts.md [new file with mode: 0644]
docs/ko/docs/deployment/fastapicloud.md [new file with mode: 0644]
docs/ko/docs/deployment/https.md [new file with mode: 0644]
docs/ko/docs/deployment/manually.md [new file with mode: 0644]
docs/ko/docs/how-to/authentication-error-status-code.md [new file with mode: 0644]
docs/ko/docs/how-to/custom-docs-ui-assets.md [new file with mode: 0644]
docs/ko/docs/how-to/custom-request-and-route.md [new file with mode: 0644]
docs/ko/docs/how-to/extending-openapi.md [new file with mode: 0644]
docs/ko/docs/how-to/general.md [new file with mode: 0644]
docs/ko/docs/how-to/graphql.md [new file with mode: 0644]
docs/ko/docs/how-to/index.md [new file with mode: 0644]
docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md [new file with mode: 0644]
docs/ko/docs/how-to/separate-openapi-schemas.md [new file with mode: 0644]
docs/ko/docs/how-to/testing-database.md [new file with mode: 0644]
docs/ko/docs/tutorial/bigger-applications.md [new file with mode: 0644]
docs/ko/docs/tutorial/body-updates.md [new file with mode: 0644]
docs/ko/docs/tutorial/dependencies/sub-dependencies.md [new file with mode: 0644]
docs/ko/docs/tutorial/handling-errors.md [new file with mode: 0644]
docs/ko/docs/tutorial/security/first-steps.md [new file with mode: 0644]
docs/ko/docs/tutorial/security/index.md [new file with mode: 0644]

diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md
new file mode 100644 (file)
index 0000000..1b828c6
--- /dev/null
@@ -0,0 +1,503 @@
+# LLM ํ…Œ์ŠคํŠธ ํŒŒ์ผ { #llm-test-file }
+
+์ด ๋ฌธ์„œ๋Š” ๋ฌธ์„œ๋ฅผ ๋ฒˆ์—ญํ•˜๋Š” <abbr title="Large Language Model - ๋Œ€๊ทœ๋ชจ ์–ธ์–ด ๋ชจ๋ธ">LLM</abbr>์ด `scripts/translate.py`์˜ `general_prompt`์™€ `docs/{language code}/llm-prompt.md`์˜ ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ดํ•ดํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋Š” `general_prompt`์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์— ์ถ”๊ฐ€๋œ ํ…Œ์ŠคํŠธ๋Š” ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ `docs/{language code}/llm-prompt.md`๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
+* ์ด ๋ฌธ์„œ๋ฅผ ์›ํ•˜๋Š” ๋Œ€์ƒ ์–ธ์–ด๋กœ ์ƒˆ๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `translate.py`์˜ `translate-page` ๋ช…๋ น). ๊ทธ๋Ÿฌ๋ฉด `docs/{language code}/docs/_llm-test.md` ์•„๋ž˜์— ๋ฒˆ์—ญ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
+* ๋ฒˆ์—ญ์—์„œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
+* ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ, ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ, ๋˜๋Š” ์˜์–ด ๋ฌธ์„œ๋ฅผ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.
+* ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฒˆ์—ญ์—์„œ ๋‚จ์•„ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ˆ˜์ •ํ•ด ์ข‹์€ ๋ฒˆ์—ญ์ด ๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
+* ์ข‹์€ ๋ฒˆ์—ญ์„ ๋‘” ์ƒํƒœ์—์„œ ๋‹ค์‹œ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค. ์ด์ƒ์ ์ธ ๊ฒฐ๊ณผ๋Š” LLM์ด ๋” ์ด์ƒ ๋ฒˆ์—ญ์— ๋ณ€๊ฒฝ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์™€ ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ตœ์„ ์ด๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค(๋•Œ๋•Œ๋กœ ๋ช‡ ๊ฐ€์ง€ seemingly random ๋ณ€๊ฒฝ์„ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM์€ ๊ฒฐ์ •๋ก ์  ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ</a>์ž…๋‹ˆ๋‹ค).
+
+ํ…Œ์ŠคํŠธ:
+
+## ์ฝ”๋“œ ์Šค๋‹ˆํŽซ { #code-snippets }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+๋‹ค์Œ์€ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ž…๋‹ˆ๋‹ค: `foo`. ๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ๋˜ ๋‹ค๋ฅธ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ž…๋‹ˆ๋‹ค: `bar`. ๊ทธ๋ฆฌ๊ณ  ๋˜ ํ•˜๋‚˜: `baz quux`.
+
+////
+
+//// tab | ์ •๋ณด
+
+์ฝ”๋“œ ์Šค๋‹ˆํŽซ์˜ ๋‚ด์šฉ์€ ๊ทธ๋Œ€๋กœ ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Content of code snippets` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ๋”ฐ์˜ดํ‘œ { #quotes }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+์–ด์ œ ์ œ ์นœ๊ตฌ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ผ์Šต๋‹ˆ๋‹ค: "If you spell incorrectly correctly, you have spelled it incorrectly". ์ด์— ์ €๋Š” ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"".
+
+/// note | ์ฐธ๊ณ 
+
+LLM์€ ์•„๋งˆ ์ด๊ฒƒ์„ ์ž˜๋ชป ๋ฒˆ์—ญํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กœ์šด ์ ์€ ์žฌ๋ฒˆ์—ญํ•  ๋•Œ ๊ณ ์ •๋œ ๋ฒˆ์—ญ์„ ์œ ์ง€ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฟ์ž…๋‹ˆ๋‹ค.
+
+///
+
+////
+
+//// tab | ์ •๋ณด
+
+ํ”„๋กฌํ”„ํŠธ ์„ค๊ณ„์ž๋Š” ์ค‘๋ฆฝ ๋”ฐ์˜ดํ‘œ๋ฅผ ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ๋”ฐ์˜ดํ‘œ๋กœ ๋ณ€ํ™˜ํ• ์ง€ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Œ€๋กœ ๋‘์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### Quotes` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์˜ ๋”ฐ์˜ดํ‘œ { #quotes-in-code-snippets }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+`pip install "foo[bar]"`
+
+์ฝ”๋“œ ์Šค๋‹ˆํŽซ์—์„œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ์˜ˆ: `"this"`, `'that'`.
+
+์ฝ”๋“œ ์Šค๋‹ˆํŽซ์—์„œ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ์–ด๋ ค์šด ์˜ˆ: `f"I like {'oranges' if orange else "apples"}"`
+
+ํ•˜๋“œ์ฝ”์–ด: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"`
+
+////
+
+//// tab | ์ •๋ณด
+
+... ํ•˜์ง€๋งŒ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ ์•ˆ์˜ ๋”ฐ์˜ดํ‘œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+////
+
+## ์ฝ”๋“œ ๋ธ”๋ก { #code-blocks }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+Bash ์ฝ”๋“œ ์˜ˆ์‹œ...
+
+```bash
+# ์šฐ์ฃผ์— ์ธ์‚ฌ๋ง ์ถœ๋ ฅ
+echo "Hello universe"
+```
+
+...๊ทธ๋ฆฌ๊ณ  ์ฝ˜์†” ์ฝ”๋“œ ์˜ˆ์‹œ...
+
+```console
+$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
+<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span>  Starting server
+        Searching for package file structure
+```
+
+...๊ทธ๋ฆฌ๊ณ  ๋˜ ๋‹ค๋ฅธ ์ฝ˜์†” ์ฝ”๋“œ ์˜ˆ์‹œ...
+
+```console
+// "Code" ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ
+$ mkdir code
+// ํ•ด๋‹น ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™
+$ cd code
+```
+
+...๊ทธ๋ฆฌ๊ณ  Python ์ฝ”๋“œ ์˜ˆ์‹œ...
+
+```Python
+wont_work()  # ์ด๊ฑด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ๐Ÿ˜ฑ
+works(foo="bar")  # ์ด๊ฑด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค ๐ŸŽ‰
+```
+
+...์ด์ƒ์ž…๋‹ˆ๋‹ค.
+
+////
+
+//// tab | ์ •๋ณด
+
+์ฝ”๋“œ ๋ธ”๋ก์˜ ์ฝ”๋“œ๋Š”(์ฃผ์„์„ ์ œ์™ธํ•˜๊ณ ) ์ˆ˜์ •ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Content of code blocks` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ํƒญ๊ณผ ์ƒ‰์ƒ ๋ฐ•์Šค { #tabs-and-colored-boxes }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+/// info | ์ •๋ณด
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// note | ์ฐธ๊ณ 
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// note Technical details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// check | ํ™•์ธ
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// tip | ํŒ
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// warning | ๊ฒฝ๊ณ 
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+/// danger | ์œ„ํ—˜
+์ผ๋ถ€ ํ…์ŠคํŠธ
+///
+
+////
+
+//// tab | ์ •๋ณด
+
+ํƒญ๊ณผ `Info`/`Note`/`Warning`/๋“ฑ์˜ ๋ธ”๋ก์€ ์ œ๋ชฉ ๋ฒˆ์—ญ์„ ์ˆ˜์ง ๋ง‰๋Œ€(`|`) ๋’ค์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Special blocks`์™€ `### Tab blocks` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ์›น ๋ฐ ๋‚ด๋ถ€ ๋งํฌ { #web-and-internal-links }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+๋งํฌ ํ…์ŠคํŠธ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜๊ณ , ๋งํฌ ์ฃผ์†Œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค:
+
+* [์œ„์˜ ์ œ๋ชฉ์œผ๋กœ ๊ฐ€๋Š” ๋งํฌ](#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>
+
+๋งํฌ ํ…์ŠคํŠธ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜๊ณ , ๋งํฌ ์ฃผ์†Œ๋Š” ๋ฒˆ์—ญ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค:
+
+* <a href="https://fastapi.tiangolo.com/ko/" class="external-link" target="_blank">FastAPI ๋งํฌ</a>
+
+////
+
+//// tab | ์ •๋ณด
+
+๋งํฌ๋Š” ๋ฒˆ์—ญ๋˜์–ด์•ผ ํ•˜์ง€๋งŒ, ์ฃผ์†Œ๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๋Š” FastAPI ๋ฌธ์„œ ํŽ˜์ด์ง€๋กœ ํ–ฅํ•˜๋Š” ์ ˆ๋Œ€ ๋งํฌ์ด๋ฉฐ, ์ด ๊ฒฝ์šฐ ๋ฒˆ์—ญ ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Links` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## HTML "abbr" ์š”์†Œ { #html-abbr-elements }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+์—ฌ๊ธฐ HTML "abbr" ์š”์†Œ๋กœ ๊ฐ์‹ผ ๋ช‡ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ผ๋ถ€๋Š” ์ž„์˜๋กœ ๋งŒ๋“  ๊ฒƒ์ž…๋‹ˆ๋‹ค):
+
+### abbr๊ฐ€ ์ „์ฒด ๋ฌธ๊ตฌ๋ฅผ ์ œ๊ณต { #the-abbr-gives-a-full-phrase }
+
+* <abbr title="Getting Things Done - ์ผ์„ ๋๋‚ด๋Š” ๋ฐฉ๋ฒ•๋ก ">GTD</abbr>
+* <abbr title="less than - ๋ณด๋‹ค ์ž‘์Œ"><code>lt</code></abbr>
+* <abbr title="XML Web Token - XML ์›น ํ† ํฐ">XWT</abbr>
+* <abbr title="Parallel Server Gateway Interface - ๋ณ‘๋ ฌ ์„œ๋ฒ„ ๊ฒŒ์ดํŠธ์›จ์ด ์ธํ„ฐํŽ˜์ด์Šค">PSGI</abbr>
+
+### abbr๊ฐ€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-an-explanation }
+
+* <abbr title="์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์„œ๋กœ ์—ฐ๊ฒฐ๋˜๊ณ  ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก ๊ตฌ์„ฑ๋œ ๋จธ์‹ ๋“ค์˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.">cluster</abbr>
+* <abbr title="์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๊ณ„์ธต ์‚ฌ์ด์— ์ˆ˜๋งŽ์€ ์€๋‹‰ ๊ณ„์ธต์„ ๋‘” ์ธ๊ณต ์‹ ๊ฒฝ๋ง์„ ์‚ฌ์šฉํ•˜๋Š” ๋จธ์‹  ๋Ÿฌ๋‹ ๋ฐฉ๋ฒ•์œผ๋กœ, ์ด๋ฅผ ํ†ตํ•ด ํฌ๊ด„์ ์ธ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค">Deep Learning</abbr>
+
+### abbr๊ฐ€ ์ „์ฒด ๋ฌธ๊ตฌ์™€ ์„ค๋ช…์„ ์ œ๊ณต { #the-abbr-gives-a-full-phrase-and-an-explanation }
+
+* <abbr title="Mozilla Developer Network - ๋ชจ์งˆ๋ผ ๊ฐœ๋ฐœ์ž ๋„คํŠธ์›Œํฌ: Firefox๋ฅผ ๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ž‘์„ฑํ•œ ๊ฐœ๋ฐœ์ž์šฉ ๋ฌธ์„œ">MDN</abbr>
+* <abbr title="Input/Output - ์ž…๋ ฅ/์ถœ๋ ฅ: ๋””์Šคํฌ ์ฝ๊ธฐ ๋˜๋Š” ์“ฐ๊ธฐ, ๋„คํŠธ์›Œํฌ ํ†ต์‹ .">I/O</abbr>.
+
+////
+
+//// tab | ์ •๋ณด
+
+"abbr" ์š”์†Œ์˜ "title" ์†์„ฑ์€ ๋ช‡ ๊ฐ€์ง€ ๊ตฌ์ฒด์ ์ธ ์ง€์นจ์— ๋”ฐ๋ผ ๋ฒˆ์—ญ๋ฉ๋‹ˆ๋‹ค.
+
+๋ฒˆ์—ญ์—์„œ๋Š”(์˜์–ด ๋‹จ์–ด๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด) ์ž์ฒด "abbr" ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, LLM์€ ์ด๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### HTML abbr elements` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ์ œ๋ชฉ { #headings }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+### ์›น์•ฑ ๊ฐœ๋ฐœํ•˜๊ธฐ - ํŠœํ† ๋ฆฌ์–ผ { #develop-a-webapp-a-tutorial }
+
+์•ˆ๋…•ํ•˜์„ธ์š”.
+
+### ํƒ€์ž… ํžŒํŠธ์™€ -์• ๋„ˆํ…Œ์ด์…˜ { #type-hints-and-annotations }
+
+๋‹ค์‹œ ์•ˆ๋…•ํ•˜์„ธ์š”.
+
+### super- ๋ฐ subclasses { #super-and-subclasses }
+
+๋‹ค์‹œ ์•ˆ๋…•ํ•˜์„ธ์š”.
+
+////
+
+//// tab | ์ •๋ณด
+
+์ œ๋ชฉ์— ๋Œ€ํ•œ ์œ ์ผํ•œ ๊ฐ•ํ•œ ๊ทœ์น™์€, LLM์ด ์ค‘๊ด„ํ˜ธ ์•ˆ์˜ ํ•ด์‹œ ๋ถ€๋ถ„์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„ ๋งํฌ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+`scripts/translate.py`์˜ ์ผ๋ฐ˜ ํ”„๋กฌํ”„ํŠธ์—์„œ `### Headings` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+์–ธ์–ด๋ณ„ ์ง€์นจ์€ ์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### Headings` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
+
+## ๋ฌธ์„œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด { #terms-used-in-the-docs }
+
+//// tab | ํ…Œ์ŠคํŠธ
+
+* ๋‹น์‹ 
+* ๋‹น์‹ ์˜
+
+* ์˜ˆ: (e.g.)
+* ๋“ฑ (etc.)
+
+* `int`๋กœ์„œ์˜ `foo`
+* `str`๋กœ์„œ์˜ `bar`
+* `list`๋กœ์„œ์˜ `baz`
+
+* ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ
+* ๊ณ ๊ธ‰ ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ
+* SQLModel ๋ฌธ์„œ
+* API ๋ฌธ์„œ
+* ์ž๋™ ๋ฌธ์„œ
+
+* Data Science
+* Deep Learning
+* Machine Learning
+* Dependency Injection
+* HTTP Basic authentication
+* HTTP Digest
+* ISO format
+* JSON Schema ํ‘œ์ค€
+* JSON schema
+* schema definition
+* Password Flow
+* Mobile
+
+* deprecated
+* designed
+* invalid
+* on the fly
+* standard
+* default
+* case-sensitive
+* case-insensitive
+
+* ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น™ํ•˜๋‹ค
+* ํŽ˜์ด์ง€๋ฅผ ์„œ๋น™ํ•˜๋‹ค
+
+* ์•ฑ
+* ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
+
+* ์š”์ฒญ
+* ์‘๋‹ต
+* ์˜ค๋ฅ˜ ์‘๋‹ต
+
+* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ
+* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ
+* ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
+
+* body
+* ์š”์ฒญ body
+* ์‘๋‹ต body
+* JSON body
+* form body
+* file body
+* ํ•จ์ˆ˜ body
+
+* parameter
+* body parameter
+* path parameter
+* query parameter
+* cookie parameter
+* header parameter
+* form parameter
+* function parameter
+
+* event
+* startup event
+* ์„œ๋ฒ„ startup
+* shutdown event
+* lifespan event
+
+* handler
+* event handler
+* exception handler
+* ์ฒ˜๋ฆฌํ•˜๋‹ค
+
+* model
+* Pydantic model
+* data model
+* database model
+* form model
+* model object
+
+* class
+* base class
+* parent class
+* subclass
+* child class
+* sibling class
+* class method
+
+* header
+* headers
+* authorization header
+* `Authorization` header
+* forwarded header
+
+* dependency injection system
+* dependency
+* dependable
+* dependant
+
+* I/O bound
+* CPU bound
+* concurrency
+* parallelism
+* multiprocessing
+
+* env var
+* environment variable
+* `PATH`
+* `PATH` variable
+
+* authentication
+* authentication provider
+* authorization
+* authorization form
+* authorization provider
+* ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆํ•œ๋‹ค
+* ์‹œ์Šคํ…œ์ด ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•œ๋‹ค
+
+* CLI
+* command line interface
+
+* server
+* client
+
+* cloud provider
+* cloud service
+
+* development
+* development stages
+
+* dict
+* dictionary
+* enumeration
+* enum
+* enum member
+
+* encoder
+* decoder
+* encodeํ•˜๋‹ค
+* decodeํ•˜๋‹ค
+
+* exception
+* raiseํ•˜๋‹ค
+
+* expression
+* statement
+
+* frontend
+* backend
+
+* GitHub discussion
+* GitHub issue
+
+* performance
+* performance optimization
+
+* return type
+* return value
+
+* security
+* security scheme
+
+* task
+* background task
+* task function
+
+* template
+* template engine
+
+* type annotation
+* type hint
+
+* server worker
+* Uvicorn worker
+* Gunicorn Worker
+* worker process
+* worker class
+* workload
+
+* deployment
+* deployํ•˜๋‹ค
+
+* SDK
+* software development kit
+
+* `APIRouter`
+* `requirements.txt`
+* Bearer Token
+* breaking change
+* bug
+* button
+* callable
+* code
+* commit
+* context manager
+* coroutine
+* database session
+* disk
+* domain
+* engine
+* fake X
+* HTTP GET method
+* item
+* library
+* lifespan
+* lock
+* middleware
+* mobile application
+* module
+* mounting
+* network
+* origin
+* override
+* payload
+* processor
+* property
+* proxy
+* pull request
+* query
+* RAM
+* remote machine
+* status code
+* string
+* tag
+* web framework
+* wildcard
+* returnํ•˜๋‹ค
+* validateํ•˜๋‹ค
+
+////
+
+//// tab | ์ •๋ณด
+
+์ด๊ฒƒ์€ ๋ฌธ์„œ์—์„œ ๋ณด์ด๋Š” (๋Œ€๋ถ€๋ถ„) ๊ธฐ์ˆ  ์šฉ์–ด์˜ ๋ถˆ์™„์ „ํ•˜๊ณ  ๋น„๊ทœ๋ฒ”์ ์ธ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ํ”„๋กฌํ”„ํŠธ ์„ค๊ณ„์ž๊ฐ€ ์–ด๋–ค ์šฉ์–ด์— ๋Œ€ํ•ด LLM์— ์ถ”๊ฐ€์ ์ธ ๋„์›€์ด ํ•„์š”ํ•œ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ข‹์€ ๋ฒˆ์—ญ์„ ๊ณ„์† ๋œ ์ข‹์€ ๋ฒˆ์—ญ์œผ๋กœ ๋˜๋Œ๋ฆด ๋•Œ, ๋˜๋Š” ์–ธ์–ด์—์„œ ์šฉ์–ด์˜ ํ™œ์šฉ/๋ณ€ํ™”๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๋•Œ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `docs/de/llm-prompt.md`์˜ `### List of English terms and their preferred German translations` ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+////
diff --git a/docs/ko/docs/advanced/additional-responses.md b/docs/ko/docs/advanced/additional-responses.md
new file mode 100644 (file)
index 0000000..a6f51f5
--- /dev/null
@@ -0,0 +1,247 @@
+# OpenAPI์—์„œ ์ถ”๊ฐ€ ์‘๋‹ต { #additional-responses-in-openapi }
+
+/// warning | ๊ฒฝ๊ณ 
+
+์ด๋Š” ๊ฝค ๊ณ ๊ธ‰ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.
+
+**FastAPI**๋ฅผ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด, ์ด ๋‚ด์šฉ์ด ํ•„์š” ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+์ถ”๊ฐ€ ์ƒํƒœ ์ฝ”๋“œ, ๋ฏธ๋””์–ด ํƒ€์ž…, ์„ค๋ช… ๋“ฑ์„ ํฌํ•จํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์€ OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋˜๋ฏ€๋กœ API ๋ฌธ์„œ์—๋„ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ถ”๊ฐ€ ์‘๋‹ต์˜ ๊ฒฝ์šฐ, ์ƒํƒœ ์ฝ”๋“œ์™€ ์ฝ˜ํ…์ธ ๋ฅผ ํฌํ•จํ•˜์—ฌ `JSONResponse` ๊ฐ™์€ `Response`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ฐ˜๋“œ์‹œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+## `model`์„ ์‚ฌ์šฉํ•œ ์ถ”๊ฐ€ ์‘๋‹ต { #additional-response-with-model }
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์— `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” `dict`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํ‚ค๋Š” ๊ฐ ์‘๋‹ต์˜ ์ƒํƒœ ์ฝ”๋“œ(์˜ˆ: `200`)์ด๊ณ , ๊ฐ’์€ ๊ฐ ์‘๋‹ต์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๋‹ค๋ฅธ `dict`์ž…๋‹ˆ๋‹ค.
+
+๊ฐ ์‘๋‹ต `dict`์—๋Š” `response_model`์ฒ˜๋Ÿผ Pydantic ๋ชจ๋ธ์„ ๋‹ด๋Š” `model` ํ‚ค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ๊ทธ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด JSON Schema๋ฅผ ์ƒ์„ฑํ•˜๊ณ , OpenAPI์˜ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒํƒœ ์ฝ”๋“œ `404`์™€ Pydantic ๋ชจ๋ธ `Message`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์‘๋‹ต์„ ์„ ์–ธํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
+
+/// note | ์ฐธ๊ณ 
+
+`JSONResponse`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.
+
+///
+
+/// info | ์ •๋ณด
+
+`model` ํ‚ค๋Š” OpenAPI์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ์—ฌ๊ธฐ์—์„œ Pydantic ๋ชจ๋ธ์„ ๊ฐ€์ ธ์™€ JSON Schema๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
+
+์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ๊ฐ’์œผ๋กœ ๋˜ ๋‹ค๋ฅธ JSON ๊ฐ์ฒด(`dict`)๋ฅผ ๊ฐ€์ง€๋Š” `content` ํ‚ค ์•ˆ์—:
+    * ๋ฏธ๋””์–ด ํƒ€์ž…(์˜ˆ: `application/json`)์„ ํ‚ค๋กœ ๊ฐ€์ง€๋ฉฐ, ๊ฐ’์œผ๋กœ ๋˜ ๋‹ค๋ฅธ JSON ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๊ณ :
+        * `schema` ํ‚ค๊ฐ€ ์žˆ๊ณ , ๊ทธ ๊ฐ’์ด ๋ชจ๋ธ์—์„œ ์ƒ์„ฑ๋œ JSON Schema์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์ž…๋‹ˆ๋‹ค.
+            * **FastAPI**๋Š” ์ด๋ฅผ ์ง์ ‘ ํฌํ•จํ•˜๋Š” ๋Œ€์‹ , OpenAPI์˜ ๋‹ค๋ฅธ ์œ„์น˜์— ์žˆ๋Š” ์ „์—ญ JSON Schemas๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์—ฌ๊ธฐ์—์„œ reference๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ทธ JSON Schema๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋” ๋‚˜์€ ์ฝ”๋“œ ์ƒ์„ฑ ๋„๊ตฌ ๋“ฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด OpenAPI์— ์ƒ์„ฑ๋˜๋Š” ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+```JSON hl_lines="3-12"
+{
+    "responses": {
+        "404": {
+            "description": "Additional Response",
+            "content": {
+                "application/json": {
+                    "schema": {
+                        "$ref": "#/components/schemas/Message"
+                    }
+                }
+            }
+        },
+        "200": {
+            "description": "Successful Response",
+            "content": {
+                "application/json": {
+                    "schema": {
+                        "$ref": "#/components/schemas/Item"
+                    }
+                }
+            }
+        },
+        "422": {
+            "description": "Validation Error",
+            "content": {
+                "application/json": {
+                    "schema": {
+                        "$ref": "#/components/schemas/HTTPValidationError"
+                    }
+                }
+            }
+        }
+    }
+}
+```
+
+์Šคํ‚ค๋งˆ๋Š” OpenAPI ์Šคํ‚ค๋งˆ ๋‚ด๋ถ€์˜ ๋‹ค๋ฅธ ์œ„์น˜๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค:
+
+```JSON hl_lines="4-16"
+{
+    "components": {
+        "schemas": {
+            "Message": {
+                "title": "Message",
+                "required": [
+                    "message"
+                ],
+                "type": "object",
+                "properties": {
+                    "message": {
+                        "title": "Message",
+                        "type": "string"
+                    }
+                }
+            },
+            "Item": {
+                "title": "Item",
+                "required": [
+                    "id",
+                    "value"
+                ],
+                "type": "object",
+                "properties": {
+                    "id": {
+                        "title": "Id",
+                        "type": "string"
+                    },
+                    "value": {
+                        "title": "Value",
+                        "type": "string"
+                    }
+                }
+            },
+            "ValidationError": {
+                "title": "ValidationError",
+                "required": [
+                    "loc",
+                    "msg",
+                    "type"
+                ],
+                "type": "object",
+                "properties": {
+                    "loc": {
+                        "title": "Location",
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+                    "msg": {
+                        "title": "Message",
+                        "type": "string"
+                    },
+                    "type": {
+                        "title": "Error Type",
+                        "type": "string"
+                    }
+                }
+            },
+            "HTTPValidationError": {
+                "title": "HTTPValidationError",
+                "type": "object",
+                "properties": {
+                    "detail": {
+                        "title": "Detail",
+                        "type": "array",
+                        "items": {
+                            "$ref": "#/components/schemas/ValidationError"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+```
+
+## ์ฃผ์š” ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋ฏธ๋””์–ด ํƒ€์ž… { #additional-media-types-for-the-main-response }
+
+๊ฐ™์€ `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋™์ผํ•œ ์ฃผ์š” ์‘๋‹ต์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ JSON ๊ฐ์ฒด(๋ฏธ๋””์–ด ํƒ€์ž… `application/json`) ๋˜๋Š” PNG ์ด๋ฏธ์ง€(๋ฏธ๋””์–ด ํƒ€์ž… `image/png`)๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด `image/png`๋ผ๋Š” ์ถ”๊ฐ€ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *}
+
+/// note | ์ฐธ๊ณ 
+
+์ด๋ฏธ์ง€๋Š” `FileResponse`๋ฅผ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.
+
+///
+
+/// info | ์ •๋ณด
+
+`responses` ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋‹ค๋ฅธ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ํ•œ, FastAPI๋Š” ์‘๋‹ต์ด ์ฃผ์š” ์‘๋‹ต ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๋ฏธ๋””์–ด ํƒ€์ž…(๊ธฐ๋ณธ๊ฐ’ `application/json`)์„ ๊ฐ€์ง„๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ปค์Šคํ…€ ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜๋ฉด์„œ ๋ฏธ๋””์–ด ํƒ€์ž…์„ `None`์œผ๋กœ ์„ค์ •ํ–ˆ๋‹ค๋ฉด, FastAPI๋Š” ์—ฐ๊ฒฐ๋œ ๋ชจ๋ธ์ด ์žˆ๋Š” ๋ชจ๋“  ์ถ”๊ฐ€ ์‘๋‹ต์— ๋Œ€ํ•ด `application/json`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ์ •๋ณด ๊ฒฐํ•ฉํ•˜๊ธฐ { #combining-information }
+
+`response_model`, `status_code`, `responses` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•ด ์—ฌ๋Ÿฌ ์œ„์น˜์˜ ์‘๋‹ต ์ •๋ณด๋ฅผ ๊ฒฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ธฐ๋ณธ ์ƒํƒœ ์ฝ”๋“œ `200`(๋˜๋Š” ํ•„์š”ํ•˜๋‹ค๋ฉด ์ปค์Šคํ…€ ์ฝ”๋“œ)์„ ์‚ฌ์šฉํ•˜์—ฌ `response_model`์„ ์„ ์–ธํ•˜๊ณ , ๊ทธ์™€ ๋™์ผํ•œ ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ `responses`์—์„œ OpenAPI ์Šคํ‚ค๋งˆ์— ์ง์ ‘ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” `responses`์˜ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๋ชจ๋ธ์˜ JSON Schema์™€ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ปค์Šคํ…€ `description`์„ ๊ฐ€์ง„ ์ƒํƒœ ์ฝ”๋“œ `404` ์‘๋‹ต์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ `response_model`์„ ์‚ฌ์šฉํ•˜๋Š” ์ƒํƒœ ์ฝ”๋“œ `200` ์‘๋‹ต์„ ์„ ์–ธํ•˜๋˜, ์ปค์Šคํ…€ `example`์„ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
+
+์ด ๋ชจ๋“  ๋‚ด์šฉ์€ OpenAPI์— ๊ฒฐํ•ฉ๋˜์–ด ํฌํ•จ๋˜๊ณ , API ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/additional-responses/image01.png">
+
+## ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต๊ณผ ์ปค์Šคํ…€ ์‘๋‹ต ๊ฒฐํ•ฉํ•˜๊ธฐ { #combine-predefined-responses-and-custom-ones }
+
+์—ฌ๋Ÿฌ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์ ์šฉ๋˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ํ•„์š”ํ•œ ์ปค์Šคํ…€ ์‘๋‹ต๊ณผ ๊ฒฐํ•ฉํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ Python์˜ `dict` โ€œunpackingโ€ ๊ธฐ๋ฒ•์ธ `**dict_to_unpack`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python
+old_dict = {
+    "old key": "old value",
+    "second old key": "second old value",
+}
+new_dict = {**old_dict, "new key": "new value"}
+```
+
+์—ฌ๊ธฐ์„œ `new_dict`๋Š” `old_dict`์˜ ๋ชจ๋“  ํ‚ค-๊ฐ’ ์Œ์— ๋”ํ•ด ์ƒˆ ํ‚ค-๊ฐ’ ์Œ๊นŒ์ง€ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:
+
+```Python
+{
+    "old key": "old value",
+    "second old key": "second old value",
+    "new key": "new value",
+}
+```
+
+์ด ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ์ผ๋ถ€ ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‘๋‹ต์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ์ถ”๊ฐ€ ์ปค์Šคํ…€ ์‘๋‹ต๊ณผ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด:
+
+{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *}
+
+## OpenAPI ์‘๋‹ต์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด { #more-information-about-openapi-responses }
+
+์‘๋‹ต์— ์ •ํ™•ํžˆ ๋ฌด์—‡์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด๋ ค๋ฉด, 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` ๋“ฑ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/advanced/behind-a-proxy.md b/docs/ko/docs/advanced/behind-a-proxy.md
new file mode 100644 (file)
index 0000000..92bddac
--- /dev/null
@@ -0,0 +1,466 @@
+# ํ”„๋ก์‹œ ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ธฐ { #behind-a-proxy }
+
+๋งŽ์€ ๊ฒฝ์šฐ FastAPI ์•ฑ ์•ž๋‹จ์— Traefik์ด๋‚˜ Nginx ๊ฐ™์€ **ํ”„๋ก์‹œ(proxy)**๋ฅผ ๋‘๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Ÿฐ ํ”„๋ก์‹œ๋Š” HTTPS ์ธ์ฆ์„œ ์ฒ˜๋ฆฌ ๋“ฑ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋‹ด๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” { #proxy-forwarded-headers }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•ž๋‹จ์˜ **ํ”„๋ก์‹œ**๋Š” ๋ณดํ†ต **์„œ๋ฒ„**๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์—, ํ•ด๋‹น ์š”์ฒญ์ด ํ”„๋ก์‹œ์— ์˜ํ•ด **์ „๋‹ฌ(forwarded)**๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์„œ๋ฒ„๊ฐ€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๋ช‡๋ช‡ ํ—ค๋”๋ฅผ ๋™์ ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„๋Š” ๋„๋ฉ”์ธ์„ ํฌํ•จํ•œ ์›๋ž˜์˜ (๊ณต๊ฐœ) URL, HTTPS ์‚ฌ์šฉ ์—ฌ๋ถ€ ๋“ฑ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**์„œ๋ฒ„** ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: **FastAPI CLI**๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” **Uvicorn**)์€ ์ด๋Ÿฐ ํ—ค๋”๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ •๋ณด๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋ณด์•ˆ์ƒ, ์„œ๋ฒ„๋Š” ์ž์‹ ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ก์‹œ ๋’ค์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ํ•ด๋‹น ํ—ค๋”๋ฅผ ํ•ด์„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+ํ”„๋ก์‹œ ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* <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>
+
+///
+
+### ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #enable-proxy-forwarded-headers }
+
+FastAPI CLI๋ฅผ *CLI ์˜ต์…˜* `--forwarded-allow-ips`๋กœ ์‹คํ–‰ํ•˜๊ณ , ์ „๋‹ฌ ํ—ค๋”๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์‹ ๋ขฐํ•  IP ์ฃผ์†Œ๋“ค์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`--forwarded-allow-ips="*"`๋กœ ์„ค์ •ํ•˜๋ฉด ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  IP๋ฅผ ์‹ ๋ขฐํ•ฉ๋‹ˆ๋‹ค.
+
+**์„œ๋ฒ„**๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” **ํ”„๋ก์‹œ** ๋’ค์— ์žˆ๊ณ  ํ”„๋ก์‹œ๋งŒ ์„œ๋ฒ„์— ์ ‘๊ทผํ•œ๋‹ค๋ฉด, ์ด๋Š” ํ•ด๋‹น **ํ”„๋ก์‹œ**์˜ IP๊ฐ€ ๋ฌด์—‡์ด๋“  ๊ฐ„์— ๋ฐ›์•„๋“ค์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+<div class="termy">
+
+```console
+$ fastapi run --forwarded-allow-ips="*"
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+### HTTPS์—์„œ ๋ฆฌ๋””๋ ‰์…˜ { #redirects-with-https }
+
+์˜ˆ๋ฅผ ๋“ค์–ด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `/items/`๋ฅผ ์ •์˜ํ–ˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค:
+
+{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
+
+ํด๋ผ์ด์–ธํŠธ๊ฐ€ `/items`๋กœ ์ ‘๊ทผํ•˜๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ `/items/`๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ *CLI ์˜ต์…˜* `--forwarded-allow-ips`๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์ „์—๋Š” `http://localhost:8000/items/`๋กœ ๋ฆฌ๋””๋ ‰์…˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด `https://mysuperapp.com`์— ํ˜ธ์ŠคํŒ…๋˜์–ด ์žˆ๊ณ , ๋ฆฌ๋””๋ ‰์…˜๋„ `https://mysuperapp.com/items/`๋กœ ๋˜์–ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋•Œ `--proxy-headers`๋ฅผ ์„ค์ •ํ•˜๋ฉด FastAPI๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž
+
+```
+https://mysuperapp.com/items/
+```
+
+/// tip | ํŒ
+
+HTTPS์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๋ ค๋ฉด ๊ฐ€์ด๋“œ [HTTPS์— ๋Œ€ํ•˜์—ฌ](../deployment/https.md){.internal-link target=_blank}๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
+
+///
+
+### ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋”๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-proxy-forwarded-headers-work }
+
+๋‹ค์Œ์€ **ํ”„๋ก์‹œ**๊ฐ€ ํด๋ผ์ด์–ธํŠธ์™€ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„** ์‚ฌ์ด์—์„œ ์ „๋‹ฌ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์„ ์‹œ๊ฐ์ ์œผ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+```mermaid
+sequenceDiagram
+    participant Client
+    participant Proxy as Proxy/Load Balancer
+    participant Server as FastAPI Server
+
+    Client->>Proxy: HTTPS Request<br/>Host: mysuperapp.com<br/>Path: /items
+
+    Note over Proxy: Proxy adds forwarded headers
+
+    Proxy->>Server: HTTP Request<br/>X-Forwarded-For: [client IP]<br/>X-Forwarded-Proto: https<br/>X-Forwarded-Host: mysuperapp.com<br/>Path: /items
+
+    Note over Server: Server interprets headers<br/>(if --forwarded-allow-ips is set)
+
+    Server->>Proxy: HTTP Response<br/>with correct HTTPS URLs
+
+    Proxy->>Client: HTTPS Response
+```
+
+**ํ”„๋ก์‹œ**๋Š” ์›๋ž˜์˜ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๊ณ , **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ํŠน์ˆ˜ํ•œ *forwarded* ํ—ค๋”(`X-Forwarded-*`)๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ํ—ค๋”๋“ค์€ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‚ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š” ์›๋ž˜ ์š”์ฒญ์˜ ์ •๋ณด๋ฅผ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค:
+
+* **X-Forwarded-For**: ์›๋ž˜ ํด๋ผ์ด์–ธํŠธ์˜ IP ์ฃผ์†Œ
+* **X-Forwarded-Proto**: ์›๋ž˜ ํ”„๋กœํ† ์ฝœ(`https`)
+* **X-Forwarded-Host**: ์›๋ž˜ ํ˜ธ์ŠคํŠธ(`mysuperapp.com`)
+
+**FastAPI CLI**๋ฅผ `--forwarded-allow-ips`๋กœ ์„ค์ •ํ•˜๋ฉด, ์ด ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋””๋ ‰์…˜์—์„œ ์˜ฌ๋ฐ”๋ฅธ URL์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+## ์ œ๊ฑฐ๋œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ { #proxy-with-a-stripped-path-prefix }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ(prefix)๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ํ”„๋ก์‹œ๋ฅผ ๋‘˜ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Ÿฐ ๊ฒฝ์šฐ `root_path`๋ฅผ ์‚ฌ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`root_path`๋Š” (FastAPI๊ฐ€ Starlette๋ฅผ ํ†ตํ•ด ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š”) ASGI ์‚ฌ์–‘์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค.
+
+`root_path`๋Š” ์ด๋Ÿฌํ•œ ํŠน์ • ์‚ฌ๋ก€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งˆ์šดํŠธํ•  ๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ(stripped)๋˜๋Š” ํ”„๋ก์‹œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€, ์ฝ”๋“œ์—์„œ๋Š” `/app`์— ๊ฒฝ๋กœ๋ฅผ ์„ ์–ธํ•˜์ง€๋งŒ, ์œ„์— ํ•œ ๊ฒน(ํ”„๋ก์‹œ)์„ ์ถ”๊ฐ€ํ•ด **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ `/api/v1` ๊ฐ™์€ ๊ฒฝ๋กœ ์•„๋ž˜์— ๋‘๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ ์›๋ž˜ ๊ฒฝ๋กœ `/app`์€ ์‹ค์ œ๋กœ `/api/v1/app`์—์„œ ์„œ๋น„์Šค๋ฉ๋‹ˆ๋‹ค.
+
+์ฝ”๋“œ๋Š” ๋ชจ๋‘ `/app`๋งŒ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ๋„ ๋ง์ž…๋‹ˆ๋‹ค.
+
+{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
+
+๊ทธ๋ฆฌ๊ณ  ํ”„๋ก์‹œ๋Š” ์š”์ฒญ์„ ์•ฑ ์„œ๋ฒ„(์•„๋งˆ FastAPI CLI๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” Uvicorn)๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, ๋™์ ์œผ๋กœ **๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ**๋ฅผ **"์ œ๊ฑฐ"**ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—ฌ์ „ํžˆ `/app`์—์„œ ์„œ๋น„์Šค๋œ๋‹ค๊ณ  ๋ฏฟ๊ฒŒ ๋˜๊ณ , ์ฝ”๋“œ ์ „์ฒด๋ฅผ `/api/v1` ์ ‘๋‘์‚ฌ๋ฅผ ํฌํ•จํ•˜๋„๋ก ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง‘๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๋ณดํ†ต ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ํ†ตํ•ฉ ๋ฌธ์„œ UI(ํ”„๋ก ํŠธ์—”๋“œ)๋ฅผ ์—ด๋ฉด, OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ `/api/v1/openapi.json`์ด ์•„๋‹ˆ๋ผ `/openapi.json`์—์„œ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋Š” `/openapi.json`์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€๋งŒ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์–ป์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.
+
+์•ฑ์— ๋Œ€ํ•ด `/api/v1` ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ํ”„๋ก ํŠธ์—”๋“œ๋Š” `/api/v1/openapi.json`์—์„œ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+```mermaid
+graph LR
+
+browser("Browser")
+proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
+server["Server on http://127.0.0.1:8000/app"]
+
+browser --> proxy
+proxy --> server
+```
+
+/// tip | ํŒ
+
+IP `0.0.0.0`์€ ๋ณดํ†ต ํ•ด๋‹น ๋จธ์‹ /์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  IP์—์„œ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฆฌ์Šจํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+๋ฌธ์„œ UI๋Š” ๋˜ํ•œ OpenAPI ์Šคํ‚ค๋งˆ์—์„œ ์ด API `server`๊ฐ€ `/api/v1`(ํ”„๋ก์‹œ ๋’ค) ์œ„์น˜์— ์žˆ๋‹ค๊ณ  ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ:
+
+```JSON hl_lines="4-8"
+{
+    "openapi": "3.1.0",
+    // More stuff here
+    "servers": [
+        {
+            "url": "/api/v1"
+        }
+    ],
+    "paths": {
+            // More stuff here
+    }
+}
+```
+
+์ด ์˜ˆ์‹œ์—์„œ "Proxy"๋Š” **Traefik** ๊ฐ™์€ ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๋Š” **Uvicorn**์œผ๋กœ ์‹คํ–‰๋˜๋Š” FastAPI CLI์ฒ˜๋Ÿผ, FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๊ตฌ์„ฑ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### `root_path` ์ œ๊ณตํ•˜๊ธฐ { #providing-the-root-path }
+
+์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋ ค๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+Hypercorn์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, Hypercorn์—๋„ `--root-path` ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+ASGI ์‚ฌ์–‘์€ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด `root_path`๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๊ฐ€ ๊ทธ `root_path`๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### ํ˜„์žฌ `root_path` ํ™•์ธํ•˜๊ธฐ { #checking-the-current-root-path }
+
+์š”์ฒญ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ ์ค‘์ธ ํ˜„์žฌ `root_path`๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” `scope` ๋”•์…”๋„ˆ๋ฆฌ(ASGI ์‚ฌ์–‘์˜ ์ผ๋ถ€)์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์„œ๋Š” ๋ฐ๋ชจ ๋ชฉ์ ์„ ์œ„ํ•ด ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
+
+๊ทธ ๋‹ค์Œ Uvicorn์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ•˜๋ฉด:
+
+<div class="termy">
+
+```console
+$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "message": "Hello World",
+    "root_path": "/api/v1"
+}
+```
+
+### FastAPI ์•ฑ์—์„œ `root_path` ์„ค์ •ํ•˜๊ธฐ { #setting-the-root-path-in-the-fastapi-app }
+
+๋˜๋Š” `--root-path` ๊ฐ™์€ ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜(๋˜๋Š” ๋™๋“ฑํ•œ ๋ฐฉ๋ฒ•)์„ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, FastAPI ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ `root_path` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
+
+`FastAPI`์— `root_path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ Uvicorn์ด๋‚˜ Hypercorn์— ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--root-path`๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
+
+### `root_path`์— ๋Œ€ํ•˜์—ฌ { #about-root-path }
+
+์„œ๋ฒ„(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>์— ์ ‘์†ํ•˜๋ฉด ์ •์ƒ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "message": "Hello World",
+    "root_path": "/api/v1"
+}
+```
+
+๋”ฐ๋ผ์„œ `http://127.0.0.1:8000/api/v1/app`๋กœ ์ ‘๊ทผ๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
+
+Uvicorn์€ ํ”„๋ก์‹œ๊ฐ€ `http://127.0.0.1:8000/app`์—์„œ Uvicorn์— ์ ‘๊ทผํ•  ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•˜๊ณ , ๊ทธ ์œ„์— `/api/v1` ์ ‘๋‘์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํ”„๋ก์‹œ์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค.
+
+## ์ œ๊ฑฐ๋œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ์— ๋Œ€ํ•˜์—ฌ { #about-proxies-with-a-stripped-path-prefix }
+
+๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ๋˜๋Š” ํ”„๋ก์‹œ๋Š” ๊ตฌ์„ฑ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ผ ๋ฟ์ด๋ผ๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.
+
+๋งŽ์€ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ ํ”„๋ก์‹œ๊ฐ€ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ(๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ) ํ”„๋ก์‹œ๋Š” `https://myawesomeapp.com` ๊ฐ™์€ ๊ณณ์—์„œ ๋ฆฌ์Šจํ•˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๊ฐ€ `https://myawesomeapp.com/api/v1/app`๋กœ ์ ‘๊ทผํ•˜๋ฉด, ์„œ๋ฒ„(์˜ˆ: Uvicorn)๊ฐ€ `http://127.0.0.1:8000`์—์„œ ๋ฆฌ์Šจํ•˜๊ณ  ์žˆ์„ ๋•Œ ํ”„๋ก์‹œ(๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”)๋Š” ๋™์ผํ•œ ๊ฒฝ๋กœ๋กœ Uvicorn์— ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค: `http://127.0.0.1:8000/api/v1/app`.
+
+## Traefik์œผ๋กœ ๋กœ์ปฌ ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #testing-locally-with-traefik }
+
+<a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์ œ๊ฑฐ๋˜๋Š” ๊ตฌ์„ฑ์„ ๋กœ์ปฌ์—์„œ ์‰ฝ๊ฒŒ ์‹คํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Traefik ๋‹ค์šด๋กœ๋“œ</a>๋Š” ๋‹จ์ผ ๋ฐ”์ด๋„ˆ๋ฆฌ์ด๋ฉฐ, ์••์ถ• ํŒŒ์ผ์„ ํ’€๊ณ  ํ„ฐ๋ฏธ๋„์—์„œ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ๋‹ค์Œ ๋‚ด์šฉ์„ ๊ฐ€์ง„ `traefik.toml` ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์„ธ์š”:
+
+```TOML hl_lines="3"
+[entryPoints]
+  [entryPoints.http]
+    address = ":9999"
+
+[providers]
+  [providers.file]
+    filename = "routes.toml"
+```
+
+์ด๋Š” Traefik์ด 9999 ํฌํŠธ์—์„œ ๋ฆฌ์Šจํ•˜๊ณ , ๋‹ค๋ฅธ ํŒŒ์ผ `routes.toml`์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+ํ‘œ์ค€ HTTP ํฌํŠธ 80 ๋Œ€์‹  9999 ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ, ๊ด€๋ฆฌ์ž(`sudo`) ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+์ด์ œ ๋‹ค๋ฅธ ํŒŒ์ผ `routes.toml`์„ ์ƒ์„ฑํ•˜์„ธ์š”:
+
+```TOML hl_lines="5  12  20"
+[http]
+  [http.middlewares]
+
+    [http.middlewares.api-stripprefix.stripPrefix]
+      prefixes = ["/api/v1"]
+
+  [http.routers]
+
+    [http.routers.app-http]
+      entryPoints = ["http"]
+      service = "app"
+      rule = "PathPrefix(`/api/v1`)"
+      middlewares = ["api-stripprefix"]
+
+  [http.services]
+
+    [http.services.app]
+      [http.services.app.loadBalancer]
+        [[http.services.app.loadBalancer.servers]]
+          url = "http://127.0.0.1:8000"
+```
+
+์ด ํŒŒ์ผ์€ Traefik์ด ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ `/api/v1`์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  Traefik์€ ์š”์ฒญ์„ `http://127.0.0.1:8000`์—์„œ ์‹คํ–‰ ์ค‘์ธ Uvicorn์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
+
+์ด์ œ Traefik์„ ์‹œ์ž‘ํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ ./traefik --configFile=traefik.toml
+
+INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
+```
+
+</div>
+
+๊ทธ๋ฆฌ๊ณ  `--root-path` ์˜ต์…˜์„ ์‚ฌ์šฉํ•ด ์•ฑ์„ ์‹œ์ž‘ํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+### ์‘๋‹ต ํ™•์ธํ•˜๊ธฐ { #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>๋กœ ์ ‘์†ํ•˜๋ฉด ์ •์ƒ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "message": "Hello World",
+    "root_path": "/api/v1"
+}
+```
+
+/// tip | ํŒ
+
+`http://127.0.0.1:8000/app`๋กœ ์ ‘๊ทผํ–ˆ๋Š”๋ฐ๋„ `/api/v1`์˜ `root_path`๊ฐ€ ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์— ์ฃผ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์˜ต์…˜ `--root-path`์—์„œ ๊ฐ€์ ธ์˜จ ๊ฐ’์ž…๋‹ˆ๋‹ค.
+
+///
+
+์ด์ œ 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>์„ ์—ฌ์„ธ์š”.
+
+๋™์ผํ•œ ์‘๋‹ต์„ ์–ป์Šต๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "message": "Hello World",
+    "root_path": "/api/v1"
+}
+```
+
+ํ•˜์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ํ”„๋ก์‹œ๊ฐ€ ์ œ๊ณตํ•œ ์ ‘๋‘์‚ฌ ๊ฒฝ๋กœ `/api/v1`์ด ํฌํ•จ๋œ URL์—์„œ์˜ ์‘๋‹ต์ž…๋‹ˆ๋‹ค.
+
+๋ฌผ๋ก  ์—ฌ๊ธฐ์„œ์˜ ์•„์ด๋””์–ด๋Š” ๋ชจ๋‘๊ฐ€ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์•ฑ์— ์ ‘๊ทผํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, `/api/v1` ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์žˆ๋Š” ๋ฒ„์ „์ด "์˜ฌ๋ฐ”๋ฅธ" ์ ‘๊ทผ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๊ฐ€ ์—†๋Š” ๋ฒ„์ „(`http://127.0.0.1:8000/app`)์€ Uvicorn์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ์˜ค์ง _ํ”„๋ก์‹œ_(Traefik)๊ฐ€ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” ํ”„๋ก์‹œ(Traefik)๊ฐ€ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์„œ๋ฒ„(Uvicorn)๊ฐ€ ์˜ต์…˜ `--root-path`๋กœ๋ถ€ํ„ฐ์˜ `root_path`๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
+
+### ๋ฌธ์„œ UI ํ™•์ธํ•˜๊ธฐ { #check-the-docs-ui }
+
+ํ•˜์ง€๋งŒ ์žฌ๋ฏธ์žˆ๋Š” ๋ถ€๋ถ„์€ ์—ฌ๊ธฐ์ž…๋‹ˆ๋‹ค. โœจ
+
+์•ฑ์— ์ ‘๊ทผํ•˜๋Š” "๊ณต์‹" ๋ฐฉ๋ฒ•์€ ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง„ ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด์„œ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ๋Œ€ํ•˜๋Š” ๋Œ€๋กœ, 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>์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<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>์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/behind-a-proxy/image02.png">
+
+์›ํ•˜๋˜ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. โœ”๏ธ
+
+์ด๋Š” FastAPI๊ฐ€ ์ด `root_path`๋ฅผ ์‚ฌ์šฉํ•ด, OpenAPI์—์„œ ๊ธฐ๋ณธ `server`๋ฅผ `root_path`๊ฐ€ ์ œ๊ณตํ•œ URL๋กœ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+## ์ถ”๊ฐ€ ์„œ๋ฒ„ { #additional-servers }
+
+/// warning | ๊ฒฝ๊ณ 
+
+์ด๋Š” ๋” ๊ณ ๊ธ‰ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
+
+///
+
+๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋Š” OpenAPI ์Šคํ‚ค๋งˆ์—์„œ `root_path`์˜ URL๋กœ `server`๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์˜ˆ๋ฅผ ๋“ค์–ด ๋™์ผํ•œ docs UI๊ฐ€ ์Šคํ…Œ์ด์ง•๊ณผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ ๋ชจ๋‘์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋„๋ก ํ•˜๋ ค๋ฉด, ๋‹ค๋ฅธ ๋Œ€์•ˆ `servers`๋ฅผ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์‚ฌ์šฉ์ž ์ •์˜ `servers` ๋ฆฌ์ŠคํŠธ๋ฅผ ์ „๋‹ฌํ–ˆ๊ณ  `root_path`(API๊ฐ€ ํ”„๋ก์‹œ ๋’ค์— ์žˆ๊ธฐ ๋•Œ๋ฌธ)๊ฐ€ ์žˆ๋‹ค๋ฉด, **FastAPI**๋Š” ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ์•ž์— ์ด `root_path`๋ฅผ ๊ฐ€์ง„ "server"๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ:
+
+{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
+
+๋‹ค์Œ๊ณผ ๊ฐ™์€ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
+
+```JSON hl_lines="5-7"
+{
+    "openapi": "3.1.0",
+    // More stuff here
+    "servers": [
+        {
+            "url": "/api/v1"
+        },
+        {
+            "url": "https://stag.example.com",
+            "description": "Staging environment"
+        },
+        {
+            "url": "https://prod.example.com",
+            "description": "Production environment"
+        }
+    ],
+    "paths": {
+            // More stuff here
+    }
+}
+```
+
+/// tip | ํŒ
+
+`root_path`์—์„œ ๊ฐ€์ ธ์˜จ ๊ฐ’์ธ `/api/v1`์˜ `url` ๊ฐ’์„ ๊ฐ€์ง„, ์ž๋™ ์ƒ์„ฑ๋œ server์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+///
+
+<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์—์„œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/behind-a-proxy/image03.png">
+
+/// tip | ํŒ
+
+docs UI๋Š” ์„ ํƒํ•œ server์™€ ์ƒํ˜ธ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+OpenAPI ์‚ฌ์–‘์—์„œ `servers` ์†์„ฑ์€ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.
+
+`servers` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  `root_path`๊ฐ€ `/`์™€ ๊ฐ™๋‹ค๋ฉด, ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ์˜ `servers` ์†์„ฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์™„์ „ํžˆ ์ƒ๋žต๋˜๋ฉฐ, ์ด๋Š” `url` ๊ฐ’์ด `/`์ธ ๋‹จ์ผ server์™€ ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### `root_path`์—์„œ ์ž๋™ server ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-automatic-server-from-root-path }
+
+**FastAPI**๊ฐ€ `root_path`๋ฅผ ์‚ฌ์šฉํ•œ ์ž๋™ server๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๋ ค๋ฉด, `root_path_in_servers=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
+
+๊ทธ๋Ÿฌ๋ฉด OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+## ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งˆ์šดํŠธํ•˜๊ธฐ { #mounting-a-sub-application }
+
+ํ”„๋ก์‹œ์—์„œ `root_path`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„, [์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ๋งˆ์šดํŠธ](sub-applications.md){.internal-link target=_blank}์— ์„ค๋ช…๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์„œ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งˆ์šดํŠธํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๊ธฐ๋Œ€ํ•˜๋Š” ๋Œ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+FastAPI๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ `root_path`๋ฅผ ๋˜‘๋˜‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ๊ทธ๋ƒฅ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. โœจ
diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md
new file mode 100644 (file)
index 0000000..92ad554
--- /dev/null
@@ -0,0 +1,95 @@
+# Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #using-dataclasses }
+
+FastAPI๋Š” **Pydantic** ์œ„์— ๊ตฌ์ถ•๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ง€๊ธˆ๊นŒ์ง€๋Š” Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ ธ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ FastAPI๋Š” <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../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์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, FastAPI๋Š” Pydantic์„ ์‚ฌ์šฉํ•ด ํ‘œ์ค€ dataclasses๋ฅผ Pydantic์˜ dataclasses ๋ณ€ํ˜•์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋ฌผ๋ก  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ๋„ ๋™์ผํ•˜๊ฒŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:
+
+* ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ
+* ๋ฐ์ดํ„ฐ ์ง๋ ฌํ™”
+* ๋ฐ์ดํ„ฐ ๋ฌธ์„œํ™” ๋“ฑ
+
+์ด๋Š” Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ๋„ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” Pydantic์„ ์‚ฌ์šฉํ•ด ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+dataclasses๋Š” Pydantic ๋ชจ๋ธ์ด ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ํ•  ์ˆ˜๋Š” ์—†๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.
+
+๊ทธ๋ž˜์„œ ์—ฌ์ „ํžˆ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด๋ฏธ ์—ฌ๋Ÿฌ dataclasses๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ์ด๊ฒƒ์€ FastAPI๋กœ ์›น API๋ฅผ ๊ตฌ๋™ํ•˜๋Š” ๋ฐ ๊ทธ๊ฒƒ๋“ค์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๐Ÿค“
+
+///
+
+## `response_model`์—์„œ Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #dataclasses-in-response-model }
+
+`response_model` ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ๋„ `dataclasses`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *}
+
+dataclass๋Š” ์ž๋™์œผ๋กœ Pydantic dataclass๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ์Šคํ‚ค๋งˆ๊ฐ€ API docs ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/dataclasses/image01.png">
+
+## ์ค‘์ฒฉ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์—์„œ Dataclasses ์‚ฌ์šฉํ•˜๊ธฐ { #dataclasses-in-nested-data-structures }
+
+`dataclasses`๋ฅผ ๋‹ค๋ฅธ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ์กฐํ•ฉํ•ด ์ค‘์ฒฉ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” Pydantic ๋ฒ„์ „์˜ `dataclasses`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ž๋™ ์ƒ์„ฑ๋œ API ๋ฌธ์„œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ ํ‘œ์ค€ `dataclasses`๋ฅผ ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ธ `pydantic.dataclasses`๋กœ ๊ฐ„๋‹จํžˆ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *}
+
+1. ํ‘œ์ค€ `dataclasses`์—์„œ `field`๋ฅผ ๊ณ„์† ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค.
+
+2. `pydantic.dataclasses`๋Š” `dataclasses`์˜ ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ž…๋‹ˆ๋‹ค.
+
+3. `Author` dataclass์—๋Š” `Item` dataclasses์˜ ๋ฆฌ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+4. `Author` dataclass๊ฐ€ `response_model` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+5. ์š”์ฒญ ๋ณธ๋ฌธ์œผ๋กœ dataclasses์™€ ํ•จ๊ป˜ ๋‹ค๋ฅธ ํ‘œ์ค€ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+    ์ด ๊ฒฝ์šฐ์—๋Š” `Item` dataclasses์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
+
+6. ์—ฌ๊ธฐ์„œ๋Š” dataclasses ๋ฆฌ์ŠคํŠธ์ธ `items`๋ฅผ ํฌํ•จํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+    FastAPI๋Š” ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ <abbr title="converting the data to a format that can be transmitted - ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†ก ๊ฐ€๋Šฅํ•œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ">serializing</abbr>ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+7. ์—ฌ๊ธฐ์„œ `response_model`์€ `Author` dataclasses ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+    ๋‹ค์‹œ ๋งํ•ด, `dataclasses`๋ฅผ ํ‘œ์ค€ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+8. ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋Š” `async def` ๋Œ€์‹  ์ผ๋ฐ˜ `def`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+    ์–ธ์ œ๋‚˜์ฒ˜๋Ÿผ FastAPI์—์„œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ `def`์™€ `async def`๋ฅผ ์กฐํ•ฉํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+    ์–ด๋–ค ๊ฒƒ์„ ์–ธ์ œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, [`async`์™€ `await`](../async.md#in-a-hurry){.internal-link target=_blank} ๋ฌธ์„œ์˜ _"๊ธ‰ํ•˜์‹ ๊ฐ€์š”?"_ ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”.
+
+9. ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*๋Š” dataclasses๋ฅผ(๋ฌผ๋ก  ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ) ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ , ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๋”•์…”๋„ˆ๋ฆฌ๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+    FastAPI๋Š” `response_model` ๋งค๊ฐœ๋ณ€์ˆ˜(dataclasses ํฌํ•จ)๋ฅผ ์‚ฌ์šฉํ•ด ์‘๋‹ต์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+`dataclasses`๋Š” ๋‹ค๋ฅธ ํƒ€์ž… ์• ๋„ˆํ…Œ์ด์…˜๊ณผ ๋งค์šฐ ๋‹ค์–‘ํ•œ ์กฐํ•ฉ์œผ๋กœ ๊ฒฐํ•ฉํ•ด ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋” ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ์€ ์œ„ ์ฝ”๋“œ ๋‚ด ์• ๋„ˆํ…Œ์ด์…˜ ํŒ์„ ํ™•์ธํ•˜์„ธ์š”.
+
+## ๋” ์•Œ์•„๋ณด๊ธฐ { #learn-more }
+
+`dataclasses`๋ฅผ ๋‹ค๋ฅธ Pydantic ๋ชจ๋ธ๊ณผ ์กฐํ•ฉํ•˜๊ฑฐ๋‚˜, ์ด๋ฅผ ์ƒ์†ํ•˜๊ฑฐ๋‚˜, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ชจ๋ธ์— ํฌํ•จํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ž์„ธํ•œ ๋‚ด์šฉ์€ <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">dataclasses์— ๊ด€ํ•œ Pydantic ๋ฌธ์„œ</a>๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+## ๋ฒ„์ „ { #version }
+
+์ด ๊ธฐ๋Šฅ์€ FastAPI `0.67.0` ๋ฒ„์ „๋ถ€ํ„ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ”–
diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md
new file mode 100644 (file)
index 0000000..1def3ef
--- /dev/null
@@ -0,0 +1,208 @@
+# SDK ์ƒ์„ฑํ•˜๊ธฐ { #generating-sdks }
+
+**FastAPI**๋Š” **OpenAPI** ์‚ฌ์–‘์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ, FastAPI์˜ API๋Š” ๋งŽ์€ ๋„๊ตฌ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ‘œ์ค€ ํ˜•์‹์œผ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋•๋ถ„์— ์—ฌ๋Ÿฌ ์–ธ์–ด์šฉ ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(<abbr title="Software Development Kits - ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ํ‚คํŠธ">**SDKs**</abbr>), ์ตœ์‹  **๋ฌธ์„œ**, ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์™€ ๋™๊ธฐํ™”๋œ **ํ…Œ์ŠคํŠธ** ๋˜๋Š” **์ž๋™ํ™” ์›Œํฌํ”Œ๋กœ**๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” FastAPI ๋ฐฑ์—”๋“œ์šฉ **TypeScript SDK**๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค.
+
+## ์˜คํ”ˆ ์†Œ์Šค SDK ์ƒ์„ฑ๊ธฐ { #open-source-sdk-generators }
+
+๋‹ค์–‘ํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์œผ๋กœ <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>๊ฐ€ ์žˆ์œผ๋ฉฐ, **๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด**๋ฅผ ์ง€์›ํ•˜๊ณ  OpenAPI ์‚ฌ์–‘์œผ๋กœ๋ถ€ํ„ฐ SDK๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**TypeScript ํด๋ผ์ด์–ธํŠธ**์˜ ๊ฒฝ์šฐ <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a>๋Š” TypeScript ์ƒํƒœ๊ณ„์— ์ตœ์ ํ™”๋œ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ๋ชฉ์ ์— ๋งž๊ฒŒ ์„ค๊ณ„๋œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.
+
+๋” ๋งŽ์€ SDK ์ƒ์„ฑ๊ธฐ๋Š” <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+FastAPI๋Š” **OpenAPI 3.1** ์‚ฌ์–‘์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๋Š” ์ด ๋ฒ„์ „์„ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## FastAPI ์Šคํฐ์„œ์˜ SDK ์ƒ์„ฑ๊ธฐ { #sdk-generators-from-fastapi-sponsors }
+
+์ด ์„น์…˜์—์„œ๋Š” FastAPI๋ฅผ ํ›„์›ํ•˜๋Š” ํšŒ์‚ฌ๋“ค์ด ์ œ๊ณตํ•˜๋Š” **๋ฒค์ฒ˜ ํˆฌ์ž ๊ธฐ๋ฐ˜** ๋ฐ **๊ธฐ์—… ์ง€์›** ์†”๋ฃจ์…˜์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์ด ์ œํ’ˆ๋“ค์€ ๊ณ ํ’ˆ์งˆ๋กœ ์ƒ์„ฑ๋œ SDK์— ๋”ํ•ด **์ถ”๊ฐ€ ๊ธฐ๋Šฅ**๊ณผ **ํ†ตํ•ฉ**์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+โœจ [**FastAPI ํ›„์›ํ•˜๊ธฐ**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} โœจ๋ฅผ ํ†ตํ•ด, ์ด ํšŒ์‚ฌ๋“ค์€ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๊ทธ **์ƒํƒœ๊ณ„**๊ฐ€ ๊ฑด๊ฐ•ํ•˜๊ณ  **์ง€์† ๊ฐ€๋Šฅ**ํ•˜๊ฒŒ ์œ ์ง€๋˜๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์ด๋“ค์˜ ํ›„์›์€ 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>
+
+์ด ์ค‘ ์ผ๋ถ€๋Š” ์˜คํ”ˆ ์†Œ์Šค์ด๊ฑฐ๋‚˜ ๋ฌด๋ฃŒ ํ‹ฐ์–ด๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ๋น„์šฉ ๋ถ€๋‹ด ์—†์ด ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ƒ์šฉ SDK ์ƒ์„ฑ๊ธฐ๋„ ์žˆ์œผ๋ฉฐ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
+
+## TypeScript SDK ๋งŒ๋“ค๊ธฐ { #create-a-typescript-sdk }
+
+๊ฐ„๋‹จํ•œ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
+
+*path operation*์—์„œ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ์™€ ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ์— ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋ธ์„ `Item`, `ResponseMessage` ๋ชจ๋ธ๋กœ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+### API ๋ฌธ์„œ { #api-docs }
+
+`/docs`๋กœ ์ด๋™ํ•˜๋ฉด, ์š”์ฒญ์œผ๋กœ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ์™€ ์‘๋‹ต์œผ๋กœ ๋ฐ›์„ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ **์Šคํ‚ค๋งˆ(schemas)**๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image01.png">
+
+์ด ์Šคํ‚ค๋งˆ๋Š” ์•ฑ์—์„œ ๋ชจ๋ธ๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ์ •๋ณด๋Š” ์•ฑ์˜ **OpenAPI ์Šคํ‚ค๋งˆ**์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์ดํ›„ API ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+
+OpenAPI์— ํฌํ•จ๋œ ๋ชจ๋ธ์˜ ๋™์ผํ•œ ์ •๋ณด๊ฐ€ **ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ƒ์„ฑ**์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### Hey API { #hey-api }
+
+๋ชจ๋ธ์ด ํฌํ•จ๋œ FastAPI ์•ฑ์ด ์ค€๋น„๋˜๋ฉด, Hey API๋ฅผ ์‚ฌ์šฉํ•ด TypeScript ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋น ๋ฅธ ๋ฐฉ๋ฒ•์€ npx๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+```sh
+npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
+```
+
+์ด ๋ช…๋ น์€ `./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>์€ ํ•ด๋‹น ์›น์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### SDK ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-sdk }
+
+์ด์ œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ importํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ์ด ์ œ๊ณต๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image02.png">
+
+๋ณด๋‚ผ ํŽ˜์ด๋กœ๋“œ์— ๋Œ€ํ•ด์„œ๋„ ์ž๋™ ์™„์„ฑ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image03.png">
+
+/// tip | ํŒ
+
+`name`๊ณผ `price`์— ๋Œ€ํ•œ ์ž๋™ ์™„์„ฑ์€ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ `Item` ๋ชจ๋ธ์— ์ •์˜๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
+
+///
+
+์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ์ธ๋ผ์ธ ์˜ค๋ฅ˜๋„ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image04.png">
+
+์‘๋‹ต ๊ฐ์ฒด๋„ ์ž๋™ ์™„์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image05.png">
+
+## ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” FastAPI ์•ฑ { #fastapi-app-with-tags }
+
+๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ FastAPI ์•ฑ์€ ๋” ์ปค์ง€๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ *path operations* ๊ทธ๋ฃน์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด **items** ์„น์…˜๊ณผ **users** ์„น์…˜์ด ์žˆ๊ณ , ์ด๋ฅผ ํƒœ๊ทธ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
+
+### ํƒœ๊ทธ๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-tags }
+
+ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” FastAPI ์•ฑ์— ๋Œ€ํ•ด ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ํƒœ๊ทธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ํ•ญ๋ชฉ๋“ค์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ •๋ ฌ๋˜๊ณ  ๊ทธ๋ฃนํ™”๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image06.png">
+
+์ด ๊ฒฝ์šฐ ๋‹ค์Œ์ด ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* `ItemsService`
+* `UsersService`
+
+### ํด๋ผ์ด์–ธํŠธ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ { #client-method-names }
+
+ํ˜„์žฌ `createItemItemsPost` ๊ฐ™์€ ์ƒ์„ฑ๋œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ๊ทธ๋‹ค์ง€ ๊น”๋”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:
+
+```TypeScript
+ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
+```
+
+...์ด๋Š” ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ ๊ฐ *path operation*์— ๋Œ€ํ•ด OpenAPI ๋‚ด๋ถ€์˜ **operation ID**๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+OpenAPI๋Š” ๋ชจ๋“  *path operations* ์ „์ฒด์—์„œ operation ID๊ฐ€ ๊ฐ๊ฐ ์œ ์ผํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ FastAPI๋Š” operation ID๊ฐ€ ์œ ์ผํ•˜๋„๋ก **ํ•จ์ˆ˜ ์ด๋ฆ„**, **๊ฒฝ๋กœ**, **HTTP method/operation**์„ ์กฐํ•ฉํ•ด operation ID๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋‹ค์Œ์—์„œ ์ด๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
+
+## ์ปค์Šคํ…€ Operation ID์™€ ๋” ๋‚˜์€ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ { #custom-operation-ids-and-better-method-names }
+
+ํด๋ผ์ด์–ธํŠธ์—์„œ **๋” ๋‹จ์ˆœํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„**์„ ๊ฐ–๋„๋ก, operation ID๊ฐ€ **์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹**์„ **์ˆ˜์ •**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ operation ID๊ฐ€ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ๋„ **์œ ์ผ**ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ *path operation*์ด ํƒœ๊ทธ๋ฅผ ๊ฐ–๋„๋ก ํ•œ ๋‹ค์Œ, **ํƒœ๊ทธ**์™€ *path operation* **์ด๋ฆ„**(ํ•จ์ˆ˜ ์ด๋ฆ„)์„ ๊ธฐ๋ฐ˜์œผ๋กœ operation ID๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์œ ์ผ ID ์ƒ์„ฑ ํ•จ์ˆ˜ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• { #custom-generate-unique-id-function }
+
+FastAPI๋Š” ๊ฐ *path operation*์— ๋Œ€ํ•ด **์œ ์ผ ID**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋Š” **operation ID** ๋ฐ ์š”์ฒญ/์‘๋‹ต์— ํ•„์š”ํ•œ ์ปค์Šคํ…€ ๋ชจ๋ธ ์ด๋ฆ„์—๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+์ด ํ•จ์ˆ˜๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” `APIRoute`๋ฅผ ๋ฐ›์•„ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ํƒœ๊ทธ(๋Œ€๋ถ€๋ถ„ ํƒœ๊ทธ๋Š” ํ•˜๋‚˜๋งŒ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค)์™€ *path operation* ์ด๋ฆ„(ํ•จ์ˆ˜ ์ด๋ฆ„)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ์ด ์ปค์Šคํ…€ ํ•จ์ˆ˜๋ฅผ `generate_unique_id_function` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ **FastAPI**์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
+
+### ์ปค์Šคํ…€ Operation ID๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-custom-operation-ids }
+
+์ด์ œ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋‹ค์‹œ ์ƒ์„ฑํ•˜๋ฉด, ๊ฐœ์„ ๋œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image07.png">
+
+๋ณด์‹œ๋‹ค์‹œํ”ผ, ์ด์ œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ํƒœ๊ทธ ๋‹ค์Œ์— ํ•จ์ˆ˜ ์ด๋ฆ„์ด ์˜ค๋ฉฐ, URL ๊ฒฝ๋กœ์™€ HTTP operation์˜ ์ •๋ณด๋Š” ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+### ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๋ฅผ ์œ„ํ•œ OpenAPI ์‚ฌ์–‘ ์ „์ฒ˜๋ฆฌ { #preprocess-the-openapi-specification-for-the-client-generator }
+
+์ƒ์„ฑ๋œ ์ฝ”๋“œ์—๋Š” ์—ฌ์ „ํžˆ ์ผ๋ถ€ **์ค‘๋ณต ์ •๋ณด**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`ItemsService`(ํƒœ๊ทธ์—์„œ ๊ฐ€์ ธ์˜ด)์— ์ด๋ฏธ **items**๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด ์ด ๋ฉ”์„œ๋“œ๊ฐ€ items์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฉ”์„œ๋“œ ์ด๋ฆ„์—๋„ ํƒœ๊ทธ ์ด๋ฆ„์ด ์ ‘๋‘์‚ฌ๋กœ ๋ถ™์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜•
+
+OpenAPI ์ „๋ฐ˜์—์„œ๋Š” operation ID๊ฐ€ **์œ ์ผ**ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ด ๋ฐฉ์‹์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š”, ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ง์ „์— OpenAPI operation ID๋ฅผ **์ˆ˜์ •**ํ•ด์„œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋” ๋ณด๊ธฐ ์ข‹๊ณ  **๊น”๋”ํ•˜๊ฒŒ** ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+OpenAPI JSON์„ `openapi.json` ํŒŒ์ผ๋กœ ๋‹ค์šด๋กœ๋“œํ•œ ๋’ค, ์•„๋ž˜์™€ ๊ฐ™์€ ์Šคํฌ๋ฆฝํŠธ๋กœ **์ ‘๋‘์‚ฌ ํƒœ๊ทธ๋ฅผ ์ œ๊ฑฐ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/generate_clients/tutorial004_py39.py *}
+
+//// tab | Node.js
+
+```Javascript
+{!> ../../docs_src/generate_clients/tutorial004.js!}
+```
+
+////
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด operation ID๊ฐ€ `items-get_items` ๊ฐ™์€ ํ˜•ํƒœ์—์„œ `get_items`๋กœ ๋ณ€๊ฒฝ๋˜์–ด, ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ ๋” ๋‹จ์ˆœํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์ „์ฒ˜๋ฆฌ๋œ OpenAPI๋กœ TypeScript ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑํ•˜๊ธฐ { #generate-a-typescript-client-with-the-preprocessed-openapi }
+
+์ด์ œ ์ตœ์ข… ๊ฒฐ๊ณผ๊ฐ€ `openapi.json` ํŒŒ์ผ์— ์žˆ์œผ๋ฏ€๋กœ, ์ž…๋ ฅ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
+
+```sh
+npx @hey-api/openapi-ts -i ./openapi.json -o src/client
+```
+
+์ƒˆ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” **๊น”๋”ํ•œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„**์„ ๊ฐ€์ง€๋ฉด์„œ๋„, **์ž๋™ ์™„์„ฑ**, **์ธ๋ผ์ธ ์˜ค๋ฅ˜** ๋“ฑ์€ ๊ทธ๋Œ€๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/generate-clients/image08.png">
+
+## ์žฅ์  { #benefits }
+
+์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์— ๋Œ€ํ•ด **์ž๋™ ์™„์„ฑ**์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* ๋ฉ”์„œ๋“œ
+* ๋ณธ๋ฌธ(body)์˜ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ, ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ
+* ์‘๋‹ต ํŽ˜์ด๋กœ๋“œ
+
+๋˜ํ•œ ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด **์ธ๋ผ์ธ ์˜ค๋ฅ˜**๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋ฐฑ์—”๋“œ ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ๋’ค ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ **์žฌ์ƒ์„ฑ(regenerate)**ํ•˜๋ฉด, ์ƒˆ *path operations*๊ฐ€ ๋ฉ”์„œ๋“œ๋กœ ์ถ”๊ฐ€๋˜๊ณ  ๊ธฐ์กด ๊ฒƒ์€ ์ œ๊ฑฐ๋˜๋ฉฐ, ๊ทธ ๋ฐ–์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋„ ์ƒ์„ฑ๋œ ์ฝ”๋“œ์— ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๐Ÿค“
+
+์ด๋Š” ๋ฌด์–ธ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ ๋ณ€๊ฒฝ์ด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—๋„ ์ž๋™์œผ๋กœ **๋ฐ˜์˜**๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ํด๋ผ์ด์–ธํŠธ๋ฅผ **๋นŒ๋“œ(build)**ํ•˜๋ฉด ์‚ฌ์šฉ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ **๋ถˆ์ผ์น˜(mismatch)**ํ•  ๊ฒฝ์šฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์ตœ์ข… ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋…ธ์ถœ๋œ ๋’ค ๋ฌธ์ œ๋ฅผ ์ถ”์ ํ•˜๋Š” ๋Œ€์‹ , ๊ฐœ๋ฐœ ์‚ฌ์ดํด ์ดˆ๊ธฐ์— **๋งŽ์€ ์˜ค๋ฅ˜๋ฅผ ๋งค์šฐ ๋นจ๋ฆฌ ๊ฐ์ง€**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ
diff --git a/docs/ko/docs/advanced/middleware.md b/docs/ko/docs/advanced/middleware.md
new file mode 100644 (file)
index 0000000..be2c972
--- /dev/null
@@ -0,0 +1,97 @@
+# ๊ณ ๊ธ‰ Middleware { #advanced-middleware }
+
+๋ฉ”์ธ ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— [์ปค์Šคํ…€ Middleware](../tutorial/middleware.md){.internal-link target=_blank}๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  [`CORSMiddleware`๋กœ CORS ์ฒ˜๋ฆฌํ•˜๊ธฐ](../tutorial/cors.md){.internal-link target=_blank}๋„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ์„น์…˜์—์„œ๋Š” ๋‹ค๋ฅธ middleware๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ASGI middleware ์ถ”๊ฐ€ํ•˜๊ธฐ { #adding-asgi-middlewares }
+
+**FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ์–ด๋–ค ASGI middleware๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ASGI ์‚ฌ์–‘์„ ๋”ฐ๋ฅด๊ธฐ๋งŒ ํ•˜๋ฉด, FastAPI๋‚˜ Starlette๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ middleware๊ฐ€ ์•„๋‹ˆ์–ด๋„ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+์ผ๋ฐ˜์ ์œผ๋กœ ASGI middleware๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ASGI ์•ฑ์„ ๋ฐ›๋„๋ก ๊ธฐ๋Œ€ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ์„œ๋“œํŒŒํ‹ฐ ASGI middleware ๋ฌธ์„œ์—์„œ๋Š” ์•„๋งˆ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ผ๊ณ  ์•ˆ๋‚ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+ํ•˜์ง€๋งŒ FastAPI(์ •ํ™•ํžˆ๋Š” Starlette)๋Š” ๋” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋‚ด๋ถ€ middleware๊ฐ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์œ„ํ•ด(๊ทธ๋ฆฌ๊ณ  CORS ์˜ˆ์ œ์—์„œ์ฒ˜๋Ÿผ) `app.add_middleware()`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()`๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ middleware ํด๋ž˜์Šค๋ฅผ ๋ฐ›๊ณ , ๊ทธ ๋’ค์—๋Š” middleware์— ์ „๋‹ฌํ•  ์ถ”๊ฐ€ ์ธ์ž๋“ค์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
+
+## ํ†ตํ•ฉ middleware { #integrated-middlewares }
+
+**FastAPI**์—๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ middleware๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์—์„œ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” `from starlette.middleware.something import SomethingMiddleware`๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž ํŽธ์˜๋ฅผ ์œ„ํ•ด `fastapi.middleware`์— ์—ฌ๋Ÿฌ middleware๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ middleware๋Š” Starlette์—์„œ ์ง์ ‘ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware }
+
+๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์ด `https` ๋˜๋Š” `wss`์—ฌ์•ผ ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
+
+`http` ๋˜๋Š” `ws`๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ ๋Œ€์‹  ๋ณด์•ˆ ์Šคํ‚ด์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
+
+## `TrustedHostMiddleware` { #trustedhostmiddleware }
+
+HTTP Host Header ๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด, ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋œ `Host` ํ—ค๋”๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
+
+๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:
+
+* `allowed_hosts` - ํ˜ธ์ŠคํŠธ๋ช…์œผ๋กœ ํ—ˆ์šฉํ•  ๋„๋ฉ”์ธ ์ด๋ฆ„ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. `*.example.com` ๊ฐ™์€ ์™€์ผ๋“œ์นด๋“œ ๋„๋ฉ”์ธ์œผ๋กœ ์„œ๋ธŒ๋„๋ฉ”์ธ์„ ๋งค์นญํ•˜๋Š” ๊ฒƒ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ํ˜ธ์ŠคํŠธ๋ช…์ด๋“  ํ—ˆ์šฉํ•˜๋ ค๋ฉด `allowed_hosts=["*"]`๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ middleware๋ฅผ ์ƒ๋žตํ•˜์„ธ์š”.
+* `www_redirect` - True๋กœ ์„ค์ •ํ•˜๋ฉด, ํ—ˆ์šฉ๋œ ํ˜ธ์ŠคํŠธ์˜ non-www ๋ฒ„์ „์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ www ๋ฒ„์ „์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `True`์ž…๋‹ˆ๋‹ค.
+
+๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ฒ€์ฆ๋˜์ง€ ์•Š์œผ๋ฉด `400` ์‘๋‹ต์ด ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
+
+## `GZipMiddleware` { #gzipmiddleware }
+
+`Accept-Encoding` ํ—ค๋”์— `"gzip"`์ด ํฌํ•จ๋œ ์–ด๋–ค ์š”์ฒญ์ด๋“  GZip ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+์ด middleware๋Š” ์ผ๋ฐ˜ ์‘๋‹ต๊ณผ ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
+
+๋‹ค์Œ ์ธ์ž๋“ค์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:
+
+* `minimum_size` - ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ง€์ •ํ•œ ์ตœ์†Œ ํฌ๊ธฐ๋ณด๋‹ค ์ž‘์€ ์‘๋‹ต์€ GZip์œผ๋กœ ์••์ถ•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `500`์ž…๋‹ˆ๋‹ค.
+* `compresslevel` - GZip ์••์ถ• ์ค‘์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 1๋ถ€ํ„ฐ 9๊นŒ์ง€์˜ ์ •์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `9`์ž…๋‹ˆ๋‹ค. ๊ฐ’์ด ๋‚ฎ์„์ˆ˜๋ก ์••์ถ•์€ ๋” ๋น ๋ฅด์ง€๋งŒ ํŒŒ์ผ ํฌ๊ธฐ๋Š” ๋” ์ปค์ง€๊ณ , ๊ฐ’์ด ๋†’์„์ˆ˜๋ก ์••์ถ•์€ ๋” ๋А๋ฆฌ์ง€๋งŒ ํŒŒ์ผ ํฌ๊ธฐ๋Š” ๋” ์ž‘์•„์ง‘๋‹ˆ๋‹ค.
+
+## ๋‹ค๋ฅธ middleware { #other-middlewares }
+
+๋‹ค๋ฅธ ASGI 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>
+
+์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ 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>๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md
new file mode 100644 (file)
index 0000000..e4bdea9
--- /dev/null
@@ -0,0 +1,186 @@
+# OpenAPI ์ฝœ๋ฐฑ { #openapi-callbacks }
+
+๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋งŒ๋“  *external API*(์•„๋งˆ๋„ ๋‹น์‹ ์˜ API๋ฅผ *์‚ฌ์šฉ*ํ•  ๋™์ผํ•œ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์š”์ฒญ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“œ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ง„ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹น์‹ ์˜ API ์•ฑ์ด *external API*๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ผ์–ด๋‚˜๋Š” ๊ณผ์ •์„ "callback"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋‹น์‹ ์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๋‹ค์Œ, ๋‹น์‹ ์˜ API๊ฐ€ ๋‹ค์‹œ *external API*๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด *๋˜๋Œ๋ ค ํ˜ธ์ถœ*ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์•„๋งˆ๋„ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งŒ๋“  API์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค).
+
+์ด ๊ฒฝ์šฐ, ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๋Š”์ง€, ์–ด๋–ค body๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š”์ง€, ์–ด๋–ค ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ๋“ฑ์ž…๋‹ˆ๋‹ค.
+
+## ์ฝœ๋ฐฑ์ด ์žˆ๋Š” ์•ฑ { #an-app-with-callbacks }
+
+์˜ˆ์‹œ๋กœ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์•ฑ์„ ๊ฐœ๋ฐœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด์„ธ์š”.
+
+์ด ์ฒญ๊ตฌ์„œ๋Š” `id`, `title`(์„ ํƒ ์‚ฌํ•ญ), `customer`, `total`์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.
+
+๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๋Š” POST ์š”์ฒญ์œผ๋กœ ๋‹น์‹ ์˜ API์—์„œ ์ฒญ๊ตฌ์„œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ๋‹น์‹ ์˜ API๋Š”(๊ฐ€์ •ํ•ด ๋ณด๋ฉด):
+
+* ์ฒญ๊ตฌ์„œ๋ฅผ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ณ ๊ฐ์—๊ฒŒ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
+* ๋ˆ์„ ์ˆ˜๊ธˆํ•ฉ๋‹ˆ๋‹ค.
+* API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)์˜ API๋กœ ๋‹ค์‹œ ์•Œ๋ฆผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
+    * ์ด๋Š” (๋‹น์‹ ์˜ API์—์„œ) ๊ทธ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์–ด๋–ค *external API*๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค(์ด๊ฒƒ์ด "callback"์ž…๋‹ˆ๋‹ค).
+
+## ์ผ๋ฐ˜์ ์ธ **FastAPI** ์•ฑ { #the-normal-fastapi-app }
+
+๋จผ์ € ์ฝœ๋ฐฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „, ์ผ๋ฐ˜์ ์ธ API ์•ฑ์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+`Invoice` body๋ฅผ ๋ฐ›๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€, ์ฝœ๋ฐฑ์„ ์œ„ํ•œ URL์„ ๋‹ด๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ `callback_url`์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด ๋ถ€๋ถ„์€ ๊ฝค ์ผ๋ฐ˜์ ์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ๋Š” ์ด๋ฏธ ์ต์ˆ™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
+
+/// tip | ํŒ
+
+`callback_url` ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” Pydantic์˜ <a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a> ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+์œ ์ผํ•˜๊ฒŒ ์ƒˆ๋กœ์šด ๊ฒƒ์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์˜ ์ธ์ž๋กœ `callbacks=invoices_callback_router.routes`๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ๋‹ค์Œ์—์„œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ์ฝœ๋ฐฑ ๋ฌธ์„œํ™”ํ•˜๊ธฐ { #documenting-the-callback }
+
+์‹ค์ œ ์ฝœ๋ฐฑ ์ฝ”๋“œ๋Š” ๋‹น์‹ ์˜ API ์•ฑ์— ํฌ๊ฒŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์•ฑ๋งˆ๋‹ค ๋งŽ์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ์ฒ˜๋Ÿผ ํ•œ๋‘ ์ค„์˜ ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+ํ•˜์ง€๋งŒ ์ฝœ๋ฐฑ์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€, ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ ์ฝœ๋ฐฑ ์š”์ฒญ body๋กœ *๋‹น์‹ ์˜ API*๊ฐ€ ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ ๋“ฑ์— ๋งž์ถฐ *external API*๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ๋‹ค์Œ์œผ๋กœ ํ•  ์ผ์€, *๋‹น์‹ ์˜ API*์—์„œ ๋ณด๋‚ด๋Š” ์ฝœ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ ๋ฌธ์„œ๋Š” ๋‹น์‹ ์˜ API์—์„œ `/docs`์˜ Swagger UI์— ํ‘œ์‹œ๋˜๋ฉฐ, ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์ด *external API*๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์‹œ๋Š” ์ฝœ๋ฐฑ ์ž์ฒด(ํ•œ ์ค„ ์ฝ”๋“œ๋กœ๋„ ๋  ์ˆ˜ ์žˆ์Œ)๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ๋ฌธ์„œํ™” ๋ถ€๋ถ„๋งŒ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์‹ค์ œ ์ฝœ๋ฐฑ์€ ๋‹จ์ง€ 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> ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## ์ฝœ๋ฐฑ ๋ฌธ์„œํ™” ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ { #write-the-callback-documentation-code }
+
+์ด ์ฝ”๋“œ๋Š” ์•ฑ์—์„œ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ *๋ฌธ์„œํ™”*ํ•˜๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ **FastAPI**๋กœ API์˜ ์ž๋™ ๋ฌธ์„œ๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ๊ทธ์™€ ๊ฐ™์€ ์ง€์‹์„ ์‚ฌ์šฉํ•ด *external API*๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒจ์•ผ ํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค... ์ฆ‰ ์™ธ๋ถ€ API๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(๋‹น์‹ ์˜ API๊ฐ€ ํ˜ธ์ถœํ•  ๊ฒƒ๋“ค)์„ ๋งŒ๋“ค์–ด์„œ ๋ง์ž…๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ฝœ๋ฐฑ์„ ๋ฌธ์„œํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š”, ์ž์‹ ์ด ๊ทธ *์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž*๋ผ๊ณ  ์ƒ์ƒํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ์€ *๋‹น์‹ ์˜ API*๊ฐ€ ์•„๋‹ˆ๋ผ *external API*๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”.
+
+์ด ๊ด€์ (์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ด€์ )์„ ์ž ์‹œ ์ฑ„ํƒํ•˜๋ฉด, ๊ทธ *external API*๋ฅผ ์œ„ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ, body์šฉ Pydantic ๋ชจ๋ธ, ์‘๋‹ต ๋“ฑ์„ ์–ด๋””์— ๋‘์–ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ๋А๊ปด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+### ์ฝœ๋ฐฑ `APIRouter` ์ƒ์„ฑํ•˜๊ธฐ { #create-a-callback-apirouter }
+
+๋จผ์ € ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฝœ๋ฐฑ์„ ๋‹ด์„ ์ƒˆ `APIRouter`๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
+
+### ์ฝœ๋ฐฑ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ƒ์„ฑํ•˜๊ธฐ { #create-the-callback-path-operation }
+
+์ฝœ๋ฐฑ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ์œ„์—์„œ ๋งŒ๋“  ๋™์ผํ•œ `APIRouter`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์ผ๋ฐ˜์ ์ธ FastAPI *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์ฒ˜๋Ÿผ ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+* ์•„๋งˆ๋„ ๋ฐ›์•„์•ผ ํ•  body ์„ ์–ธ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ: `body: InvoiceEvent`).
+* ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•  ์‘๋‹ต ์„ ์–ธ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: `response_model=InvoiceEventReceived`).
+
+{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
+
+์ผ๋ฐ˜์ ์ธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€์˜ ์ฃผ์š” ์ฐจ์ด์ ์€ 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*๋กœ ๋ณด๋‚ด์ง„ ์›๋ž˜ ์š”์ฒญ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ผ๋ถ€ ๊ฐ’์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์ฝœ๋ฐฑ ๊ฒฝ๋กœ ํ‘œํ˜„์‹ { #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>์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ, ๋‹ค์Œ `str`์ž…๋‹ˆ๋‹ค:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+๋”ฐ๋ผ์„œ ๋‹น์‹ ์˜ API ์‚ฌ์šฉ์ž(์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž)๊ฐ€ *๋‹น์‹ ์˜ API*๋กœ ๋‹ค์Œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ :
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+JSON body๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๋ฉด:
+
+```JSON
+{
+    "id": "2expen51ve",
+    "customer": "Mr. Richie Rich",
+    "total": "9999"
+}
+```
+
+๊ทธ๋Ÿฌ๋ฉด *๋‹น์‹ ์˜ API*๋Š” ์ฒญ๊ตฌ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—์„œ `callback_url`(์ฆ‰ *external API*)๋กœ ์ฝœ๋ฐฑ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค:
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ JSON body๋ฅผ ํฌํ•จํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "description": "Payment celebration",
+    "paid": true
+}
+```
+
+๋˜ํ•œ ๊ทธ *external API*๋กœ๋ถ€ํ„ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ JSON body ์‘๋‹ต์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค:
+
+```JSON
+{
+    "ok": true
+}
+```
+
+/// tip | ํŒ
+
+์ฝœ๋ฐฑ URL์—๋Š” `callback_url` ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ URL(`https://www.external.org/events`)๋ฟ ์•„๋‹ˆ๋ผ, JSON body ์•ˆ์˜ ์ฒญ๊ตฌ์„œ `id`(`2expen51ve`)๋„ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+///
+
+### ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-the-callback-router }
+
+์ด ์‹œ์ ์—์„œ, ์œ„์—์„œ ๋งŒ๋“  ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ ์•ˆ์— *์ฝœ๋ฐฑ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ(๋“ค)*(์ฆ‰ *external developer*๊ฐ€ *external API*์— ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค)์„ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+์ด์ œ *๋‹น์‹ ์˜ API ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ `callbacks` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด, ๊ทธ ์ฝœ๋ฐฑ ๋ผ์šฐํ„ฐ์˜ `.routes` ์†์„ฑ(์‹ค์ œ๋กœ๋Š” routes/*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `list`)์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
+
+/// tip | ํŒ
+
+`callback=`์— ๋ผ์šฐํ„ฐ ์ž์ฒด(`invoices_callback_router`)๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, `invoices_callback_router.routes`์ฒ˜๋Ÿผ `.routes` ์†์„ฑ์„ ๋„˜๊ธด๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+///
+
+### ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #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>๋กœ ์ด๋™ํ•˜์„ธ์š”.
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด "Callbacks" ์„น์…˜์„ ํฌํ•จํ•œ ๋ฌธ์„œ๊ฐ€ ํ‘œ์‹œ๋˜๋ฉฐ, *external API*๊ฐ€ ์–ด๋–ค ํ˜•ํƒœ์—ฌ์•ผ ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/openapi-callbacks/image01.png">
diff --git a/docs/ko/docs/advanced/openapi-webhooks.md b/docs/ko/docs/advanced/openapi-webhooks.md
new file mode 100644 (file)
index 0000000..89cacf7
--- /dev/null
@@ -0,0 +1,55 @@
+# OpenAPI Webhooks { #openapi-webhooks }
+
+์•ฑ์ด ์–ด๋–ค ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ (์š”์ฒญ์„ ๋ณด๋‚ด์„œ) *์‚ฌ์šฉ์ž์˜* ์•ฑ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ณ , ๋ณดํ†ต ์–ด๋–ค **์ด๋ฒคํŠธ**๋ฅผ **์•Œ๋ฆฌ๊ธฐ** ์œ„ํ•ด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ API **์‚ฌ์šฉ์ž**์—๊ฒŒ ์•Œ๋ ค์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ผ๋ฐ˜์ ์ธ ๊ณผ์ • ๋Œ€์‹ , **์—ฌ๋Ÿฌ๋ถ„์˜ API**(๋˜๋Š” ์•ฑ)๊ฐ€ **์‚ฌ์šฉ์ž์˜ ์‹œ์Šคํ…œ**(์‚ฌ์šฉ์ž์˜ API, ์‚ฌ์šฉ์ž์˜ ์•ฑ)์œผ๋กœ **์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค**๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ๋ณดํ†ต **webhook**์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
+
+## Webhooks ๋‹จ๊ณ„ { #webhooks-steps }
+
+์ผ๋ฐ˜์ ์ธ ๊ณผ์ •์€, ์—ฌ๋Ÿฌ๋ถ„์ด ์ฝ”๋“œ์—์„œ ๋ณด๋‚ผ ๋ฉ”์‹œ์ง€, ์ฆ‰ **์š”์ฒญ ๋ณธ๋ฌธ(body)**์ด ๋ฌด์—‡์ธ์ง€ **์ •์˜**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์–ด๋–ค **์‹œ์ **์— ๊ทธ ์š”์ฒญ(๋˜๋Š” ์ด๋ฒคํŠธ)์„ ๋ณด๋‚ผ์ง€๋„ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  **์‚ฌ์šฉ์ž**๋Š” (์˜ˆ: ์–ด๋”˜๊ฐ€์˜ ์›น ๋Œ€์‹œ๋ณด๋“œ์—์„œ) ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๊ทธ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•  **URL**์„ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+
+webhook์˜ URL์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์‹ค์ œ๋กœ ๊ทธ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋ชจ๋“  **๋กœ์ง**์€ ์—ฌ๋Ÿฌ๋ถ„์—๊ฒŒ ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. **์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ**์—์„œ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
+
+## **FastAPI**์™€ OpenAPI๋กœ webhooks ๋ฌธ์„œํ™”ํ•˜๊ธฐ { #documenting-webhooks-with-fastapi-and-openapi }
+
+**FastAPI**์—์„œ๋Š” OpenAPI๋ฅผ ์‚ฌ์šฉํ•ด, ์ด๋Ÿฌํ•œ webhook์˜ ์ด๋ฆ„, ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” HTTP ์ž‘์—… ํƒ€์ž…(์˜ˆ: `POST`, `PUT` ๋“ฑ), ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ๋ณด๋‚ผ ์š”์ฒญ **๋ณธ๋ฌธ(body)**์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ **webhook** ์š”์ฒญ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด **์ž์‹ ๋“ค์˜ API๋ฅผ ๊ตฌํ˜„**ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›Œ์ง€๊ณ , ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ๋Š” ์ž์‹ ์˜ API ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+Webhooks๋Š” OpenAPI 3.1.0 ์ด์ƒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI `0.99.0` ์ด์ƒ์—์„œ ์ง€์›๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## webhooks๊ฐ€ ์žˆ๋Š” ์•ฑ { #an-app-with-webhooks }
+
+**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ(์˜ˆ: `@app.webhooks.post()`), *webhooks*๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” `webhooks` ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
+
+์—ฌ๋Ÿฌ๋ถ„์ด ์ •์˜ํ•œ webhook์€ **OpenAPI** ์Šคํ‚ค๋งˆ์™€ ์ž๋™ **docs UI**์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+`app.webhooks` ๊ฐ์ฒด๋Š” ์‹ค์ œ๋กœ `APIRouter`์ผ ๋ฟ์ด๋ฉฐ, ์—ฌ๋Ÿฌ ํŒŒ์ผ๋กœ ์•ฑ์„ ๊ตฌ์กฐํ™”ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.
+
+///
+
+webhook์—์„œ๋Š” ์‹ค์ œ๋กœ(`/items/` ๊ฐ™์€) *๊ฒฝ๋กœ(path)*๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ๊ทธ๊ณณ์— ์ „๋‹ฌํ•˜๋Š” ํ…์ŠคํŠธ๋Š” webhook์˜ **์‹๋ณ„์ž**(์ด๋ฒคํŠธ ์ด๋ฆ„)์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `@app.webhooks.post("new-subscription")`์—์„œ webhook ์ด๋ฆ„์€ `new-subscription`์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” **์‚ฌ์šฉ์ž**๊ฐ€ webhook ์š”์ฒญ์„ ๋ฐ›๊ณ  ์‹ถ์€ ์‹ค์ œ **URL ๊ฒฝ๋กœ**๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹(์˜ˆ: ์›น ๋Œ€์‹œ๋ณด๋“œ)์œผ๋กœ ์ •์˜ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+### ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #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>๋กœ ์ด๋™ํ•˜์„ธ์š”.
+
+๋ฌธ์„œ์— ์ผ๋ฐ˜์ ์ธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ๋ณด์ด๊ณ , ์ด์ œ๋Š” ์ผ๋ถ€ **webhooks**๋„ ํ•จ๊ป˜ ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/openapi-webhooks/image01.png">
diff --git a/docs/ko/docs/advanced/path-operation-advanced-configuration.md b/docs/ko/docs/advanced/path-operation-advanced-configuration.md
new file mode 100644 (file)
index 0000000..f20fa6d
--- /dev/null
@@ -0,0 +1,172 @@
+# ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ณ ๊ธ‰ ๊ตฌ์„ฑ { #path-operation-advanced-configuration }
+
+## OpenAPI operationId { #openapi-operationid }
+
+/// warning | ๊ฒฝ๊ณ 
+
+OpenAPI โ€œ์ „๋ฌธ๊ฐ€โ€๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ์•„๋งˆ ์ด ๋‚ด์šฉ์€ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
+
+๋งค๊ฐœ๋ณ€์ˆ˜ `operation_id`๋ฅผ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์‚ฌ์šฉํ•  OpenAPI `operationId`๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ ์ž‘์—…๋งˆ๋‹ค ๊ณ ์œ ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
+
+### *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ์ด๋ฆ„์„ operationId๋กœ ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-path-operation-function-name-as-the-operationid }
+
+API์˜ ํ•จ์ˆ˜ ์ด๋ฆ„์„ `operationId`๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋ชจ๋“  API๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ `APIRoute.name`์„ ์‚ฌ์šฉํ•ด ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ `operation_id`๋ฅผ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ชจ๋“  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
+
+/// tip | ํŒ
+
+`app.openapi()`๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด, ๊ทธ ์ „์— `operationId`๋“ค์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// warning | ๊ฒฝ๊ณ 
+
+์ด๋ ‡๊ฒŒ ํ•  ๊ฒฝ์šฐ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ์ด๋ฆ„์ด ๊ณ ์œ ํ•˜๋„๋ก ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+์„œ๋กœ ๋‹ค๋ฅธ ๋ชจ๋“ˆ(ํŒŒ์ด์ฌ ํŒŒ์ผ)์— ์žˆ์–ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
+
+///
+
+## OpenAPI์—์„œ ์ œ์™ธํ•˜๊ธฐ { #exclude-from-openapi }
+
+์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ(๋”ฐ๋ผ์„œ ์ž๋™ ๋ฌธ์„œํ™” ์‹œ์Šคํ…œ)์—์„œ ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ œ์™ธํ•˜๋ ค๋ฉด, `include_in_schema` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `False`๋กœ ์„ค์ •ํ•˜์„ธ์š”:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
+
+## docstring์—์„œ ๊ณ ๊ธ‰ ์„ค๋ช… ๊ฐ€์ ธ์˜ค๊ธฐ { #advanced-description-from-docstring }
+
+OpenAPI์— ์‚ฌ์šฉํ•  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ docstring ์ค„ ์ˆ˜๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`\f`(์ด์Šค์ผ€์ดํ”„๋œ "form feed" ๋ฌธ์ž)๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด **FastAPI**๋Š” ์ด ์ง€์ ์—์„œ OpenAPI์— ์‚ฌ์šฉํ•  ์ถœ๋ ฅ ๋‚ด์šฉ์„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.
+
+๋ฌธ์„œ์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š์ง€๋งŒ, Sphinx ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ๋Š” ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
+
+## ์ถ”๊ฐ€ ์‘๋‹ต { #additional-responses }
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด `response_model`๊ณผ `status_code`๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ๋ณด์…จ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ๊ธฐ๋ณธ ์‘๋‹ต์— ๋Œ€ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๋ชจ๋ธ, ์ƒํƒœ ์ฝ”๋“œ ๋“ฑ๊ณผ ํ•จ๊ป˜ ์ถ”๊ฐ€ ์‘๋‹ต๋„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด์— ๋Œ€ํ•œ ๋ฌธ์„œ์˜ ์ „์ฒด ์žฅ์ด ์žˆ์œผ๋‹ˆ, [OpenAPI์˜ ์ถ”๊ฐ€ ์‘๋‹ต](additional-responses.md){.internal-link target=_blank}์—์„œ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## OpenAPI Extra { #openapi-extra }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์„ ์–ธํ•˜๋ฉด, **FastAPI**๋Š” OpenAPI ์Šคํ‚ค๋งˆ์— ํฌํ•จ๋  ํ•ด๋‹น *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ๊ด€๋ จ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+/// 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>๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
+
+///
+
+์—ฌ๊ธฐ์—๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ž๋™ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+`tags`, `parameters`, `requestBody`, `responses` ๋“ฑ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ „์šฉ OpenAPI ์Šคํ‚ค๋งˆ๋Š” ๋ณดํ†ต **FastAPI**๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์ง€๋งŒ, ํ™•์žฅํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ด๋Š” ์ €์ˆ˜์ค€ ํ™•์žฅ ์ง€์ ์ž…๋‹ˆ๋‹ค.
+
+์ถ”๊ฐ€ ์‘๋‹ต๋งŒ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค๋ฉด, ๋” ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์€ [OpenAPI์˜ ์ถ”๊ฐ€ ์‘๋‹ต](additional-responses.md){.internal-link target=_blank}์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
+
+`openapi_extra` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### OpenAPI ํ™•์žฅ { #openapi-extensions }
+
+์˜ˆ๋ฅผ ๋“ค์–ด `openapi_extra`๋Š” [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
+
+์ž๋™ API ๋ฌธ์„œ๋ฅผ ์—ด๋ฉด, ํ•ด๋‹น ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ํ•˜๋‹จ์— ํ™•์žฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+
+<img src="/img/tutorial/path-operation-advanced-configuration/image01.png">
+
+๋˜ํ•œ API์˜ `/openapi.json`์—์„œ ๊ฒฐ๊ณผ OpenAPI๋ฅผ ๋ณด๋ฉด, ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ์ผ๋ถ€๋กœ ํ™•์žฅ์ด ํฌํ•จ๋œ ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```JSON hl_lines="22"
+{
+    "openapi": "3.1.0",
+    "info": {
+        "title": "FastAPI",
+        "version": "0.1.0"
+    },
+    "paths": {
+        "/items/": {
+            "get": {
+                "summary": "Read Items",
+                "operationId": "read_items_items__get",
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {
+                            "application/json": {
+                                "schema": {}
+                            }
+                        }
+                    }
+                },
+                "x-aperture-labs-portal": "blue"
+            }
+        }
+    }
+}
+```
+
+### ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์Šคํ‚ค๋งˆ { #custom-openapi-path-operation-schema }
+
+`openapi_extra`์˜ ๋”•์…”๋„ˆ๋ฆฌ๋Š” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ์™€ ๊นŠ๊ฒŒ ๋ณ‘ํ•ฉ๋ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์ž๋™ ์ƒ์„ฑ๋œ ์Šคํ‚ค๋งˆ์— ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด Pydantic๊ณผ ํ•จ๊ป˜ FastAPI์˜ ์ž๋™ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ž์ฒด ์ฝ”๋“œ๋กœ ์š”์ฒญ์„ ์ฝ๊ณ  ๊ฒ€์ฆํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, OpenAPI ์Šคํ‚ค๋งˆ์—๋Š” ์—ฌ์ „ํžˆ ๊ทธ ์š”์ฒญ์„ ์ •์˜ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿด ๋•Œ `openapi_extra`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” ์–ด๋–ค Pydantic ๋ชจ๋ธ๋„ ์„ ์–ธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์š”์ฒญ ๋ฐ”๋””๋Š” JSON์œผ๋กœ <abbr title="converted from some plain format, like bytes, into Python objects - bytes ๊ฐ™์€ ์ผ๋ฐ˜ ํ˜•์‹์—์„œ Python ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜">parsed</abbr>๋˜์ง€๋„ ์•Š๊ณ , `bytes`๋กœ ์ง์ ‘ ์ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜ `magic_data_reader()`๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ์ด๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์š”์ฒญ ๋ฐ”๋””์— ๋Œ€ํ•ด ๊ธฐ๋Œ€ํ•˜๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI ์ฝ˜ํ…์ธ  ํƒ€์ž… { #custom-openapi-content-type }
+
+๊ฐ™์€ ํŠธ๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด, Pydantic ๋ชจ๋ธ์„ ์ด์šฉํ•ด JSON Schema๋ฅผ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์˜ ์‚ฌ์šฉ์ž ์ •์˜ OpenAPI ์Šคํ‚ค๋งˆ ์„น์…˜์— ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์š”์ฒญ์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด JSON์ด ์•„๋‹ˆ๋”๋ผ๋„ ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” Pydantic ๋ชจ๋ธ์—์„œ JSON Schema๋ฅผ ์ถ”์ถœํ•˜๋Š” FastAPI์˜ ํ†ตํ•ฉ ๊ธฐ๋Šฅ๋„, JSON์— ๋Œ€ํ•œ ์ž๋™ ๊ฒ€์ฆ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์š”์ฒญ ์ฝ˜ํ…์ธ  ํƒ€์ž…์„ JSON์ด ์•„๋‹ˆ๋ผ YAML๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
+
+๊ทธ๋Ÿผ์—๋„ ๊ธฐ๋ณธ ํ†ตํ•ฉ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„, YAML๋กœ ๋ฐ›๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ JSON Schema๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Pydantic ๋ชจ๋ธ์„ ์—ฌ์ „ํžˆ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ์š”์ฒญ์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ณ , ๋ฐ”๋””๋ฅผ `bytes`๋กœ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” FastAPI๊ฐ€ ์š”์ฒญ ํŽ˜์ด๋กœ๋“œ๋ฅผ JSON์œผ๋กœ ํŒŒ์‹ฑํ•˜๋ ค๊ณ  ์‹œ๋„์กฐ์ฐจ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์—์„œ YAML ์ฝ˜ํ…์ธ ๋ฅผ ์ง์ ‘ ํŒŒ์‹ฑํ•œ ๋’ค, ๋‹ค์‹œ ๊ฐ™์€ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด YAML ์ฝ˜ํ…์ธ ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
+
+/// tip | ํŒ
+
+์—ฌ๊ธฐ์„œ๋Š” ๊ฐ™์€ Pydantic ๋ชจ๋ธ์„ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
diff --git a/docs/ko/docs/advanced/security/http-basic-auth.md b/docs/ko/docs/advanced/security/http-basic-auth.md
new file mode 100644 (file)
index 0000000..611aad7
--- /dev/null
@@ -0,0 +1,107 @@
+# HTTP Basic Auth { #http-basic-auth }
+
+๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ์—๋Š” HTTP Basic Auth๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+HTTP Basic Auth์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋“ค์–ด ์žˆ๋Š” ํ—ค๋”๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๋ฉด HTTP 401 "Unauthorized" ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๊ฐ’์ด `Basic`์ด๊ณ  ์„ ํƒ์ ์œผ๋กœ `realm` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” `WWW-Authenticate` ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ํ†ตํ•ฉ ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ‘œ์‹œํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
+
+๊ทธ๋‹ค์Œ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด๋‹น ๊ฐ’์„ ํ—ค๋”์— ๋‹ด์•„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
+
+## ๊ฐ„๋‹จํ•œ HTTP Basic Auth { #simple-http-basic-auth }
+
+* `HTTPBasic`๊ณผ `HTTPBasicCredentials`๋ฅผ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค.
+* `HTTPBasic`์„ ์‚ฌ์šฉํ•ด "`security` scheme"์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+* *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ dependency๋กœ ํ•ด๋‹น `security`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+* `HTTPBasicCredentials` ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:
+    * ์ „์†ก๋œ `username`๊ณผ `password`๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
+
+์ฒ˜์Œ์œผ๋กœ URL์„ ์—ด์–ด๋ณด๋ฉด(๋˜๋Š” ๋ฌธ์„œ์—์„œ "Execute" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด) ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฌผ์–ด๋ด…๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/security/image12.png">
+
+## ์‚ฌ์šฉ์ž๋ช… ํ™•์ธํ•˜๊ธฐ { #check-the-username }
+
+๋” ์™„์ „ํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
+
+dependency๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜์„ธ์š”.
+
+์ด๋ฅผ ์œ„ํ•ด Python ํ‘œ์ค€ ๋ชจ๋“ˆ <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a>๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
+
+`secrets.compare_digest()`๋Š” `bytes` ๋˜๋Š” ASCII ๋ฌธ์ž(์˜์–ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž)๋งŒ ํฌํ•จํ•œ `str`์„ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, `Sebastiรกn`์˜ `รก` ๊ฐ™์€ ๋ฌธ์ž๊ฐ€ ์žˆ์œผ๋ฉด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € `username`๊ณผ `password`๋ฅผ UTF-8๋กœ ์ธ์ฝ”๋”ฉํ•ด์„œ `bytes`๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๋‹ค์Œ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•ด `credentials.username`์ด `"stanleyjobson"`์ด๊ณ  `credentials.password`๊ฐ€ `"swordfish"`์ธ์ง€ ํ™•์‹คํžˆ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
+
+์ด๋Š” ๋‹ค์Œ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค:
+
+```Python
+if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
+    # Return some error
+    ...
+```
+
+ํ•˜์ง€๋งŒ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด "timing attacks"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ํ•œ ์œ ํ˜•์˜ ๊ณต๊ฒฉ์— ๋Œ€ํ•ด ์•ˆ์ „ํ•ด์ง‘๋‹ˆ๋‹ค.
+
+### Timing Attacks { #timing-attacks }
+
+๊ทธ๋ ‡๋‹ค๋ฉด "timing attack"์ด๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?
+
+๊ณต๊ฒฉ์ž๋“ค์ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ถ”์ธกํ•˜๋ ค๊ณ  ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋ช… `johndoe`, ๋น„๋ฐ€๋ฒˆํ˜ธ `love123`์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฌ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Python ์ฝ”๋“œ๋Š” ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+```Python
+if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
+    ...
+```
+
+ํ•˜์ง€๋งŒ Python์ด `johndoe`์˜ ์ฒซ ๊ธ€์ž `j`๋ฅผ `stanleyjobson`์˜ ์ฒซ ๊ธ€์ž `s`์™€ ๋น„๊ตํ•˜๋Š” ์ˆœ๊ฐ„, ๋‘ ๋ฌธ์ž์—ด์ด ๊ฐ™์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์ด๋ฏธ ์•Œ๊ฒŒ ๋˜์–ด `False`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” โ€œ๋‚˜๋จธ์ง€ ๊ธ€์ž๋“ค์„ ๋น„๊ตํ•˜๋А๋ผ ๊ณ„์‚ฐ์„ ๋” ๋‚ญ๋น„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹คโ€๊ณ  ํŒ๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ "Incorrect username or password"๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ๋ฐ ๊ณต๊ฒฉ์ž๋“ค์ด ์‚ฌ์šฉ์ž๋ช…์„ `stanleyjobsox`, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ `love123`์œผ๋กœ ๋‹ค์‹œ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฌ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค:
+
+```Python
+if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
+    ...
+```
+
+Python์€ ๋‘ ๋ฌธ์ž์—ด์ด ๊ฐ™์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆฌ๊ธฐ ์ „๊นŒ์ง€ `stanleyjobsox`์™€ `stanleyjobson` ์–‘์ชฝ์˜ `stanleyjobso` ์ „์ฒด๋ฅผ ๋น„๊ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ "Incorrect username or password"๋ผ๊ณ  ์‘๋‹ตํ•˜๊ธฐ๊นŒ์ง€ ์ถ”๊ฐ€๋กœ ๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ๊ฐ€ ๋” ๊ฑธ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+#### ์‘๋‹ต ์‹œ๊ฐ„์€ ๊ณต๊ฒฉ์ž์—๊ฒŒ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค { #the-time-to-answer-helps-the-attackers }
+
+์ด ์‹œ์ ์—์„œ ์„œ๋ฒ„๊ฐ€ "Incorrect username or password" ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๋ฐ ๋ช‡ ๋งˆ์ดํฌ๋กœ์ดˆ ๋” ๊ฑธ๋ ธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฑ„๋ฉด, ๊ณต๊ฒฉ์ž๋“ค์€ _๋ฌด์–ธ๊ฐ€_ ๋งž์•˜๋‹ค๋Š” ๊ฒƒ(์ดˆ๊ธฐ ๋ช‡ ๊ธ€์ž๊ฐ€ ๋งž์•˜๋‹ค๋Š” ๊ฒƒ)์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  `johndoe`๋ณด๋‹ค๋Š” `stanleyjobsox`์— ๋” ๊ฐ€๊นŒ์šด ๊ฐ’์„ ์‹œ๋„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+#### "์ „๋ฌธ์ ์ธ" ๊ณต๊ฒฉ { #a-professional-attack }
+
+๋ฌผ๋ก  ๊ณต๊ฒฉ์ž๋“ค์€ ์ด๋Ÿฐ ์ž‘์—…์„ ์†์œผ๋กœ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณดํ†ต ์ดˆ๋‹น ์ˆ˜์ฒœ~์ˆ˜๋ฐฑ๋งŒ ๋ฒˆ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ๊ฒƒ์ด๊ณ , ํ•œ ๋ฒˆ์— ์ •๋‹ต ๊ธ€์ž ํ•˜๋‚˜์”ฉ ์ถ”๊ฐ€๋กœ ์–ป์–ด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ช‡ ๋ถ„ ๋˜๋Š” ๋ช‡ ์‹œ๊ฐ„ ๋งŒ์—, ์‘๋‹ต์— ๊ฑธ๋ฆฐ ์‹œ๊ฐ„๋งŒ์„ ์ด์šฉํ•ด(์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ โ€œ๋„์›€โ€์„ ๋ฐ›์•„) ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ถ”์ธกํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+#### `secrets.compare_digest()`๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ { #fix-it-with-secrets-compare-digest }
+
+ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์š”์•ฝํ•˜๋ฉด, `stanleyjobsox`์™€ `stanleyjobson`์„ ๋น„๊ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ `johndoe`์™€ `stanleyjobson`์„ ๋น„๊ตํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„๊ณผ ๊ฐ™์•„์ง‘๋‹ˆ๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ `secrets.compare_digest()`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ด๋Ÿฌํ•œ ๋ฒ”์œ„์˜ ๋ณด์•ˆ ๊ณต๊ฒฉ ์ „๋ฐ˜์— ๋Œ€ํ•ด ์•ˆ์ „ํ•ด์ง‘๋‹ˆ๋‹ค.
+
+### ์˜ค๋ฅ˜ ๋ฐ˜ํ™˜ํ•˜๊ธฐ { #return-the-error }
+
+์ž๊ฒฉ ์ฆ๋ช…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จ๋˜๋ฉด, ์ƒํƒœ ์ฝ”๋“œ 401(์ž๊ฒฉ ์ฆ๋ช…์ด ์ œ๊ณต๋˜์ง€ ์•Š์•˜์„ ๋•Œ์™€ ๋™์ผ)์„ ์‚ฌ์šฉํ•˜๋Š” `HTTPException`์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋กœ๊ทธ์ธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋‹ค์‹œ ํ‘œ์‹œํ•˜๋„๋ก `WWW-Authenticate` ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”:
+
+{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
diff --git a/docs/ko/docs/advanced/security/index.md b/docs/ko/docs/advanced/security/index.md
new file mode 100644 (file)
index 0000000..4c7abfa
--- /dev/null
@@ -0,0 +1,19 @@
+# ๊ณ ๊ธ‰ ๋ณด์•ˆ { #advanced-security }
+
+## ์ถ”๊ฐ€ ๊ธฐ๋Šฅ { #additional-features }
+
+[ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ: ๋ณด์•ˆ](../../tutorial/security/index.md){.internal-link target=_blank}์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ ์™ธ์—๋„, ๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+๋‹ค์Œ ์„น์…˜๋“ค์€ **๋ฐ˜๋“œ์‹œ "๊ณ ๊ธ‰"์ด๋ผ๊ณ  ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค**.
+
+๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ, ๊ทธ์ค‘ ํ•˜๋‚˜์— ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## ๋จผ์ € ํŠœํ† ๋ฆฌ์–ผ ์ฝ๊ธฐ { #read-the-tutorial-first }
+
+๋‹ค์Œ ์„น์…˜์€ ์ฃผ์š” [ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ: ๋ณด์•ˆ](../../tutorial/security/index.md){.internal-link target=_blank}์„ ์ด๋ฏธ ์ฝ์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+๋ชจ๋‘ ๋™์ผํ•œ ๊ฐœ๋…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/advanced/security/oauth2-scopes.md b/docs/ko/docs/advanced/security/oauth2-scopes.md
new file mode 100644 (file)
index 0000000..0f90f92
--- /dev/null
@@ -0,0 +1,274 @@
+# OAuth2 ์Šค์ฝ”ํ”„ { #oauth2-scopes }
+
+**FastAPI**์—์„œ OAuth2 ์Šค์ฝ”ํ”„๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ํ†ตํ•ด OAuth2 ํ‘œ์ค€์„ ๋”ฐ๋ฅด๋Š” ๋” ์„ธ๋ฐ€ํ•œ ๊ถŒํ•œ ์‹œ์Šคํ…œ์„ OpenAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋ฐ API ๋ฌธ์„œ)์— ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” OAuth2๋Š” Facebook, Google, GitHub, Microsoft, X(Twitter) ๋“ฑ ๋งŽ์€ ๋Œ€ํ˜• ์ธ์ฆ ์ œ๊ณต์ž๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ์ด๋“ค์€ ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํŠน์ • ๊ถŒํ•œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+Facebook, Google, GitHub, Microsoft, X(Twitter)๋กœ โ€œ๋กœ๊ทธ์ธโ€ํ•  ๋•Œ๋งˆ๋‹ค, ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ์„น์…˜์—์„œ๋Š” **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋™์ผํ•œ โ€œ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2โ€๋กœ ์ธ์ฆ(Authentication)๊ณผ ์ธ๊ฐ€(Authorization)๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
+
+/// warning | ๊ฒฝ๊ณ 
+
+์ด ์„น์…˜์€ ๋‹ค์†Œ ๊ณ ๊ธ‰ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+OAuth2 ์Šค์ฝ”ํ”„๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋Š” ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋Š” (OpenAPI์™€ ํ•จ๊ป˜) API ๋ฐ API ๋ฌธ์„œ์— ๊น”๋”ํ•˜๊ฒŒ ํ†ตํ•ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ํ•ด๋‹น ์Šค์ฝ”ํ”„(๋˜๋Š” ๊ทธ ๋ฐ–์˜ ์–ด๋–ค ๋ณด์•ˆ/์ธ๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ์ด๋“ )๋Š” ์ฝ”๋“œ์—์„œ ํ•„์š”์— ๋งž๊ฒŒ ์ง์ ‘ ๊ฐ•์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+๋งŽ์€ ๊ฒฝ์šฐ ์Šค์ฝ”ํ”„๊ฐ€ ์žˆ๋Š” OAuth2๋Š” ๊ณผํ•œ ์„ ํƒ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ํ•„์š”ํ•˜๋‹ค๊ณ  ์•Œ๊ณ  ์žˆ๊ฑฐ๋‚˜ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด ๊ณ„์† ์ฝ์–ด๋ณด์„ธ์š”.
+
+///
+
+## OAuth2 ์Šค์ฝ”ํ”„์™€ OpenAPI { #oauth2-scopes-and-openapi }
+
+OAuth2 ์‚ฌ์–‘์€ โ€œ์Šค์ฝ”ํ”„(scopes)โ€๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด ๋ชฉ๋ก์œผ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ฐ ๋ฌธ์ž์—ด์˜ ๋‚ด์šฉ์€ ์–ด๋–ค ํ˜•์‹์ด๋“  ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ณต๋ฐฑ์„ ํฌํ•จํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
+
+์ด ์Šค์ฝ”ํ”„๋“ค์€ โ€œ๊ถŒํ•œโ€์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
+
+OpenAPI(์˜ˆ: API ๋ฌธ์„œ)์—์„œ๋Š” โ€œsecurity schemesโ€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด security scheme ์ค‘ ํ•˜๋‚˜๊ฐ€ OAuth2๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์Šค์ฝ”ํ”„๋„ ์„ ์–ธํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ โ€œ์Šค์ฝ”ํ”„โ€๋Š” (๊ณต๋ฐฑ ์—†๋Š”) ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
+
+๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํŠน์ • ๋ณด์•ˆ ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+* `users:read` ๋˜๋Š” `users:write` ๋Š” ํ”ํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
+* `instagram_basic` ๋Š” Facebook/Instagram์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+* `https://www.googleapis.com/auth/drive` ๋Š” Google์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+OAuth2์—์„œ โ€œ์Šค์ฝ”ํ”„โ€๋Š” ํ•„์š”ํ•œ ํŠน์ • ๊ถŒํ•œ์„ ์„ ์–ธํ•˜๋Š” ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
+
+`:` ๊ฐ™์€ ๋‹ค๋ฅธ ๋ฌธ์ž๊ฐ€ ์žˆ๊ฑฐ๋‚˜ URL์ด์–ด๋„ ์ƒ๊ด€์—†์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ์„ธ๋ถ€์‚ฌํ•ญ์€ ๊ตฌํ˜„์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
+
+OAuth2 ์ž…์žฅ์—์„œ๋Š” ๊ทธ์ € ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
+
+///
+
+## ์ „์ฒด ๊ฐœ์š” { #global-view }
+
+๋จผ์ €, ๋ฉ”์ธ **ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ**์˜ [๋น„๋ฐ€๋ฒˆํ˜ธ(๋ฐ ํ•ด์‹ฑ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” OAuth2, JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” Bearer](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ์˜ˆ์ œ์—์„œ ์–ด๋–ค ๋ถ€๋ถ„์ด ๋ฐ”๋€Œ๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ OAuth2 ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
+
+์ด์ œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## OAuth2 ๋ณด์•ˆ ์Šคํ‚ด { #oauth2-security-scheme }
+
+์ฒซ ๋ฒˆ์งธ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ด์ œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šค์ฝ”ํ”„ 2๊ฐœ(`me`, `items`)๋กœ OAuth2 ๋ณด์•ˆ ์Šคํ‚ด์„ ์„ ์–ธํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
+
+`scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ฐ ์Šค์ฝ”ํ”„๋ฅผ ํ‚ค๋กœ ํ•˜๊ณ , ์„ค๋ช…์„ ๊ฐ’์œผ๋กœ ํ•˜๋Š” `dict`๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *}
+
+์ด์ œ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋กœ๊ทธ์ธ/์ธ๊ฐ€ํ•  ๋•Œ API ๋ฌธ์„œ์— ์Šค์ฝ”ํ”„๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์Šค์ฝ”ํ”„๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค: `me`์™€ `items`.
+
+์ด๋Š” Facebook, Google, GitHub ๋“ฑ์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๋ฉด์„œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/security/image11.png">
+
+## ์Šค์ฝ”ํ”„๋ฅผ ํฌํ•จํ•œ JWT ํ† ํฐ { #jwt-token-with-scopes }
+
+์ด์ œ ํ† ํฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ˆ˜์ •ํ•ด, ์š”์ฒญ๋œ ์Šค์ฝ”ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
+
+์—ฌ์ „ํžˆ ๋™์ผํ•œ `OAuth2PasswordRequestForm`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์š”์ฒญ์—์„œ ๋ฐ›์€ ๊ฐ ์Šค์ฝ”ํ”„๋ฅผ ๋‹ด๋Š” `scopes` ์†์„ฑ์ด ์žˆ์œผ๋ฉฐ, ํƒ€์ž…์€ `str`์˜ `list`์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  JWT ํ† ํฐ์˜ ์ผ๋ถ€๋กœ ์Šค์ฝ”ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+/// danger | ์œ„ํ—˜
+
+๋‹จ์ˆœํ™”๋ฅผ ์œ„ํ•ด, ์—ฌ๊ธฐ์„œ๋Š” ์š”์ฒญ์œผ๋กœ ๋ฐ›์€ ์Šค์ฝ”ํ”„๋ฅผ ๊ทธ๋Œ€๋กœ ํ† ํฐ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ๋ณด์•ˆ์„ ์œ„ํ•ด, ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์Šค์ฝ”ํ”„๋งŒ(๋˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜ํ•œ ๊ฒƒ๋งŒ) ์ถ”๊ฐ€ํ•˜๋„๋ก ๋ฐ˜๋“œ์‹œ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
+
+## *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ ์˜์กด์„ฑ์—์„œ ์Šค์ฝ”ํ”„ ์„ ์–ธํ•˜๊ธฐ { #declare-scopes-in-path-operations-and-dependencies }
+
+์ด์ œ `/users/me/items/`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ์Šค์ฝ”ํ”„ `items`๋ฅผ ์š”๊ตฌํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์œ„ํ•ด `fastapi`์—์„œ `Security`๋ฅผ importํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+`Security`๋Š” (`Depends`์ฒ˜๋Ÿผ) ์˜์กด์„ฑ์„ ์„ ์–ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, `Security`๋Š” ์Šค์ฝ”ํ”„(๋ฌธ์ž์—ด) ๋ชฉ๋ก์„ ๋ฐ›๋Š” `scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ, ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋ฅผ `Security`์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค(`Depends`๋กœ ํ•  ๋•Œ์™€ ๊ฐ™์€ ๋ฐฉ์‹).
+
+ํ•˜์ง€๋งŒ ์Šค์ฝ”ํ”„ `list`๋„ ํ•จ๊ป˜ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์Šค์ฝ”ํ”„ ํ•˜๋‚˜๋งŒ: `items`(๋” ๋งŽ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+๋˜ํ•œ ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋Š” `Depends`๋ฟ ์•„๋‹ˆ๋ผ `Security`๋กœ๋„ ํ•˜์œ„ ์˜์กด์„ฑ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์ฒด ํ•˜์œ„ ์˜์กด์„ฑ ํ•จ์ˆ˜(`get_current_user`)์™€ ์ถ”๊ฐ€ ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ์—๋Š” ์Šค์ฝ”ํ”„ `me`๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค(์—ฌ๋Ÿฌ ์Šค์ฝ”ํ”„๋ฅผ ์š”๊ตฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+/// note | ์ฐธ๊ณ 
+
+๋ฐ˜๋“œ์‹œ ์„œ๋กœ ๋‹ค๋ฅธ ๊ณณ์— ์„œ๋กœ ๋‹ค๋ฅธ ์Šค์ฝ”ํ”„๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์„œ๋Š” **FastAPI**๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ ˆ๋ฒจ์—์„œ ์„ ์–ธ๋œ ์Šค์ฝ”ํ”„๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ด๋ ‡๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
+
+/// info | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+`Security`๋Š” ์‹ค์ œ๋กœ `Depends`์˜ ์„œ๋ธŒํด๋ž˜์Šค์ด๋ฉฐ, ๋‚˜์ค‘์— ๋ณด๊ฒŒ ๋  ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ํ•˜๋‚˜๋งŒ ๋” ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `Depends` ๋Œ€์‹  `Security`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, **FastAPI**๋Š” ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, OpenAPI๋กœ API๋ฅผ ๋ฌธ์„œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `fastapi`์—์„œ `Query`, `Path`, `Depends`, `Security` ๋“ฑ์„ importํ•  ๋•Œ, ์ด๊ฒƒ๋“ค์€ ์‹ค์ œ๋กœ ํŠน์ˆ˜ํ•œ ํด๋ž˜์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
+
+///
+
+## `SecurityScopes` ์‚ฌ์šฉํ•˜๊ธฐ { #use-securityscopes }
+
+์ด์ œ ์˜์กด์„ฑ `get_current_user`๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Š” ์œ„์˜ ์˜์กด์„ฑ๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์—์„œ ์•ž์„œ ๋งŒ๋“  ๋™์ผํ•œ OAuth2 ์Šคํ‚ด์„ ์˜์กด์„ฑ์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค: `oauth2_scheme`.
+
+์ด ์˜์กด์„ฑ ํ•จ์ˆ˜ ์ž์ฒด์—๋Š” ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—, `oauth2_scheme`์™€ ํ•จ๊ป˜ `Depends`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ๋Š” `Security`๋ฅผ ์“ธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ `fastapi.security`์—์„œ importํ•œ `SecurityScopes` ํƒ€์ž…์˜ ํŠน๋ณ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+
+์ด `SecurityScopes` ํด๋ž˜์Šค๋Š” `Request`์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค(`Request`๋Š” ์š”์ฒญ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์–ป๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค).
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *}
+
+## `scopes` ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-scopes }
+
+๋งค๊ฐœ๋ณ€์ˆ˜ `security_scopes`์˜ ํƒ€์ž…์€ `SecurityScopes`์ž…๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” `scopes` ์†์„ฑ์ด ์žˆ์œผ๋ฉฐ, ์ž๊ธฐ ์ž์‹ ๊ณผ ์ด ํ•จ์ˆ˜๋ฅผ ํ•˜์œ„ ์˜์กด์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์˜์กด์„ฑ์ด ์š”๊ตฌํ•˜๋Š” ์Šค์ฝ”ํ”„ ์ „์ฒด๋ฅผ ๋‹ด์€ `list`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  โ€œdependantsโ€... ๋‹ค์†Œ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋Š”๋ฐ, ์•„๋ž˜์—์„œ ๋‹ค์‹œ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
+
+`security_scopes` ๊ฐ์ฒด(`SecurityScopes` ํด๋ž˜์Šค)์—๋Š” ๋˜ํ•œ `scope_str` ์†์„ฑ์ด ์žˆ๋Š”๋ฐ, ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋‹จ์ผ ๋ฌธ์ž์—ด๋กœ ์Šค์ฝ”ํ”„๋“ค์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(์ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค).
+
+๋‚˜์ค‘์— ์—ฌ๋Ÿฌ ์ง€์ ์—์„œ ์žฌ์‚ฌ์šฉ(`raise`)ํ•  ์ˆ˜ ์žˆ๋Š” `HTTPException`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์™ธ์—๋Š” ํ•„์š”ํ•œ ์Šค์ฝ”ํ”„(์žˆ๋‹ค๋ฉด)๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด(`scope_str`)๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์Šค์ฝ”ํ”„ ๋ฌธ์ž์—ด์„ `WWW-Authenticate` ํ—ค๋”์— ๋„ฃ์Šต๋‹ˆ๋‹ค(์ด๋Š” ์‚ฌ์–‘์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค).
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *}
+
+## `username`๊ณผ ๋ฐ์ดํ„ฐ ํ˜•ํƒœ ๊ฒ€์ฆํ•˜๊ธฐ { #verify-the-username-and-data-shape }
+
+`username`์„ ์–ป์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์Šค์ฝ”ํ”„๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๋‹ค์Œ Pydantic ๋ชจ๋ธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค(`ValidationError` ์˜ˆ์™ธ๋ฅผ ์žก์Šต๋‹ˆ๋‹ค). JWT ํ† ํฐ์„ ์ฝ๊ฑฐ๋‚˜ Pydantic์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฉด, ์•ž์—์„œ ๋งŒ๋“  `HTTPException`์„ raiseํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์œ„ํ•ด Pydantic ๋ชจ๋ธ `TokenData`์— ์ƒˆ ์†์„ฑ `scopes`๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
+
+Pydantic์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด ์Šค์ฝ”ํ”„๊ฐ€ ์ •ํ™•ํžˆ `str`์˜ `list`์ด๊ณ  `username`์ด `str`์ธ์ง€ ๋“ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `dict`๋‚˜ ๋‹ค๋ฅธ ํ˜•ํƒœ๋ผ๋ฉด, ๋‚˜์ค‘์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ด๋А ์‹œ์ ์— ๊นจ์ง€๋ฉด์„œ ๋ณด์•ˆ ์œ„ํ—˜์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ํ•ด๋‹น username์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์—†๋‹ค๋ฉด ์•ž์—์„œ ๋งŒ๋“  ๋™์ผํ•œ ์˜ˆ์™ธ๋ฅผ raiseํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *}
+
+## `scopes` ๊ฒ€์ฆํ•˜๊ธฐ { #verify-the-scopes }
+
+์ด์ œ ์ด ์˜์กด์„ฑ๊ณผ ๋ชจ๋“  dependant( *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ํฌํ•จ)๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๋ชจ๋“  ์Šค์ฝ”ํ”„๊ฐ€, ๋ฐ›์€ ํ† ํฐ์˜ ์Šค์ฝ”ํ”„์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด `HTTPException`์„ raiseํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์œ„ํ•ด, ๋ชจ๋“  ์Šค์ฝ”ํ”„๋ฅผ `str`๋กœ ๋‹ด๊ณ  ์žˆ๋Š” `security_scopes.scopes`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *}
+
+## ์˜์กด์„ฑ ํŠธ๋ฆฌ์™€ ์Šค์ฝ”ํ”„ { #dependency-tree-and-scopes }
+
+์ด ์˜์กด์„ฑ ํŠธ๋ฆฌ์™€ ์Šค์ฝ”ํ”„๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+`get_current_active_user` ์˜์กด์„ฑ์€ `get_current_user`๋ฅผ ํ•˜์œ„ ์˜์กด์„ฑ์œผ๋กœ ๊ฐ€์ง€๋ฏ€๋กœ, `get_current_active_user`์—์„œ ์„ ์–ธ๋œ ์Šค์ฝ”ํ”„ `"me"`๋Š” `get_current_user`์— ์ „๋‹ฌ๋˜๋Š” `security_scopes.scopes`์˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ ๋ชฉ๋ก์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ž์ฒด๋„ ์Šค์ฝ”ํ”„ `"items"`๋ฅผ ์„ ์–ธํ•˜๋ฏ€๋กœ, ์ด๊ฒƒ ๋˜ํ•œ `get_current_user`์— ์ „๋‹ฌ๋˜๋Š” `security_scopes.scopes` ๋ชฉ๋ก์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+์˜์กด์„ฑ๊ณผ ์Šค์ฝ”ํ”„์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_own_items`๋Š”:
+    * ์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ `["items"]`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค:
+    * `get_current_active_user`:
+        * ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_active_user`๋Š”:
+            * ์˜์กด์„ฑ๊ณผ ํ•จ๊ป˜ ์š”๊ตฌ ์Šค์ฝ”ํ”„ `["me"]`๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค:
+            * `get_current_user`:
+                * ์˜์กด์„ฑ ํ•จ์ˆ˜ `get_current_user`๋Š”:
+                    * ์ž์ฒด์ ์œผ๋กœ๋Š” ์š”๊ตฌ ์Šค์ฝ”ํ”„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
+                    * `oauth2_scheme`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜์กด์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+                    * `SecurityScopes` ํƒ€์ž…์˜ `security_scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:
+                        * ์ด `security_scopes` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์œ„์—์„œ ์„ ์–ธ๋œ ๋ชจ๋“  ์Šค์ฝ”ํ”„๋ฅผ ๋‹ด์€ `list`์ธ `scopes` ์†์„ฑ์„ ๊ฐ€์ง€๋ฏ€๋กœ:
+                            * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_own_items`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `["me", "items"]`๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
+                            * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_users_me`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `["me"]`๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ด๋Š” ์˜์กด์„ฑ `get_current_active_user`์—์„œ ์„ ์–ธ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+                            * *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* `read_system_status`์˜ ๊ฒฝ์šฐ `security_scopes.scopes`์—๋Š” `[]`(์—†์Œ)๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. `scopes`๊ฐ€ ์žˆ๋Š” `Security`๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ณ , ๊ทธ ์˜์กด์„ฑ์ธ `get_current_user`๋„ `scopes`๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ โ€œ๋งˆ๋ฒ• ๊ฐ™์€โ€ ์ ์€ `get_current_user`๊ฐ€ ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜๋Š” `scopes` ๋ชฉ๋ก์ด ๋‹ฌ๋ผ์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” ํŠน์ • *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•œ ์˜์กด์„ฑ ํŠธ๋ฆฌ์—์„œ, ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ ๊ฐ ์˜์กด์„ฑ์— ์„ ์–ธ๋œ `scopes`์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
+
+///
+
+## `SecurityScopes`์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์„ค๋ช… { #more-details-about-securityscopes }
+
+`SecurityScopes`๋Š” ์–ด๋А ์ง€์ ์—์„œ๋“ , ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, โ€œ๋ฃจํŠธโ€ ์˜์กด์„ฑ์—๋งŒ ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
+
+`SecurityScopes`๋Š” **ํ•ด๋‹น ํŠน์ •** *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์™€ **ํ•ด๋‹น ํŠน์ •** ์˜์กด์„ฑ ํŠธ๋ฆฌ์— ๋Œ€ํ•ด, ํ˜„์žฌ `Security` ์˜์กด์„ฑ๊ณผ ๋ชจ๋“  dependant์— ์„ ์–ธ๋œ ๋ณด์•ˆ ์Šค์ฝ”ํ”„๋ฅผ ํ•ญ์ƒ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`SecurityScopes`์—๋Š” dependant๊ฐ€ ์„ ์–ธํ•œ ๋ชจ๋“  ์Šค์ฝ”ํ”„๊ฐ€ ํฌํ•จ๋˜๋ฏ€๋กœ, ์ค‘์•™์˜ ์˜์กด์„ฑ ํ•จ์ˆ˜์—์„œ ํ† ํฐ์ด ํ•„์š”ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•œ ๋‹ค์Œ, ์„œ๋กœ ๋‹ค๋ฅธ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ์Šค์ฝ”ํ”„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋“ค์€ ๊ฐ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋งˆ๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ ๊ฒ€์‚ฌ๋ฉ๋‹ˆ๋‹ค.
+
+## ํ™•์ธํ•˜๊ธฐ { #check-it }
+
+API ๋ฌธ์„œ๋ฅผ ์—ด๋ฉด, ์ธ์ฆํ•˜๊ณ  ์ธ๊ฐ€ํ•  ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+<img src="/img/tutorial/security/image11.png">
+
+์–ด๋–ค ์Šค์ฝ”ํ”„๋„ ์„ ํƒํ•˜์ง€ ์•Š์œผ๋ฉด โ€œ์ธ์ฆโ€์€ ๋˜์ง€๋งŒ, `/users/me/` ๋˜๋Š” `/users/me/items/`์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๊ถŒํ•œ์ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. `/status/`์—๋Š” ์—ฌ์ „ํžˆ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์Šค์ฝ”ํ”„ `me`๋Š” ์„ ํƒํ–ˆ์ง€๋งŒ ์Šค์ฝ”ํ”„ `items`๋Š” ์„ ํƒํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, `/users/me/`์—๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ `/users/me/items/`์—๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ, ์ œ3์ž ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ œ๊ณต๋ฐ›์€ ํ† ํฐ์œผ๋กœ ์ด *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋“ค ์ค‘ ํ•˜๋‚˜์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
+
+## ์ œ3์ž ํ†ตํ•ฉ์— ๋Œ€ํ•ด { #about-third-party-integrations }
+
+์ด ์˜ˆ์ œ์—์„œ๋Š” OAuth2 โ€œpasswordโ€ ํ”Œ๋กœ์šฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ๋ณดํ†ต ์ž์ฒด ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์žˆ๋Š” ์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋กœ๊ทธ์ธํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
+
+์šฐ๋ฆฌ๊ฐ€ ์ด๋ฅผ ํ†ต์ œํ•˜๋ฏ€๋กœ `username`๊ณผ `password`๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์„ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์—ฐ๊ฒฐํ•  OAuth2 ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์ฆ‰, Facebook, Google, GitHub ๋“ฑ๊ณผ ๋™๋“ฑํ•œ ์ธ์ฆ ์ œ๊ณต์ž๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๋ฉด)์„ ๊ตฌ์ถ•ํ•œ๋‹ค๋ฉด, ๋‹ค๋ฅธ ํ”Œ๋กœ์šฐ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ฐ€์žฅ ํ”ํ•œ ๊ฒƒ์€ implicit ํ”Œ๋กœ์šฐ์ž…๋‹ˆ๋‹ค.
+
+๊ฐ€์žฅ ์•ˆ์ „ํ•œ ๊ฒƒ์€ code ํ”Œ๋กœ์šฐ์ด์ง€๋งŒ, ๋” ๋งŽ์€ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•ด ๊ตฌํ˜„์ด ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. ๋ณต์žกํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ์ œ๊ณต์ž๋Š” implicit ํ”Œ๋กœ์šฐ๋ฅผ ๊ถŒ์žฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+/// note | ์ฐธ๊ณ 
+
+์ธ์ฆ ์ œ๊ณต์ž๋งˆ๋‹ค ์ž์‹ ๋“ค์˜ ๋ธŒ๋žœ๋“œ์˜ ์ผ๋ถ€๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด, ๊ฐ ํ”Œ๋กœ์šฐ๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฆ„ ๋ถ™์ด๋Š” ๊ฒฝ์šฐ๊ฐ€ ํ”ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ, ๋™์ผํ•œ OAuth2 ํ‘œ์ค€์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
+
+**FastAPI**๋Š” `fastapi.security.oauth2`์— ์ด๋Ÿฌํ•œ ๋ชจ๋“  OAuth2 ์ธ์ฆ ํ”Œ๋กœ์šฐ๋ฅผ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
+
+## ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ `dependencies`์—์„œ์˜ `Security` { #security-in-decorator-dependencies }
+
+[๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์˜ ์˜์กด์„ฑ](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์˜ `dependencies` ๋งค๊ฐœ๋ณ€์ˆ˜์— `Depends`์˜ `list`๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ๊ฑฐ๊ธฐ์—์„œ `scopes`์™€ ํ•จ๊ป˜ `Security`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/advanced/settings.md b/docs/ko/docs/advanced/settings.md
new file mode 100644 (file)
index 0000000..6fa7c64
--- /dev/null
@@ -0,0 +1,302 @@
+# ์„ค์ •๊ณผ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ { #settings-and-environment-variables }
+
+๋งŽ์€ ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” ์™ธ๋ถ€ ์„ค์ •์ด๋‚˜ ๊ตฌ์„ฑ(์˜ˆ: secret key, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž๊ฒฉ ์ฆ๋ช…, ์ด๋ฉ”์ผ ์„œ๋น„์Šค ์ž๊ฒฉ ์ฆ๋ช… ๋“ฑ)์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Ÿฌํ•œ ์„ค์ • ๋Œ€๋ถ€๋ถ„์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค URL์ฒ˜๋Ÿผ ๋ณ€๋™ ๊ฐ€๋Šฅ(๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Œ)ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ์„ค์ •์€ secret์ฒ˜๋Ÿผ ๋ฏผ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๋•Œ๋ฌธ์— ๋ณดํ†ต ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฝ์–ด๋“ค์ด๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด [ํ™˜๊ฒฝ ๋ณ€์ˆ˜](../environment-variables.md){.internal-link target=_blank}๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+///
+
+## ํƒ€์ž…๊ณผ ๊ฒ€์ฆ { #types-and-validation }
+
+์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์€ Python ์™ธ๋ถ€์— ์žˆ์œผ๋ฉฐ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ ๋ฐ ์‹œ์Šคํ…œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„(๊ทธ๋ฆฌ๊ณ  Linux, Windows, macOS ๊ฐ™์€ ์„œ๋กœ ๋‹ค๋ฅธ ์šด์˜์ฒด์ œ์™€๋„)๊ณผ ํ˜ธํ™˜๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ, ํ…์ŠคํŠธ ๋ฌธ์ž์—ด๋งŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ฆ‰, Python์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ๋ถ€ํ„ฐ ์ฝ์–ด์˜จ ์–ด๋–ค ๊ฐ’์ด๋“  `str`์ด ๋˜๋ฉฐ, ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ์˜ ๋ณ€ํ™˜์ด๋‚˜ ๊ฒ€์ฆ์€ ์ฝ”๋“œ์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+## 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-settings` ์„ค์น˜ํ•˜๊ธฐ { #install-pydantic-settings }
+
+๋จผ์ € [๊ฐ€์ƒ ํ™˜๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, `pydantic-settings` ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ pip install pydantic-settings
+---> 100%
+```
+
+</div>
+
+๋˜๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ `all` extras๋ฅผ ์„ค์น˜ํ•˜๋ฉด ํ•จ๊ป˜ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ pip install "fastapi[all]"
+---> 100%
+```
+
+</div>
+
+### `Settings` ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ { #create-the-settings-object }
+
+Pydantic์—์„œ `BaseSettings`๋ฅผ importํ•˜๊ณ , Pydantic ๋ชจ๋ธ๊ณผ ๋งค์šฐ ๋น„์Šทํ•˜๊ฒŒ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ์„ธ์š”.
+
+Pydantic ๋ชจ๋ธ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜(๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•˜๋‹ค๋ฉด ๊ธฐ๋ณธ๊ฐ’)๊ณผ ํ•จ๊ป˜ ํด๋ž˜์Šค ์†์„ฑ์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+
+๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…, `Field()`๋กœ ์ถ”๊ฐ€ ๊ฒ€์ฆ ๋“ฑ Pydantic ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋™์ผํ•œ ๊ฒ€์ฆ ๊ธฐ๋Šฅ๊ณผ ๋„๊ตฌ๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
+
+/// tip | ํŒ
+
+๋น ๋ฅด๊ฒŒ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐํ•  ์˜ˆ์‹œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ด ์˜ˆ์‹œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ์•„๋ž˜์˜ ๋งˆ์ง€๋ง‰ ์˜ˆ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
+
+///
+
+๊ทธ ๋‹ค์Œ, ํ•ด๋‹น `Settings` ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค(์—ฌ๊ธฐ์„œ๋Š” `settings` ๊ฐ์ฒด)๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Pydantic์ด ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋Œ€๋ฌธ์ž ๋ณ€์ˆ˜ `APP_NAME`๋„ `app_name` ์†์„ฑ์— ๋Œ€ํ•ด ์ฝํž™๋‹ˆ๋‹ค.
+
+์ดํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ `settings` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ ์–ธํ•œ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค(์˜ˆ: `items_per_user`๋Š” `int`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค).
+
+### `settings` ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-settings }
+
+์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ƒˆ `settings` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
+
+### ์„œ๋ฒ„ ์‹คํ–‰ํ•˜๊ธฐ { #run-the-server }
+
+๋‹ค์Œ์œผ๋กœ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๊ตฌ์„ฑ์„ ์ „๋‹ฌํ•˜๋ฉด์„œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์ฒ˜๋Ÿผ `ADMIN_EMAIL`๊ณผ `APP_NAME`์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+/// tip | ํŒ
+
+ํ•˜๋‚˜์˜ ๋ช…๋ น์— ์—ฌ๋Ÿฌ env var๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ณ , ๋ชจ๋‘ ๋ช…๋ น ์•ž์— ๋‘์„ธ์š”.
+
+///
+
+๊ทธ๋Ÿฌ๋ฉด `admin_email` ์„ค์ •์€ `"deadpool@example.com"`์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
+
+`app_name`์€ `"ChimichangApp"`์ด ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  `items_per_user`๋Š” ๊ธฐ๋ณธ๊ฐ’ `50`์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
+
+## ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ์„ค์ • { #settings-in-another-module }
+
+[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ, ์„ค์ •์„ ๋‹ค๋ฅธ ๋ชจ๋“ˆ ํŒŒ์ผ์— ๋„ฃ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `config.py` ํŒŒ์ผ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/app01_py39/config.py *}
+
+๊ทธ๋ฆฌ๊ณ  `main.py` ํŒŒ์ผ์—์„œ ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
+
+/// tip | ํŒ
+
+[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ `__init__.py` ํŒŒ์ผ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ์˜์กด์„ฑ์—์„œ ์„ค์ • ์‚ฌ์šฉํ•˜๊ธฐ { #settings-in-a-dependency }
+
+์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์–ด๋””์„œ๋‚˜ ์‚ฌ์šฉ๋˜๋Š” ์ „์—ญ `settings` ๊ฐ์ฒด๋ฅผ ๋‘๋Š” ๋Œ€์‹ , ์˜์กด์„ฑ์—์„œ ์„ค์ •์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ํŠนํžˆ ํ…Œ์ŠคํŠธ ์ค‘์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์‚ฌ์šฉ์ž ์ •์˜ ์„ค์ •์œผ๋กœ ์˜์กด์„ฑ์„ overrideํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+### config ํŒŒ์ผ { #the-config-file }
+
+์ด์ „ ์˜ˆ์‹œ์—์„œ ์ด์–ด์„œ, `config.py` ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
+
+์ด์ œ๋Š” ๊ธฐ๋ณธ ์ธ์Šคํ„ด์Šค `settings = Settings()`๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.
+
+### ๋ฉ”์ธ ์•ฑ ํŒŒ์ผ { #the-main-app-file }
+
+์ด์ œ ์ƒˆ๋กœ์šด `config.Settings()`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์˜์กด์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
+
+/// tip | ํŒ
+
+`@lru_cache`๋Š” ์กฐ๊ธˆ ๋’ค์— ๋‹ค๋ฃน๋‹ˆ๋‹ค.
+
+์ง€๊ธˆ์€ `get_settings()`๊ฐ€ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋ผ๊ณ  ๊ฐ€์ •ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+๊ทธ ๋‹ค์Œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ ์ด๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์š”๊ตฌํ•˜๊ณ , ํ•„์š”ํ•œ ์–ด๋””์„œ๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
+
+### ์„ค์ •๊ณผ ํ…Œ์ŠคํŠธ { #settings-and-testing }
+
+๊ทธ ๋‹ค์Œ, `get_settings`์— ๋Œ€ํ•œ ์˜์กด์„ฑ override๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ ์ค‘์— ๋‹ค๋ฅธ ์„ค์ • ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
+
+์˜์กด์„ฑ override์—์„œ๋Š” ์ƒˆ `Settings` ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ `admin_email`์˜ ์ƒˆ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , ๊ทธ ์ƒˆ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ๊ทธ๊ฒƒ์ด ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## `.env` ํŒŒ์ผ ์ฝ๊ธฐ { #reading-a-env-file }
+
+๋งŽ์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ์„ค์ •์ด ๋งŽ๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ด๋ฅผ ํŒŒ์ผ์— ๋„ฃ์–ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ฝ๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ด€ํ–‰์€ ์ถฉ๋ถ„ํžˆ ํ”ํ•ด์„œ ์ด๋ฆ„๋„ ์žˆ๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋“ค์€ ๋ณดํ†ต `.env` ํŒŒ์ผ์— ๋‘๋ฉฐ, ๊ทธ ํŒŒ์ผ์„ "dotenv"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ (`.`)์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํŒŒ์ผ์€ Linux, macOS ๊ฐ™์€ Unix ๊ณ„์—ด ์‹œ์Šคํ…œ์—์„œ ์ˆจ๊น€ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ dotenv ํŒŒ์ผ์ด ๊ผญ ๊ทธ ์ •ํ™•ํ•œ ํŒŒ์ผ๋ช…์„ ๊ฐ€์ ธ์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
+
+///
+
+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>๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+/// tip | ํŒ
+
+์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด `pip install python-dotenv`๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### `.env` ํŒŒ์ผ { #the-env-file }
+
+๋‹ค์Œ๊ณผ ๊ฐ™์€ `.env` ํŒŒ์ผ์„ ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```bash
+ADMIN_EMAIL="deadpool@example.com"
+APP_NAME="ChimichangApp"
+```
+
+### `.env`์—์„œ ์„ค์ • ์ฝ๊ธฐ { #read-settings-from-env }
+
+๊ทธ๋ฆฌ๊ณ  `config.py`๋ฅผ ๋‹ค์Œ์ฒ˜๋Ÿผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
+
+/// tip | ํŒ
+
+`model_config` ์†์„ฑ์€ Pydantic ์„ค์ •์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+///
+
+์—ฌ๊ธฐ์„œ๋Š” Pydantic `Settings` ํด๋ž˜์Šค ์•ˆ์— config `env_file`์„ ์ •์˜ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๋ ค๋Š” dotenv ํŒŒ์ผ์˜ ํŒŒ์ผ๋ช…์„ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+### `lru_cache`๋กœ `Settings`๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑํ•˜๊ธฐ { #creating-the-settings-only-once-with-lru-cache }
+
+๋””์Šคํฌ์—์„œ ํŒŒ์ผ์„ ์ฝ๋Š” ๊ฒƒ์€ ๋ณดํ†ต ๋น„์šฉ์ด ํฐ(๋А๋ฆฐ) ์ž‘์—…์ด๋ฏ€๋กœ, ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์ฝ๊ธฐ๋ณด๋‹ค๋Š” ํ•œ ๋ฒˆ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋™์ผํ•œ settings ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋งค๋ฒˆ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด:
+
+```Python
+Settings()
+```
+
+์ƒˆ `Settings` ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ์ƒ์„ฑ ์‹œ์ ์— `.env` ํŒŒ์ผ์„ ๋‹ค์‹œ ์ฝ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+์˜์กด์„ฑ ํ•จ์ˆ˜๊ฐ€ ๋‹จ์ˆœํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๋ฉด:
+
+```Python
+def get_settings():
+    return Settings()
+```
+
+์š”์ฒญ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๊ณ , ์š”์ฒญ๋งˆ๋‹ค `.env` ํŒŒ์ผ์„ ์ฝ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โš ๏ธ
+
+ํ•˜์ง€๋งŒ ์œ„์— `@lru_cache` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, `Settings` ๊ฐ์ฒด๋Š” ์ตœ์ดˆ ํ˜ธ์ถœ ์‹œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. โœ”๏ธ
+
+{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
+
+๊ทธ ๋‹ค์Œ ์š”์ฒญ๋“ค์—์„œ ์˜์กด์„ฑ์œผ๋กœ `get_settings()`๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค, `get_settings()`์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์„œ ์ƒˆ `Settings` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ์ฒซ ํ˜ธ์ถœ์—์„œ ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ๊ณ„์† ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+#### `lru_cache` Technical Details { #lru-cache-technical-details }
+
+`@lru_cache`๋Š” ๋ฐ์ฝ”๋ ˆ์ด์…˜ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋งค๋ฒˆ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ๋Œ€์‹ , ์ฒซ ๋ฒˆ์งธ์— ๋ฐ˜ํ™˜๋œ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋งค๋ฒˆ ํ•จ์ˆ˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
+
+๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ํ•จ์ˆ˜๋Š” ์ธ์ž ์กฐํ•ฉ๋งˆ๋‹ค ํ•œ ๋ฒˆ์”ฉ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ์ธ์ž ์กฐํ•ฉ์— ๋Œ€ํ•ด ๋ฐ˜ํ™˜๋œ ๊ฐ’์€, ํ•จ์ˆ˜๊ฐ€ ์ •ํ™•ํžˆ ๊ฐ™์€ ์ธ์ž ์กฐํ•ฉ์œผ๋กœ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด:
+
+```Python
+@lru_cache
+def say_hi(name: str, salutation: str = "Ms."):
+    return f"Hello {salutation} {name}"
+```
+
+ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```mermaid
+sequenceDiagram
+
+participant code as Code
+participant function as say_hi()
+participant execute as Execute function
+
+    rect rgba(0, 255, 0, .1)
+        code ->> function: say_hi(name="Camila")
+        function ->> execute: execute function code
+        execute ->> code: return the result
+    end
+
+    rect rgba(0, 255, 255, .1)
+        code ->> function: say_hi(name="Camila")
+        function ->> code: return stored result
+    end
+
+    rect rgba(0, 255, 0, .1)
+        code ->> function: say_hi(name="Rick")
+        function ->> execute: execute function code
+        execute ->> code: return the result
+    end
+
+    rect rgba(0, 255, 0, .1)
+        code ->> function: say_hi(name="Rick", salutation="Mr.")
+        function ->> execute: execute function code
+        execute ->> code: return the result
+    end
+
+    rect rgba(0, 255, 255, .1)
+        code ->> function: say_hi(name="Rick")
+        function ->> code: return stored result
+    end
+
+    rect rgba(0, 255, 255, .1)
+        code ->> function: say_hi(name="Camila")
+        function ->> code: return stored result
+    end
+```
+
+์šฐ๋ฆฌ์˜ ์˜์กด์„ฑ `get_settings()`์˜ ๊ฒฝ์šฐ, ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์ธ์ž๋„ ๋ฐ›์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฑฐ์˜ ์ „์—ญ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜์กด์„ฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์‰ฝ๊ฒŒ 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>์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## ์ •๋ฆฌ { #recap }
+
+Pydantic Settings๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Pydantic ๋ชจ๋ธ์˜ ๋ชจ๋“  ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ • ๋˜๋Š” ๊ตฌ์„ฑ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+* ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `.env` ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `@lru_cache`๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ์š”์ฒญ๋งˆ๋‹ค dotenv ํŒŒ์ผ์„ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋ฉด์„œ๋„, ํ…Œ์ŠคํŠธ ์ค‘์—๋Š” ์ด๋ฅผ overrideํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md
new file mode 100644 (file)
index 0000000..d8c2df2
--- /dev/null
@@ -0,0 +1,485 @@
+# ๋Œ€์•ˆ, ์˜๊ฐ, ๋น„๊ต { #alternatives-inspiration-and-comparisons }
+
+**FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ๋“ค, ๋Œ€์•ˆ๊ณผ์˜ ๋น„๊ต, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋กœ๋ถ€ํ„ฐ ๋ฌด์—‡์„ ๋ฐฐ์› ๋Š”์ง€์— ๋Œ€ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
+
+## ์†Œ๊ฐœ { #intro }
+
+๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์ด์ „ ์ž‘์—…์ด ์—†์—ˆ๋‹ค๋ฉด **FastAPI**๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ ์ „์— ๋งŒ๋“ค์–ด์ง„ ๋งŽ์€ ๋„๊ตฌ๋“ค์ด **FastAPI**์˜ ํƒ„์ƒ์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ €๋Š” ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ ์ƒˆ๋กœ์šด framework๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € **FastAPI**๊ฐ€ ๋‹ค๋ฃจ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์—ฌ๋Ÿฌ ์„œ๋กœ ๋‹ค๋ฅธ framework, plug-in, ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•ด ๋ณด๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์–ด๋А ์‹œ์ ์—๋Š”, ์ด์ „ ๋„๊ตฌ๋“ค์˜ ๊ฐ€์žฅ ์ข‹์€ ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ€๋Šฅํ•œ ์ตœ์„ ์˜ ๋ฐฉ์‹์œผ๋กœ ์กฐํ•ฉํ•˜๊ณ , ์ด์ „์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š์•˜๋˜ ์–ธ์–ด ๊ธฐ๋Šฅ(Python 3.6+ type hints)์„ ํ™œ์šฉํ•ด ์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ ์™ธ์—๋Š” ๋‹ค๋ฅธ ์„ ํƒ์ง€๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
+
+## ์ด์ „ ๋„๊ตฌ๋“ค { #previous-tools }
+
+### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
+
+๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” Python framework์ด๋ฉฐ ๋„๋ฆฌ ์‹ ๋ขฐ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Instagram ๊ฐ™์€ ์‹œ์Šคํ…œ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+์ƒ๋Œ€์ ์œผ๋กœ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(์˜ˆ: MySQL ๋˜๋Š” PostgreSQL)์™€ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์–ด์„œ, NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(์˜ˆ: Couchbase, MongoDB, Cassandra ๋“ฑ)๋ฅผ ์ฃผ ์ €์žฅ ์—”์ง„์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋ฆฌ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+๋ฐฑ์—”๋“œ์—์„œ 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๋Š” Django๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Web API๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ์œ ์—ฐํ•œ toolkit์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๊ณ , Django์˜ API ๊ธฐ๋Šฅ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+Mozilla, Red Hat, Eventbrite๋ฅผ ํฌํ•จํ•ด ๋งŽ์€ ํšŒ์‚ฌ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+**์ž๋™ API ๋ฌธ์„œํ™”**์˜ ์ดˆ๊ธฐ ์‚ฌ๋ก€ ์ค‘ ํ•˜๋‚˜์˜€๊ณ , ์ด๊ฒƒ์ด ํŠนํžˆ **FastAPI**๋ฅผ "์ฐพ๊ฒŒ ๋œ" ์ฒซ ์•„์ด๋””์–ด ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค.
+
+/// note | ์ฐธ๊ณ 
+
+Django REST Framework๋Š” Tom Christie๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. **FastAPI**์˜ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” Starlette์™€ Uvicorn์„ ๋งŒ๋“  ์‚ฌ๋žŒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+์ž๋™ API ๋ฌธ์„œํ™” ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ.
+
+///
+
+### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
+
+Flask๋Š” "microframework"๋กœ, Django์— ๊ธฐ๋ณธ์œผ๋กœ ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ตํ•ฉ์ด๋‚˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์„ ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ด ๋‹จ์ˆœํ•จ๊ณผ ์œ ์—ฐ์„ฑ ๋•๋ถ„์— NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ฃผ ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹œ์Šคํ…œ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ™์€ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
+
+๋งค์šฐ ๋‹จ์ˆœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๊ต์  ์ง๊ด€์ ์œผ๋กœ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฌธ์„œ๊ฐ€ ์–ด๋–ค ์ง€์ ์—์„œ๋Š” ๋‹ค์†Œ ๊ธฐ์ˆ ์ ์œผ๋กœ ๊นŠ์–ด์ง€๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ, ํ˜น์€ Django์— ๋ฏธ๋ฆฌ ๊ตฌ์ถ•๋˜์–ด ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์ด ๊ผญ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋„ ํ”ํžˆ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค ์ค‘ ๋‹ค์ˆ˜๋Š” plug-in์œผ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Ÿฐ ๊ตฌ์„ฑ์š”์†Œ์˜ ๋ถ„๋ฆฌ์™€, ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์ •ํ™•ํžˆ ๋ง๋ถ™์—ฌ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” "microframework"๋ผ๋Š” ์ ์€ ์ œ๊ฐ€ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ํ•ต์‹ฌ ํŠน์„ฑ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+Flask์˜ ๋‹จ์ˆœํ•จ์„ ๊ณ ๋ คํ•˜๋ฉด API๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ž˜ ๋งž๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์ฐพ๊ณ ์ž ํ–ˆ๋˜ ๊ฒƒ์€ Flask์šฉ "Django REST Framework"์˜€์Šต๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+micro-framework๊ฐ€ ๋˜๊ธฐ. ํ•„์š”ํ•œ ๋„๊ตฌ์™€ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ.
+
+๋‹จ์ˆœํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด routing ์‹œ์Šคํ…œ์„ ๊ฐ–๊ธฐ.
+
+///
+
+### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
+
+**FastAPI**๋Š” ์‹ค์ œ๋กœ **Requests**์˜ ๋Œ€์•ˆ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‘˜์˜ ๋ฒ”์œ„๋Š” ๋งค์šฐ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
+
+์‹ค์ œ๋กœ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ *๋‚ด๋ถ€์—์„œ* Requests๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ํ”ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿผ์—๋„ FastAPI๋Š” Requests๋กœ๋ถ€ํ„ฐ ๊ฝค ๋งŽ์€ ์˜๊ฐ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.
+
+**Requests**๋Š” (ํด๋ผ์ด์–ธํŠธ๋กœ์„œ) API์™€ *์ƒํ˜ธ์ž‘์šฉ*ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ , **FastAPI**๋Š” (์„œ๋ฒ„๋กœ์„œ) API๋ฅผ *๊ตฌ์ถ•*ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
+
+๋Œ€๋žต ๋งํ•˜๋ฉด ์„œ๋กœ ๋ฐ˜๋Œ€ํŽธ์— ์žˆ์œผ๋ฉฐ, ์„œ๋กœ๋ฅผ ๋ณด์™„ํ•ฉ๋‹ˆ๋‹ค.
+
+Requests๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ธ ์„ค๊ณ„๋ฅผ ๊ฐ€์กŒ๊ณ , ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์•„์ฃผ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋™์‹œ์— ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๊ณ  ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ๊ณต์‹ ์›น์‚ฌ์ดํŠธ์—์„œ ๋งํ•˜๋“ฏ์ด:
+
+> Requests is one of the most downloaded Python packages of all time
+
+์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `GET` ์š”์ฒญ์„ ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค:
+
+```Python
+response = requests.get("http://example.com/some/url")
+```
+
+์ด์— ๋Œ€์‘ํ•˜๋Š” FastAPI์˜ API *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python hl_lines="1"
+@app.get("/some/url")
+def read_url():
+    return {"message": "Hello World"}
+```
+
+`requests.get(...)`์™€ `@app.get(...)`์˜ ์œ ์‚ฌ์„ฑ์„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+* ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ธ API๋ฅผ ๊ฐ–๊ธฐ.
+* HTTP method ์ด๋ฆ„(operations)์„ ์ง์ ‘, ์ง๊ด€์ ์ด๊ณ  ๋ช…ํ™•ํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ.
+* ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•˜๋˜, ๊ฐ•๋ ฅํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ.
+
+///
+
+### <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 }
+
+์ œ๊ฐ€ Django REST Framework์—์„œ ๊ฐ€์žฅ ์›ํ–ˆ๋˜ ์ฃผ์š” ๊ธฐ๋Šฅ์€ ์ž๋™ API ๋ฌธ์„œํ™”์˜€์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ํ›„ JSON(๋˜๋Š” JSON์˜ ํ™•์žฅ์ธ YAML)์„ ์‚ฌ์šฉํ•ด API๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ํ‘œ์ค€์ธ Swagger๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  Swagger API๋ฅผ ์œ„ํ•œ ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ ธ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ API์— ๋Œ€ํ•œ Swagger ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ด ์›น ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž๋™์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+์–ด๋А ์‹œ์ ์— Swagger๋Š” Linux Foundation์œผ๋กœ ๋„˜์–ด๊ฐ€ OpenAPI๋กœ ์ด๋ฆ„์ด ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ 2.0 ๋ฒ„์ „์„ ์ด์•ผ๊ธฐํ•  ๋•Œ๋Š” "Swagger"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๊ณ , 3+ ๋ฒ„์ „์€ "OpenAPI"๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+์ปค์Šคํ…€ schema ๋Œ€์‹ , 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>
+
+์ด ๋‘ ๊ฐ€์ง€๋Š” ๊ฝค ๋Œ€์ค‘์ ์ด๊ณ  ์•ˆ์ •์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํžˆ ๊ฒ€์ƒ‰ํ•ด๋ณด๋ฉด OpenAPI๋ฅผ ์œ„ํ•œ ๋Œ€์•ˆ UI๊ฐ€ ์ˆ˜์‹ญ ๊ฐ€์ง€๋‚˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(**FastAPI**์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+///
+
+### Flask REST framework๋“ค { #flask-rest-frameworks }
+
+Flask REST framework๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ์žˆ์ง€๋งŒ, ์‹œ๊ฐ„์„ ๋“ค์—ฌ ์กฐ์‚ฌํ•ด ๋ณธ ๊ฒฐ๊ณผ, ์ƒ๋‹น์ˆ˜๊ฐ€ ์ค‘๋‹จ๋˜์—ˆ๊ฑฐ๋‚˜ ๋ฐฉ์น˜๋˜์–ด ์žˆ์—ˆ๊ณ , ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ์—ฌ๋Ÿฌ ์ด์Šˆ ๋•Œ๋ฌธ์— ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.
+
+### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
+
+API ์‹œ์Šคํ…œ์— ํ•„์š”ํ•œ ์ฃผ์š” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ์ดํ„ฐ "<abbr title="also called marshalling, conversion - ๋งˆ์ƒฌ๋ง, ๋ณ€ํ™˜์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค">serialization</abbr>"์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ(Python)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋„คํŠธ์›Œํฌ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ JSON ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, `datetime` ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค.
+
+API์— ๋˜ ํ•˜๋‚˜ ํฌ๊ฒŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์€ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์–ด๋–ค ํ•„๋“œ๊ฐ€ `int`์ธ์ง€, ์ž„์˜์˜ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๋Š” ์‹์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ์‹œ์Šคํ…œ์ด ์—†๋‹ค๋ฉด, ๋ชจ๋“  ๊ฒ€์‚ฌ๋ฅผ ์ฝ”๋“œ์—์„œ ์ˆ˜๋™์œผ๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Ÿฐ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด Marshmallow๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ํ›Œ๋ฅญํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฉฐ, ์ €๋„ ์ด์ „์— ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ Python type hints๊ฐ€ ์กด์žฌํ•˜๊ธฐ ์ „์— ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ <abbr title="the definition of how data should be formed - ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์ •์˜">schema</abbr>๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด Marshmallow๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+๋ฐ์ดํ„ฐ ํƒ€์ž…๊ณผ ๊ฒ€์ฆ์„ ์ œ๊ณตํ•˜๋Š” "schema"๋ฅผ ์ฝ”๋“œ๋กœ ์ •์˜ํ•˜๊ณ , ์ด๋ฅผ ์ž๋™์œผ๋กœ ํ™œ์šฉํ•˜๊ธฐ.
+
+///
+
+### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
+
+API์— ํ•„์š”ํ•œ ๋˜ ๋‹ค๋ฅธ ํฐ ๊ธฐ๋Šฅ์€ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ <abbr title="reading and converting to Python data - ์ฝ์–ด์„œ Python ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ">parsing</abbr>ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+Webargs๋Š” Flask๋ฅผ ํฌํ•จํ•œ ์—ฌ๋Ÿฌ framework ์œ„์—์„œ ์ด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.
+
+๋‚ด๋ถ€์ ์œผ๋กœ Marshmallow๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์•„์ฃผ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ด๋ฉฐ, ์ €๋„ **FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์ „์— ๋งŽ์ด ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+Webargs๋Š” Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+๋“ค์–ด์˜ค๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ์˜ ์ž๋™ ๊ฒ€์ฆ์„ ๊ฐ–๊ธฐ.
+
+///
+
+### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
+
+Marshmallow์™€ Webargs๋Š” plug-in ํ˜•ํƒœ๋กœ ๊ฒ€์ฆ, parsing, serialization์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋ฌธ์„œํ™”๋Š” ์—ฌ์ „ํžˆ ๋ถ€์กฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ APISpec์ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ์—ฌ๋Ÿฌ framework๋ฅผ ์œ„ํ•œ plug-in์ด๋ฉฐ(Starlette์šฉ plug-in๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+์ž‘๋™ ๋ฐฉ์‹์€, ๊ฐ route๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜์˜ docstring ์•ˆ์— YAML ํ˜•์‹์œผ๋กœ schema ์ •์˜๋ฅผ ์ž‘์„ฑํ•˜๊ณ ,
+
+๊ทธ๋กœ๋ถ€ํ„ฐ OpenAPI schema๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+Flask, Starlette, Responder ๋“ฑ์—์„œ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋‹ค์‹œ, Python ๋ฌธ์ž์—ด ๋‚ด๋ถ€(ํฐ YAML)์—์„œ micro-syntax๋ฅผ ๋‹ค๋ฃจ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—๋””ํ„ฐ๊ฐ€ ์ด๋ฅผ ํฌ๊ฒŒ ๋„์™€์ฃผ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋‚˜ Marshmallow schema๋ฅผ ์ˆ˜์ •ํ•ด๋†“๊ณ  YAML docstring๋„ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๋ฉด, ์ƒ์„ฑ๋œ schema๋Š” ์˜ค๋ž˜๋œ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+APISpec์€ Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+API๋ฅผ ์œ„ํ•œ ์—ด๋ฆฐ ํ‘œ์ค€์ธ OpenAPI๋ฅผ ์ง€์›ํ•˜๊ธฐ.
+
+///
+
+### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
+
+Flask plug-in์œผ๋กœ, Webargs, Marshmallow, APISpec์„ ๋ฌถ์–ด์ค๋‹ˆ๋‹ค.
+
+Webargs์™€ Marshmallow์˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•ด APISpec์œผ๋กœ OpenAPI schema๋ฅผ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ธ๋ฐ๋„ ๊ณผ์†Œํ‰๊ฐ€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋งŽ์€ Flask plug-in๋ณด๋‹ค ํ›จ์”ฌ ๋” ์œ ๋ช…ํ•ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ๊ฐ€ ๋„ˆ๋ฌด ๊ฐ„๊ฒฐํ•˜๊ณ  ์ถ”์ƒ์ ์ด๋ผ์„œ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๋„๊ตฌ๋Š” Python docstring ๋‚ด๋ถ€์— YAML(๋˜ ๋‹ค๋ฅธ ๋ฌธ๋ฒ•)์„ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+Flask + Flask-apispec + Marshmallow + Webargs ์กฐํ•ฉ์€ **FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์ „๊นŒ์ง€ ์ œ๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋˜ ๋ฐฑ์—”๋“œ stack์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์—ฌ๋Ÿฌ 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>
+
+๊ทธ๋ฆฌ๊ณ  ์ด ๋™์ผํ•œ full-stack generator๋“ค์ด [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}์˜ ๊ธฐ๋ฐ˜์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+Flask-apispec์€ Marshmallow์™€ ๊ฐ™์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+serialization๊ณผ validation์„ ์ •์˜ํ•˜๋Š” ๋™์ผํ•œ ์ฝ”๋“œ๋กœ๋ถ€ํ„ฐ OpenAPI schema๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜๊ธฐ.
+
+///
+
+### <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 }
+
+์ด๊ฑด Python๋„ ์•„๋‹™๋‹ˆ๋‹ค. NestJS๋Š” Angular์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ JavaScript(TypeScript) NodeJS framework์ž…๋‹ˆ๋‹ค.
+
+Flask-apispec์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ์–ด๋А ์ •๋„ ๋น„์Šทํ•œ ๊ฒƒ์„ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+Angular 2์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์ด ํ†ตํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์•„๋Š” ๋‹ค๋ฅธ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ๋“ค์ฒ˜๋Ÿผ "injectable"์„ ์‚ฌ์ „์— ๋“ฑ๋กํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์žฅํ™ฉํ•จ๊ณผ ์ฝ”๋“œ ๋ฐ˜๋ณต์ด ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค.
+
+ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ TypeScript ํƒ€์ž…(Python type hints์™€ ์œ ์‚ฌํ•จ)์œผ๋กœ ์„ค๋ช…๋˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋””ํ„ฐ ์ง€์›์€ ๊ฝค ์ข‹์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ TypeScript ๋ฐ์ดํ„ฐ๋Š” JavaScript๋กœ ์ปดํŒŒ์ผ๋œ ๋’ค์—๋Š” ๋ณด์กด๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ํƒ€์ž…์— ์˜์กดํ•ด ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋ฅผ ๋™์‹œ์— ์ •์˜ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์ ๊ณผ ์ผ๋ถ€ ์„ค๊ณ„ ๊ฒฐ์ • ๋•Œ๋ฌธ์—, ๊ฒ€์ฆ/serialization/์ž๋™ schema ์ƒ์„ฑ์„ ํ•˜๋ ค๋ฉด ์—ฌ๋Ÿฌ ๊ณณ์— decorator๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋งค์šฐ ์žฅํ™ฉํ•ด์ง‘๋‹ˆ๋‹ค.
+
+์ค‘์ฒฉ ๋ชจ๋ธ์„ ์ž˜ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์š”์ฒญ์˜ JSON body๊ฐ€ ๋‚ด๋ถ€ ํ•„๋“œ๋ฅผ ๊ฐ€์ง„ JSON ๊ฐ์ฒด์ด๊ณ  ๊ทธ ๋‚ด๋ถ€ ํ•„๋“œ๋“ค์ด ๋‹ค์‹œ ์ค‘์ฒฉ๋œ JSON ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ, ์ œ๋Œ€๋กœ ๋ฌธ์„œํ™”ํ•˜๊ณ  ๊ฒ€์ฆํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+Python ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด ๋›ฐ์–ด๋‚œ ์—๋””ํ„ฐ ์ง€์›์„ ์ œ๊ณตํ•˜๊ธฐ.
+
+๊ฐ•๋ ฅํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์„ ๊ฐ–์ถ”๊ธฐ. ์ฝ”๋“œ ๋ฐ˜๋ณต์„ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ.
+
+///
+
+### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
+
+`asyncio` ๊ธฐ๋ฐ˜์˜ ๋งค์šฐ ๋น ๋ฅธ Python framework ์ค‘ ์ดˆ๊ธฐ ์‚ฌ๋ก€์˜€์Šต๋‹ˆ๋‹ค. Flask์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+๊ธฐ๋ณธ Python `asyncio` ๋ฃจํ”„ ๋Œ€์‹  <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a>๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“  ์š”์ธ์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” Uvicorn๊ณผ Starlette์— ๋ช…ํ™•ํžˆ ์˜๊ฐ์„ ์ฃผ์—ˆ๊ณ , ํ˜„์žฌ ๊ณต๊ฐœ benchmark์—์„œ๋Š” ์ด ๋‘˜์ด Sanic๋ณด๋‹ค ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+๋ฏธ์นœ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ.
+
+๊ทธ๋ž˜์„œ **FastAPI**๋Š” Starlette๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. Starlette๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ framework ์ค‘ ๊ฐ€์žฅ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(์„œ๋“œํŒŒํ‹ฐ benchmark๋กœ ํ…Œ์ŠคํŠธ๋จ).
+
+///
+
+### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
+
+Falcon์€ ๋˜ ๋‹ค๋ฅธ ๊ณ ์„ฑ๋Šฅ Python framework๋กœ, ์ตœ์†Œํ•œ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ณ  Hug ๊ฐ™์€ ๋‹ค๋ฅธ framework์˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.
+
+ํ•จ์ˆ˜๊ฐ€ ๋‘ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ(ํ•˜๋‚˜๋Š” "request", ํ•˜๋‚˜๋Š” "response")๋ฅผ ๋ฐ›๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ request์—์„œ ์ผ๋ถ€๋ฅผ "์ฝ๊ณ ", response์— ์ผ๋ถ€๋ฅผ "์ž‘์„ฑ"ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค๊ณ„ ๋•Œ๋ฌธ์—, ํ‘œ์ค€ Python type hints๋ฅผ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‚ฌ์šฉํ•ด ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ body๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋Š” ์ž๋™์œผ๋กœ ๋˜์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” Hug์ฒ˜๋Ÿผ Falcon ์œ„์— framework๋ฅผ ์–น์–ด ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. request ๊ฐ์ฒด ํ•˜๋‚˜์™€ response ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” Falcon์˜ ์„ค๊ณ„์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ๋‹ค๋ฅธ framework์—์„œ๋„ ๊ฐ™์€ ๊ตฌ๋ถ„์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+ํ›Œ๋ฅญํ•œ ์„ฑ๋Šฅ์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ.
+
+Hug(= Falcon ๊ธฐ๋ฐ˜)๊ณผ ํ•จ๊ป˜, ํ•จ์ˆ˜์—์„œ `response` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค๋งŒ FastAPI์—์„œ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ, ์ฃผ๋กœ ํ—ค๋”, ์ฟ ํ‚ค, ๊ทธ๋ฆฌ๊ณ  ๋Œ€์ฒด status code๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
+
+**FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ•œ ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ Molten์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ , ๊ฝค ๋น„์Šทํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ฐ–๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค:
+
+* Python type hints ๊ธฐ๋ฐ˜
+* ์ด ํƒ€์ž…์œผ๋กœ๋ถ€ํ„ฐ ๊ฒ€์ฆ๊ณผ ๋ฌธ์„œํ™” ์ƒ์„ฑ
+* ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ
+
+Pydantic ๊ฐ™์€ ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ/serialization/๋ฌธ์„œํ™”๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ์ž์ฒด ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ •์˜๋ฅผ ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.
+
+์กฐ๊ธˆ ๋” ์žฅํ™ฉํ•œ ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ WSGI(ASGI๊ฐ€ ์•„๋‹ˆ๋ผ) ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ, Uvicorn, Starlette, Sanic ๊ฐ™์€ ๋„๊ตฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ์„ ํ™œ์šฉํ•˜๋„๋ก ์„ค๊ณ„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
+
+์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์€ ์˜์กด์„ฑ์„ ์‚ฌ์ „์— ๋“ฑ๋กํ•ด์•ผ ํ•˜๊ณ , ์„ ์–ธ๋œ ํƒ€์ž…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜์กด์„ฑ์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŠน์ • ํƒ€์ž…์„ ์ œ๊ณตํ•˜๋Š” "component"๋ฅผ ๋‘ ๊ฐœ ์ด์ƒ ์„ ์–ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
+
+Route๋Š” ํ•œ ๊ณณ์—์„œ ์„ ์–ธํ•˜๊ณ , ๋‹ค๋ฅธ ๊ณณ์— ์„ ์–ธ๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์—”๋“œํฌ์ธํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜ ๋ฐ”๋กœ ์œ„์— ๋‘˜ ์ˆ˜ ์žˆ๋Š” decorator๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ ). ์ด๋Š” Flask(๋ฐ Starlette)๋ณด๋‹ค๋Š” Django ๋ฐฉ์‹์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ์ƒ๋Œ€์ ์œผ๋กœ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ ๊ฒƒ๋“ค์„ ๋ถ„๋ฆฌํ•ด ๋†“์Šต๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+๋ชจ๋ธ ์†์„ฑ์˜ "default" ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ ํƒ€์ž…์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๊ฒ€์ฆ์„ ์ •์˜ํ•˜๊ธฐ. ์ด๋Š” ์—๋””ํ„ฐ ์ง€์›์„ ๊ฐœ์„ ํ•˜๋ฉฐ, ์ด์ „์—๋Š” Pydantic์— ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์€ ์‹ค์ œ๋กœ Pydantic์˜ ์ผ๋ถ€๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ๊ฐ™์€ ๊ฒ€์ฆ ์„ ์–ธ ์Šคํƒ€์ผ์„ ์ง€์›ํ•˜๋„๋ก ํ•˜๋Š” ๋ฐ ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค(์ด ๊ธฐ๋Šฅ์€ ์ด์ œ Pydantic์— ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค).
+
+///
+
+### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
+
+Hug๋Š” Python type hints๋ฅผ ์‚ฌ์šฉํ•ด API ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์„ ์„ ์–ธํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ์ดˆ๊ธฐ framework ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค๋„ ๊ฐ™์€ ๋ฐฉ์‹์„ ํ•˜๋„๋ก ์˜๊ฐ์„ ์ค€ ํ›Œ๋ฅญํ•œ ์•„์ด๋””์–ด์˜€์Šต๋‹ˆ๋‹ค.
+
+ํ‘œ์ค€ Python ํƒ€์ž… ๋Œ€์‹  ์ปค์Šคํ…€ ํƒ€์ž…์„ ์„ ์–ธ์— ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ํฐ ์ง„์ „์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์ „์ฒด API๋ฅผ JSON์œผ๋กœ ์„ ์–ธํ•˜๋Š” ์ปค์Šคํ…€ schema๋ฅผ ์ƒ์„ฑํ•œ ์ดˆ๊ธฐ framework ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค.
+
+OpenAPI๋‚˜ JSON Schema ๊ฐ™์€ ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— Swagger UI ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์€ ์ง๊ด€์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ญ์‹œ ๋งค์šฐ ํ˜์‹ ์ ์ธ ์•„์ด๋””์–ด์˜€์Šต๋‹ˆ๋‹ค.
+
+ํฅ๋ฏธ๋กญ๊ณ  ํ”์น˜ ์•Š์€ ๊ธฐ๋Šฅ์ด ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ framework๋กœ API๋ฟ ์•„๋‹ˆ๋ผ CLI๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋™๊ธฐ์‹ Python ์›น framework์˜ ์ด์ „ ํ‘œ์ค€(WSGI) ๊ธฐ๋ฐ˜์ด์–ด์„œ Websockets์™€ ๋‹ค๋ฅธ ๊ฒƒ๋“ค์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ, ์„ฑ๋Šฅ์€ ์—ฌ์ „ํžˆ ๋†’์Šต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+Hug๋Š” Timothy Crosley๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. Python ํŒŒ์ผ์—์„œ import๋ฅผ ์ž๋™์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ํ›Œ๋ฅญํ•œ ๋„๊ตฌ์ธ <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>์˜ ์ œ์ž‘์ž์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ์•„์ด๋””์–ด๋“ค
+
+Hug๋Š” APIStar์˜ ์ผ๋ถ€์— ์˜๊ฐ์„ ์ฃผ์—ˆ๊ณ , ์ €๋Š” APIStar์™€ ํ•จ๊ป˜ Hug๋ฅผ ๊ฐ€์žฅ ์œ ๋งํ•œ ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๋กœ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
+
+Hug๋Š” Python type hints๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๊ณ , API๋ฅผ ์ •์˜ํ•˜๋Š” schema๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+Hug๋Š” ํ—ค๋”์™€ ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜์— `response` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ ์–ธํ•˜๋„๋ก **FastAPI**์— ์˜๊ฐ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
+
+**FastAPI**๋ฅผ ๋งŒ๋“ค๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ธฐ ์ง์ „์— **APIStar** ์„œ๋ฒ„๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฐพ๊ณ  ์žˆ๋˜ ๊ฑฐ์˜ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ–์ถ”๊ณ  ์žˆ์—ˆ๊ณ  ์„ค๊ณ„๋„ ํ›Œ๋ฅญํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+NestJS์™€ Molten๋ณด๋‹ค ์•ž์„œ, Python type hints๋ฅผ ์‚ฌ์šฉํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์š”์ฒญ์„ ์„ ์–ธํ•˜๋Š” framework ๊ตฌํ˜„์„ ์ œ๊ฐ€ ์ฒ˜์Œ ๋ณธ ์‚ฌ๋ก€๋“ค ์ค‘ ํ•˜๋‚˜์˜€์Šต๋‹ˆ๋‹ค. Hug์™€ ๊ฑฐ์˜ ๊ฐ™์€ ์‹œ๊ธฐ์— ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ APIStar๋Š” OpenAPI ํ‘œ์ค€์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ๋™์ผํ•œ type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, ๋ฐ์ดํ„ฐ serialization, OpenAPI schema ์ƒ์„ฑ์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+Body schema ์ •์˜๋Š” Pydantic์ฒ˜๋Ÿผ ๋™์ผํ•œ Python type hints๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋Š” ์•Š์•˜๊ณ  Marshmallow์™€ ์กฐ๊ธˆ ๋” ๋น„์Šทํ•ด์„œ ์—๋””ํ„ฐ ์ง€์›์€ ๊ทธ๋งŒํผ ์ข‹์ง€ ์•Š์•˜์ง€๋งŒ, ๊ทธ๋ž˜๋„ APIStar๋Š” ๋‹น์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์„ ์˜ ์„ ํƒ์ง€์˜€์Šต๋‹ˆ๋‹ค.
+
+๋‹น์‹œ ์ตœ๊ณ ์˜ ์„ฑ๋Šฅ benchmark๋ฅผ ๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค(Starlette์— ์˜ํ•ด์„œ๋งŒ ์ถ”์›”๋จ).
+
+์ฒ˜์Œ์—๋Š” ์ž๋™ API ๋ฌธ์„œํ™” ์›น UI๊ฐ€ ์—†์—ˆ์ง€๋งŒ, Swagger UI๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค์ฒ˜๋Ÿผ component์˜ ์‚ฌ์ „ ๋“ฑ๋ก์ด ํ•„์š”ํ–ˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ํ›Œ๋ฅญํ•œ ๊ธฐ๋Šฅ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๋ณด์•ˆ ํ†ตํ•ฉ์ด ์—†์–ด์„œ ์ „์ฒด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Flask-apispec ๊ธฐ๋ฐ˜ full-stack generator๋กœ ๊ฐ–์ถ”๊ณ  ์žˆ๋˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” pull request๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ œ ๋ฐฑ๋กœ๊ทธ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ดํ›„ ํ”„๋กœ์ ํŠธ์˜ ์ดˆ์ ์ด ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+๋” ์ด์ƒ API web framework๊ฐ€ ์•„๋‹ˆ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ์ œ์ž‘์ž๊ฐ€ Starlette์— ์ง‘์ค‘ํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+์ด์ œ APIStar๋Š” web framework๊ฐ€ ์•„๋‹ˆ๋ผ OpenAPI ์‚ฌ์–‘์„ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+APIStar๋Š” Tom Christie๊ฐ€ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ๋งŒ๋“  ์‚ฌ๋žŒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค:
+
+* Django REST Framework
+* Starlette(**FastAPI**์˜ ๊ธฐ๋ฐ˜)
+* Uvicorn(Starlette์™€ **FastAPI**์—์„œ ์‚ฌ์šฉ)
+
+///
+
+/// check | **FastAPI**์— ์˜๊ฐ์„ ์ค€ ๊ฒƒ
+
+์กด์žฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ.
+
+๋™์ผํ•œ Python ํƒ€์ž…์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€(๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”)๋ฅผ ์„ ์–ธํ•˜๋ฉด์„œ ๋™์‹œ์— ๋›ฐ์–ด๋‚œ ์—๋””ํ„ฐ ์ง€์›์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด๋Š” ์ œ๊ฐ€ ๋งค์šฐ ํ›Œ๋ฅญํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์˜ค๋žซ๋™์•ˆ ๋น„์Šทํ•œ framework๋ฅผ ์ฐพ์•„ ์—ฌ๋Ÿฌ ๋Œ€์•ˆ์„ ํ…Œ์ŠคํŠธํ•œ ๋์—, APIStar๊ฐ€ ๊ทธ๋•Œ ์ด์šฉ ๊ฐ€๋Šฅํ•œ ์ตœ์„ ์˜ ์„ ํƒ์ง€์˜€์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ํ›„ APIStar ์„œ๋ฒ„๊ฐ€ ๋”๋Š” ์กด์žฌํ•˜์ง€ ์•Š๊ฒŒ ๋˜๊ณ  Starlette๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๋Š”๋ฐ, ์ด๋Š” ๊ทธ๋Ÿฐ ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ๋” ์ƒˆ๋กญ๊ณ  ๋” ๋‚˜์€ ๊ธฐ๋ฐ˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด **FastAPI**๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋œ ์ตœ์ข… ์˜๊ฐ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ €๋Š” **FastAPI**๋ฅผ APIStar์˜ "์ •์‹ ์  ํ›„๊ณ„์ž"๋กœ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋™์‹œ์—, ์ด ๋ชจ๋“  ์ด์ „ ๋„๊ตฌ๋“ค์—์„œ ๋ฐฐ์šด ๊ฒƒ๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ธฐ๋Šฅ, typing ์‹œ์Šคํ…œ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋ถ€๋ถ„๋“ค์„ ๊ฐœ์„ ํ•˜๊ณ  ํ™•์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## **FastAPI**๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ { #used-by-fastapi }
+
+### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
+
+Pydantic์€ Python type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”(JSON Schema ์‚ฌ์šฉ)๋ฅผ ์ •์˜ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ ๋•๋ถ„์— ๋งค์šฐ ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค.
+
+Marshmallow์™€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ benchmark์—์„œ Marshmallow๋ณด๋‹ค ๋น ๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋™์ผํ•œ Python type hints๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ ์—๋””ํ„ฐ ์ง€์›๋„ ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์ 
+
+๋ชจ๋“  ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, ๋ฐ์ดํ„ฐ serialization, ์ž๋™ ๋ชจ๋ธ ๋ฌธ์„œํ™”(JSON Schema ๊ธฐ๋ฐ˜)๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ.
+
+๊ทธ ๋‹ค์Œ **FastAPI**๋Š” ๊ทธ JSON Schema ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ OpenAPI์— ํฌํ•จ์‹œํ‚ค๋ฉฐ, ๊ทธ ์™ธ์—๋„ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
+
+Starlette๋Š” ๊ฒฝ๋Ÿ‰ <abbr title="The new standard for building asynchronous Python web applications - ๋น„๋™๊ธฐ Python ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ์ƒˆ๋กœ์šด ํ‘œ์ค€">ASGI</abbr> framework/toolkit์œผ๋กœ, ๊ณ ์„ฑ๋Šฅ asyncio ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ์— ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค.
+
+๋งค์šฐ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค. ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๊ณ , ๋ชจ๋“ˆ์‹ component๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:
+
+* ์ •๋ง ์ธ์ƒ์ ์ธ ์„ฑ๋Šฅ.
+* WebSocket ์ง€์›.
+* ํ”„๋กœ์„ธ์Šค ๋‚ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—….
+* ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ์ด๋ฒคํŠธ.
+* HTTPX ๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ ํด๋ผ์ด์–ธํŠธ.
+* CORS, GZip, Static Files, Streaming responses.
+* ์„ธ์…˜ ๋ฐ ์ฟ ํ‚ค ์ง€์›.
+* 100% ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€.
+* 100% ํƒ€์ž… ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ์ฝ”๋“œ๋ฒ ์ด์Šค.
+* ์†Œ์ˆ˜์˜ ํ•„์ˆ˜ ์˜์กด์„ฑ.
+
+Starlette๋Š” ํ˜„์žฌ ํ…Œ์ŠคํŠธ๋œ Python framework ์ค‘ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค. ๋‹จ, framework๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์ธ Uvicorn์ด ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค.
+
+Starlette๋Š” ์›น microframework์˜ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ž๋™ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, serialization, ๋ฌธ์„œํ™”๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๊ฒƒ์ด **FastAPI**๊ฐ€ ์œ„์— ์ถ”๊ฐ€ํ•˜๋Š” ํ•ต์‹ฌ ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๋ชจ๋‘ Python type hints(Pydantic ์‚ฌ์šฉ)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋”ํ•ด ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ, ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ, OpenAPI schema ์ƒ์„ฑ ๋“ฑ๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+ASGI๋Š” Django ์ฝ”์–ด ํŒ€ ๋ฉค๋ฒ„๋“ค์ด ๊ฐœ๋ฐœ ์ค‘์ธ ์ƒˆ๋กœ์šด "ํ‘œ์ค€"์ž…๋‹ˆ๋‹ค. ์•„์ง "Python ํ‘œ์ค€"(PEP)์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ทธ ๋ฐฉํ–ฅ์œผ๋กœ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿผ์—๋„ ์ด๋ฏธ ์—ฌ๋Ÿฌ ๋„๊ตฌ์—์„œ "ํ‘œ์ค€"์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ƒํ˜ธ์šด์šฉ์„ฑ์„ ํฌ๊ฒŒ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Uvicorn์„ ๋‹ค๋ฅธ ASGI ์„œ๋ฒ„(์˜ˆ: Daphne ๋˜๋Š” Hypercorn)๋กœ ๊ต์ฒดํ•  ์ˆ˜๋„ ์žˆ๊ณ , `python-socketio` ๊ฐ™์€ ASGI ํ˜ธํ™˜ ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชฉ์ 
+
+ํ•ต์‹ฌ ์›น ๋ถ€๋ถ„์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ธฐ. ๊ทธ ์œ„์— ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ.
+
+`FastAPI` ํด๋ž˜์Šค ์ž์ฒด๋Š” `Starlette` ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ Starlette๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ **FastAPI**๋กœ๋„ ์ง์ ‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, **FastAPI**๋Š” ์‚ฌ์‹ค์ƒ Starlette์— ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๋”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
+
+### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
+
+Uvicorn์€ uvloop๊ณผ httptools๋กœ ๊ตฌ์ถ•๋œ ์ดˆ๊ณ ์† ASGI ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.
+
+web framework๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ routing์„ ์œ„ํ•œ ๋„๊ตฌ๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒƒ์€ Starlette(๋˜๋Š” **FastAPI**) ๊ฐ™์€ framework๊ฐ€ ์œ„์—์„œ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+Starlette์™€ **FastAPI**์—์„œ ๊ถŒ์žฅํ•˜๋Š” ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค.
+
+/// check | **FastAPI**๊ฐ€ ์ด๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹
+
+**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์š” ์›น ์„œ๋ฒ„.
+
+๋˜ํ•œ `--workers` ์ปค๋งจ๋“œ๋ผ์ธ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๋™๊ธฐ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค ์„œ๋ฒ„๋กœ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ž์„ธํ•œ ๋‚ด์šฉ์€ [๋ฐฐํฌ](deployment/index.md){.internal-link target=_blank} ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”.
+
+///
+
+## ๋ฒค์น˜๋งˆํฌ์™€ ์†๋„ { #benchmarks-and-speed }
+
+Uvicorn, Starlette, FastAPI ์‚ฌ์ด์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋น„๊ตํ•˜๋ ค๋ฉด [๋ฒค์น˜๋งˆํฌ](benchmarks.md){.internal-link target=_blank} ์„น์…˜์„ ํ™•์ธํ•˜์„ธ์š”.
diff --git a/docs/ko/docs/deployment/concepts.md b/docs/ko/docs/deployment/concepts.md
new file mode 100644 (file)
index 0000000..dd7edd1
--- /dev/null
@@ -0,0 +1,321 @@
+# ๋ฐฐํฌ ๊ฐœ๋… { #deployments-concepts }
+
+**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์‚ฌ์‹ค ์–ด๋–ค ์ข…๋ฅ˜์˜ ์›น API๋“ )์„ ๋ฐฐํฌํ•  ๋•Œ๋Š”, ์—ฌ๋Ÿฌ๋ถ„์ด ์‹ ๊ฒฝ ์จ์•ผ ํ•  ์—ฌ๋Ÿฌ ๊ฐœ๋…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๊ฐœ๋…๋“ค์„ ํ™œ์šฉํ•˜๋ฉด **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•**์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ค‘์š”ํ•œ ๊ฐœ๋… ๋ช‡ ๊ฐ€์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ๋ณด์•ˆ - HTTPS
+* ์‹œ์ž‘ ์‹œ ์‹คํ–‰
+* ์žฌ์‹œ์ž‘
+* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜)
+* ๋ฉ”๋ชจ๋ฆฌ
+* ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„
+
+์ด๊ฒƒ๋“ค์ด **๋ฐฐํฌ**์— ์–ด๋–ค ์˜ํ–ฅ์„ ์ฃผ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๊ฒฐ๊ตญ ์ตœ์ข… ๋ชฉํ‘œ๋Š” **API ํด๋ผ์ด์–ธํŠธ์— ์„œ๋น„์Šค๋ฅผ ์ œ๊ณต**ํ•  ๋•Œ **๋ณด์•ˆ**์„ ๋ณด์žฅํ•˜๊ณ , **์ค‘๋‹จ์„ ํ”ผํ•˜๋ฉฐ**, **์ปดํ“จํŒ… ๋ฆฌ์†Œ์Šค**(์˜ˆ: ์›๊ฒฉ ์„œ๋ฒ„/๊ฐ€์ƒ ๋จธ์‹ )๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿš€
+
+์—ฌ๊ธฐ์„œ ์ด **๊ฐœ๋…๋“ค**์„ ์กฐ๊ธˆ ๋” ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์„œ๋กœ ๋งค์šฐ ๋‹ค๋ฅธ ํ™˜๊ฒฝ, ์‹ฌ์ง€์–ด ์•„์ง ์กด์žฌํ•˜์ง€ ์•Š๋Š” **๋ฏธ๋ž˜**์˜ ํ™˜๊ฒฝ์—์„œ๋„ API๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐํฌํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ **์ง๊ด€**์„ ์–ป์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด ๊ฐœ๋…๋“ค์„ ๊ณ ๋ คํ•˜๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ **์ž์‹ ์˜ API**๋ฅผ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์„ **ํ‰๊ฐ€ํ•˜๊ณ  ์„ค๊ณ„**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ๋” **๊ตฌ์ฒด์ ์ธ ๋ ˆ์‹œํ”ผ**๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€, ์ด ์ค‘์š”ํ•œ **๊ฐœ๋…์  ์•„์ด๋””์–ด**๋“ค์„ ํ™•์ธํ•ด ๋ด…์‹œ๋‹ค. ์ด ๊ฐœ๋…๋“ค์€ ๋‹ค๋ฅธ ์–ด๋–ค ์ข…๋ฅ˜์˜ ์›น API์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ’ก
+
+## ๋ณด์•ˆ - HTTPS { #security-https }
+
+[์ด์ „ HTTPS ์žฅ](https.md){.internal-link target=_blank}์—์„œ HTTPS๊ฐ€ API์— ์•”ํ˜ธํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ HTTPS๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ๋ฐ”๊นฅ์˜ **์™ธ๋ถ€** ์ปดํฌ๋„ŒํŠธ์ธ **TLS Termination Proxy**๊ฐ€ ์ œ๊ณตํ•œ๋‹ค๋Š” ๊ฒƒ๋„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  **HTTPS ์ธ์ฆ์„œ ๊ฐฑ์‹ **์„ ๋‹ด๋‹นํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ทธ ์—ญํ• ์„ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€๊ฐ€ ๋‹ด๋‹นํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### HTTPS๋ฅผ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-for-https }
+
+TLS Termination Proxy๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* Traefik
+    * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ โœจ
+* Caddy
+    * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ โœจ
+* Nginx
+    * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด Certbot ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ
+* HAProxy
+    * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด Certbot ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ
+* Nginx ๊ฐ™์€ Ingress Controller๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Kubernetes
+    * ์ธ์ฆ์„œ ๊ฐฑ์‹ ์„ ์œ„ํ•ด cert-manager ๊ฐ™์€ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ
+* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ(์•„๋ž˜๋ฅผ ์ฝ์–ด๋ณด์„ธ์š” ๐Ÿ‘‡)
+
+๋˜ ๋‹ค๋ฅธ ์„ ํƒ์ง€๋Š” HTTPS ์„ค์ •์„ ํฌํ•จํ•ด ๋” ๋งŽ์€ ์ผ์„ ๋Œ€์‹ ํ•ด์ฃผ๋Š” **ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ์•ฝ์ด ์žˆ๊ฑฐ๋‚˜ ๋น„์šฉ์ด ๋” ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ๊ฒฝ์šฐ์—๋Š” TLS Termination Proxy๋ฅผ ์ง์ ‘ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ ์žฅ์—์„œ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+---
+
+๋‹ค์Œ์œผ๋กœ ๊ณ ๋ คํ•  ๊ฐœ๋…๋“ค์€ ์‹ค์ œ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ API๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)๊ณผ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
+
+## ํ”„๋กœ๊ทธ๋žจ๊ณผ ํ”„๋กœ์„ธ์Šค { #program-and-process }
+
+์‹คํ–‰ ์ค‘์ธ "**ํ”„๋กœ์„ธ์Šค**"์— ๋Œ€ํ•ด ๋งŽ์ด ์ด์•ผ๊ธฐํ•˜๊ฒŒ ๋  ํ…๋ฐ, ์ด ๋ง์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  "**ํ”„๋กœ๊ทธ๋žจ**"์ด๋ผ๋Š” ๋‹จ์–ด์™€ ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€ ๋ช…ํ™•ํžˆ ํ•ด๋‘๋Š” ๊ฒƒ์ด ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+### ํ”„๋กœ๊ทธ๋žจ์ด๋ž€ { #what-is-a-program }
+
+**ํ”„๋กœ๊ทธ๋žจ**์ด๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค:
+
+* ์—ฌ๋Ÿฌ๋ถ„์ด ์ž‘์„ฑํ•˜๋Š” **์ฝ”๋“œ**, ์ฆ‰ **Python ํŒŒ์ผ**๋“ค
+* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰**ํ•  ์ˆ˜ ์žˆ๋Š” **ํŒŒ์ผ**, ์˜ˆ: `python`, `python.exe`, `uvicorn`
+* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰ ์ค‘**์ธ ํŠน์ • ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ, CPU๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์— ๋‚ด์šฉ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ **ํ”„๋กœ์„ธ์Šค**๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.
+
+### ํ”„๋กœ์„ธ์Šค๋ž€ { #what-is-a-process }
+
+**ํ”„๋กœ์„ธ์Šค**๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ๋” ๊ตฌ์ฒด์ ์œผ๋กœ, ์šด์˜์ฒด์ œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๊ฒƒ(์œ„ ๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์ฒ˜๋Ÿผ)๋งŒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค:
+
+* ์šด์˜์ฒด์ œ์—์„œ **์‹คํ–‰ ์ค‘**์ธ ํŠน์ • ํ”„๋กœ๊ทธ๋žจ
+    * ํŒŒ์ผ์ด๋‚˜ ์ฝ”๋“œ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์šด์˜์ฒด์ œ๊ฐ€ **์‹ค์ œ๋กœ ์‹คํ–‰**ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋Œ€์ƒ์„ **๊ตฌ์ฒด์ ์œผ๋กœ** ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
+* ์–ด๋–ค ํ”„๋กœ๊ทธ๋žจ์ด๋“  ์–ด๋–ค ์ฝ”๋“œ๋“ , **์‹คํ–‰**๋  ๋•Œ๋งŒ ๋ฌด์–ธ๊ฐ€๋ฅผ **ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค**. ์ฆ‰, **ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘**์ผ ๋•Œ์ž…๋‹ˆ๋‹ค.
+* ํ”„๋กœ์„ธ์Šค๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด, ํ˜น์€ ์šด์˜์ฒด์ œ๊ฐ€ **์ข…๋ฃŒ**(๋˜๋Š” โ€œkillโ€)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์‹คํ–‰์ด ๋ฉˆ์ถ”๊ณ , ๋” ์ด์ƒ **์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค**.
+* ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋’ค์—๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ, ๊ฐ ์ฐฝ ๋“ฑ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปดํ“จํ„ฐ๊ฐ€ ์ผœ์ ธ ์žˆ๋Š” ๋™์•ˆ ๋ณดํ†ต ๋งŽ์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ **๋™์‹œ์—** ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
+* **๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ**์˜ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์šด์˜์ฒด์ œ์˜ โ€œ์ž‘์—… ๊ด€๋ฆฌ์ž(task manager)โ€๋‚˜ โ€œ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ(system monitor)โ€(๋˜๋Š” ๋น„์Šทํ•œ ๋„๊ตฌ)๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด, ์ด๋Ÿฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋งŽ์ด ์‹คํ–‰ ์ค‘์ธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ™์€ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ๊ทธ๋žจ(Firefox, Chrome, Edge ๋“ฑ)์„ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋Š” ๊ฒƒ๋„ ๋ณด์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ๋ณดํ†ต ํƒญ๋งˆ๋‹ค ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ๊ทธ ์™ธ์—๋„ ์ถ”๊ฐ€ ํ”„๋กœ์„ธ์Šค ๋ช‡ ๊ฐœ๊ฐ€ ๋” ์žˆ์Šต๋‹ˆ๋‹ค.
+
+<img class="shadow" src="/img/deployment/concepts/image01.png">
+
+---
+
+์ด์ œ **ํ”„๋กœ์„ธ์Šค**์™€ **ํ”„๋กœ๊ทธ๋žจ**์˜ ์ฐจ์ด๋ฅผ ์•Œ์•˜์œผ๋‹ˆ, ๋ฐฐํฌ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ๊ณ„์†ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ์‹œ์ž‘ ์‹œ ์‹คํ–‰ { #running-on-startup }
+
+๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์›น API๋ฅผ ๋งŒ๋“ค๋ฉด, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ธ์ œ๋‚˜ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก **ํ•ญ์ƒ ์‹คํ–‰**๋˜๊ณ  ์ค‘๋‹จ๋˜์ง€ ์•Š๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ํŠน์ • ์ƒํ™ฉ์—์„œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์žˆ์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์€ ์ง€์†์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ **์‚ฌ์šฉ ๊ฐ€๋Šฅ**ํ•œ ์ƒํƒœ์ด๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.
+
+### ์›๊ฒฉ ์„œ๋ฒ„์—์„œ { #in-a-remote-server }
+
+์›๊ฒฉ ์„œ๋ฒ„(ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„, ๊ฐ€์ƒ ๋จธ์‹  ๋“ฑ)๋ฅผ ์„ค์ •ํ•  ๋•Œ, ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ๋•Œ์ฒ˜๋Ÿผ ์ˆ˜๋™์œผ๋กœ `fastapi run`(Uvicorn์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค)์ด๋‚˜ ๋น„์Šทํ•œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด ๋ฐฉ์‹์€ ๋™์ž‘ํ•˜๊ณ , **๊ฐœ๋ฐœ ์ค‘์—๋Š”** ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์„œ๋ฒ„์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์ด ๋Š๊ธฐ๋ฉด, ์‹คํ–‰ ์ค‘์ธ **ํ”„๋กœ์„ธ์Šค**๋„ ์•„๋งˆ ์ข…๋ฃŒ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ ์„œ๋ฒ„๊ฐ€ ์žฌ์‹œ์ž‘๋˜๋ฉด(์˜ˆ: ์—…๋ฐ์ดํŠธ ์ดํ›„, ํ˜น์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ดํ›„) ์—ฌ๋Ÿฌ๋ถ„์€ ์•„๋งˆ **์•Œ์•„์ฐจ๋ฆฌ์ง€ ๋ชปํ• ** ๊ฒ๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ, ํ”„๋กœ์„ธ์Šค๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค๋„ ๋ชจ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด API๋Š” ๊ทธ๋ƒฅ ์ฃฝ์€ ์ƒํƒœ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ฑ
+
+### ์‹œ์ž‘ ์‹œ ์ž๋™ ์‹คํ–‰ { #run-automatically-on-startup }
+
+์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)์€ ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์ž๋™์œผ๋กœ ์‹œ์ž‘๋˜๊ณ , **์‚ฌ๋žŒ์˜ ๊ฐœ์ž…** ์—†์ด๋„ FastAPI ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•ญ์ƒ ์‹คํ–‰ ์ค‘์ด๋„๋ก(์˜ˆ: FastAPI ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” Uvicorn) ๊ตฌ์„ฑํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+### ๋ณ„๋„์˜ ํ”„๋กœ๊ทธ๋žจ { #separate-program }
+
+์ด๋ฅผ ์œ„ํ•ด ๋ณดํ†ต ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘ ์‹œ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” **๋ณ„๋„์˜ ํ”„๋กœ๊ทธ๋žจ**์„ ๋‘ก๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ™์€ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋„ ํ•จ๊ป˜ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
+
+### ์‹œ์ž‘ ์‹œ ์‹คํ–‰์„ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-to-run-at-startup }
+
+์ด ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Swarm Mode์˜ Docker
+* Systemd
+* Supervisor
+* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ
+* ๊ธฐํƒ€...
+
+๋‹ค์Œ ์žฅ์—์„œ ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ์žฌ์‹œ์ž‘ { #restarts }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘ ์‹œ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๊ฒŒ, ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ **์žฌ์‹œ์ž‘**๋˜๋„๋ก ๋ณด์žฅํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+### ์šฐ๋ฆฌ๋Š” ์‹ค์ˆ˜ํ•ฉ๋‹ˆ๋‹ค { #we-make-mistakes }
+
+์‚ฌ๋žŒ์€ ์–ธ์ œ๋‚˜ **์‹ค์ˆ˜**ํ•ฉ๋‹ˆ๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด์—๋Š” ๊ฑฐ์˜ *ํ•ญ์ƒ* ์—ฌ๊ธฐ์ €๊ธฐ์— ์ˆจ์€ **๋ฒ„๊ทธ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ›
+
+๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๋Š” ๋ฒ„๊ทธ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ๊ณ„์† ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค(์ƒˆ๋กœ์šด ๋ฒ„๊ทธ๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ  ๐Ÿ˜…).
+
+### ์ž‘์€ ์˜ค๋ฅ˜๋Š” ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋จ { #small-errors-automatically-handled }
+
+FastAPI๋กœ ์›น API๋ฅผ ๋งŒ๋“ค ๋•Œ ์ฝ”๋“œ์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์œผ๋ฉด, FastAPI๋Š” ๋ณดํ†ต ๊ทธ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ๋‹จ์ผ ์š”์ฒญ ์•ˆ์—๋งŒ ๋ฌธ์ œ๋ฅผ ๊ฐ€๋‘ก๋‹ˆ๋‹ค. ๐Ÿ›ก
+
+ํด๋ผ์ด์–ธํŠธ๋Š” ํ•ด๋‹น ์š”์ฒญ์— ๋Œ€ํ•ด **500 Internal Server Error**๋ฅผ ๋ฐ›์ง€๋งŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์™„์ „ํžˆ ํฌ๋ž˜์‹œํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ์š”์ฒญ๋ถ€ํ„ฐ๋Š” ๊ณ„์† ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+### ๋” ํฐ ์˜ค๋ฅ˜ - ํฌ๋ž˜์‹œ { #bigger-errors-crashes }
+
+๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ **์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํฌ๋ž˜์‹œ**์‹œ์ผœ Uvicorn๊ณผ Python ์ž์ฒด๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’ฅ
+
+๊ทธ๋ž˜๋„ ํ•œ ๊ตฐ๋ฐ ์˜ค๋ฅ˜ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฃฝ์€ ์ฑ„๋กœ ๋‚จ์•„ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ง๊ฐ€์ง„ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ผ๋„ **๊ณ„์† ์‹คํ–‰**๋˜๊ธฐ๋ฅผ ์›ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+### ํฌ๋ž˜์‹œ ํ›„ ์žฌ์‹œ์ž‘ { #restart-after-crash }
+
+ํ•˜์ง€๋งŒ ์‹คํ–‰ ์ค‘์ธ **ํ”„๋กœ์„ธ์Šค**๊ฐ€ ํฌ๋ž˜์‹œํ•˜๋Š” ์ •๋ง ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜์˜ ๊ฒฝ์šฐ์—๋Š”, ์ ์–ด๋„ ๋ช‡ ๋ฒˆ์€ ํ”„๋กœ์„ธ์Šค๋ฅผ **์žฌ์‹œ์ž‘**ํ•˜๋„๋ก ๋‹ด๋‹นํ•˜๋Š” ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค...
+
+/// tip | ํŒ
+
+...๋‹ค๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด๊ฐ€ **์ฆ‰์‹œ ๊ณ„์† ํฌ๋ž˜์‹œ**ํ•œ๋‹ค๋ฉด, ๋ฌดํ•œํžˆ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ์•„๋งˆ ์˜๋ฏธ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ๊ฐœ๋ฐœ ์ค‘์—, ๋˜๋Š” ์ตœ์†Œํ•œ ๋ฐฐํฌ ์งํ›„์— ์•Œ์•„์ฐจ๋ฆด ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฌ๋‹ˆ ์—ฌ๊ธฐ์„œ๋Š”, ํŠน์ •ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ „์ฒด๊ฐ€ ํฌ๋ž˜์‹œํ•  ์ˆ˜ ์žˆ๊ณ  **๋ฏธ๋ž˜**์—๋„ ๊ทธ๋Ÿด ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ๋ž˜๋„ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์˜๋ฏธ ์žˆ๋Š” ์ฃผ์š” ์‚ฌ๋ก€์— ์ง‘์ค‘ํ•ด ๋ด…์‹œ๋‹ค.
+
+///
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‹œ์ž‘ํ•˜๋Š” ์—ญํ• ์€ **์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ**๊ฐ€ ๋งก๋Š” ํŽธ์ด ๋ณดํ†ต ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ ์‹œ์ ์—๋Š” Uvicorn๊ณผ Python์„ ํฌํ•จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ด๋ฏธ ํฌ๋ž˜์‹œํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ™์€ ์•ฑ์˜ ๊ฐ™์€ ์ฝ”๋“œ ์•ˆ์—์„œ ์ด๋ฅผ ํ•ด๊ฒฐํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+### ์ž๋™ ์žฌ์‹œ์ž‘์„ ์œ„ํ•œ ๋„๊ตฌ ์˜ˆ์‹œ { #example-tools-to-restart-automatically }
+
+๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ **์‹œ์ž‘ ์‹œ ์‹คํ–‰**์— ์‚ฌ์šฉํ•œ ๋„๊ตฌ๊ฐ€ ์ž๋™ **์žฌ์‹œ์ž‘**๋„ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Swarm Mode์˜ Docker
+* Systemd
+* Supervisor
+* ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž๊ฐ€ ์„œ๋น„์Šค ์ผ๋ถ€๋กœ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌ
+* ๊ธฐํƒ€...
+
+## ๋ณต์ œ - ํ”„๋กœ์„ธ์Šค์™€ ๋ฉ”๋ชจ๋ฆฌ { #replication-processes-and-memory }
+
+FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Uvicorn์„ ์‹คํ–‰ํ•˜๋Š” `fastapi` ๋ช…๋ น ๊ฐ™์€ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋ฉด, **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•˜๋”๋ผ๋„ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋งŽ์€ ๊ฒฝ์šฐ, ์—ฌ๋Ÿฌ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+### ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค - ์›Œ์ปค { #multiple-processes-workers }
+
+๋‹จ์ผ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋” ๋งŽ๊ณ (์˜ˆ: ๊ฐ€์ƒ ๋จธ์‹ ์ด ๊ทธ๋ฆฌ ํฌ์ง€ ์•Š์„ ๋•Œ), ์„œ๋ฒ„ CPU์— **์—ฌ๋Ÿฌ ์ฝ”์–ด**๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋™์‹œ์— ๋„์šฐ๊ณ  ์š”์ฒญ์„ ๋ถ„์‚ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ™์€ API ํ”„๋กœ๊ทธ๋žจ์„ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋กœ ์‹คํ–‰ํ•  ๋•Œ, ์ด ํ”„๋กœ์„ธ์Šค๋“ค์„ ๋ณดํ†ต **workers**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
+
+### ์›Œ์ปค ํ”„๋กœ์„ธ์Šค์™€ ํฌํŠธ { #worker-processes-and-ports }
+
+[HTTPS์— ๋Œ€ํ•œ ๋ฌธ์„œ](https.md){.internal-link target=_blank}์—์„œ, ์„œ๋ฒ„์—์„œ ํ•˜๋‚˜์˜ ํฌํŠธ์™€ IP ์ฃผ์†Œ ์กฐํ•ฉ์—๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”?
+
+์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋ ค๋ฉด, ๋จผ์ € **ํฌํŠธ์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๊ทธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ๊ฐ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋กœ ํ†ต์‹ ์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+### ํ”„๋กœ์„ธ์Šค๋‹น ๋ฉ”๋ชจ๋ฆฌ { #memory-per-process }
+
+์ด์ œ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๋กœ๋“œํ•œ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ๋ณ€์ˆ˜์— ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜ ํฐ ํŒŒ์ผ ๋‚ด์šฉ์„ ๋ณ€์ˆ˜์— ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒƒ๋“ค์€ ์„œ๋ฒ„์˜ **๋ฉ”๋ชจ๋ฆฌ(RAM)**๋ฅผ ์–ด๋А ์ •๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋Š” ๋ณดํ†ต **๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ์ฆ‰, ๊ฐ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๋Š” ์ž์ฒด ๋ณ€์ˆ˜์™€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, **๊ฐ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ๊ทธ๋งŒํผ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+### ์„œ๋ฒ„ ๋ฉ”๋ชจ๋ฆฌ { #server-memory }
+
+์˜ˆ๋ฅผ ๋“ค์–ด ์ฝ”๋“œ๊ฐ€ ํฌ๊ธฐ **1 GB**์˜ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ๋กœ๋“œํ•œ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. API๋ฅผ ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๋กœ ์‹คํ–‰ํ•˜๋ฉด RAM์„ ์ตœ์†Œ 1GB ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  **4๊ฐœ ํ”„๋กœ์„ธ์Šค**(์›Œ์ปค 4๊ฐœ)๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ๊ฐ๊ฐ 1GB RAM์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰ ์ด **4 GB RAM**์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ๋ฐ ์›๊ฒฉ ์„œ๋ฒ„๋‚˜ ๊ฐ€์ƒ ๋จธ์‹ ์˜ RAM์ด 3GB๋ฟ์ด๋ผ๋ฉด, 4GB๋ฅผ ๋„˜๊ฒŒ ๋กœ๋“œํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ๐Ÿšจ
+
+### ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค - ์˜ˆ์‹œ { #multiple-processes-an-example }
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” **Manager Process**๊ฐ€ ๋‘ ๊ฐœ์˜ **Worker Processes**๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
+
+์ด Manager Process๋Š” ์•„๋งˆ IP์˜ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ํ†ต์‹ ์„ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
+
+์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋“ค์ด ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ฉฐ, **์š”์ฒญ**์„ ๋ฐ›์•„ **์‘๋‹ต**์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฃผ์š” ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ณ , RAM์— ๋ณ€์ˆ˜๋กœ ๋กœ๋“œํ•œ ๋ชจ๋“  ๋‚ด์šฉ์„ ๋‹ด์Šต๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/concepts/process-ram.drawio.svg">
+
+๊ทธ๋ฆฌ๊ณ  ๋ฌผ๋ก  ๊ฐ™์€ ๋จธ์‹ ์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์™ธ์—๋„ **๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค**๋“ค์ด ์‹คํ–‰ ์ค‘์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+ํฅ๋ฏธ๋กœ์šด ์ ์€ ๊ฐ ํ”„๋กœ์„ธ์Šค์˜ **CPU ์‚ฌ์šฉ๋ฅ **์€ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํฌ๊ฒŒ **๋ณ€๋™**ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, **๋ฉ”๋ชจ๋ฆฌ(RAM)**๋Š” ๋ณดํ†ต ๋Œ€์ฒด๋กœ **์•ˆ์ •์ **์œผ๋กœ ์œ ์ง€๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋งค๋ฒˆ ๋น„์Šทํ•œ ์–‘์˜ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” API์ด๊ณ  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งŽ๋‹ค๋ฉด, **CPU ์‚ฌ์šฉ๋ฅ **๋„ (๊ธ‰๊ฒฉํžˆ ์˜ค๋ฅด๋‚ด๋ฆฌ๊ธฐ๋ณด๋‹ค๋Š”) *์•ˆ์ •์ ์ผ* ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+### ๋ณต์ œ ๋„๊ตฌ์™€ ์ „๋žต ์˜ˆ์‹œ { #examples-of-replication-tools-and-strategies }
+
+์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ ์žฅ๋“ค์—์„œ Docker์™€ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์„ค๋ช…ํ•  ๋•Œ ๊ตฌ์ฒด์ ์ธ ์ „๋žต์„ ๋” ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๊ณ ๋ คํ•ด์•ผ ํ•  ์ฃผ์š” ์ œ์•ฝ์€ **๊ณต๊ฐœ IP**์˜ **ํฌํŠธ**๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” **๋‹จ์ผ** ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ณต์ œ๋œ **ํ”„๋กœ์„ธ์Šค/์›Œ์ปค**๋กœ ํ†ต์‹ ์„ **์ „๋‹ฌ**ํ•  ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ฐ€๋Šฅํ•œ ์กฐํ•ฉ๊ณผ ์ „๋žต ๋ช‡ ๊ฐ€์ง€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* `--workers` ์˜ต์…˜์„ ์‚ฌ์šฉํ•œ **Uvicorn**
+    * ํ•˜๋‚˜์˜ Uvicorn **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๊ฐ€ **IP**์™€ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•˜๊ณ , **์—ฌ๋Ÿฌ Uvicorn ์›Œ์ปค ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+* **Kubernetes** ๋ฐ ๊ธฐํƒ€ ๋ถ„์‚ฐ **์ปจํ…Œ์ด๋„ˆ ์‹œ์Šคํ…œ**
+    * **Kubernetes** ๋ ˆ์ด์–ด์˜ ๋ฌด์–ธ๊ฐ€๊ฐ€ **IP**์™€ **ํฌํŠธ**์—์„œ ๋ฆฌ์Šค๋‹ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  **์—ฌ๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ๋‘์–ด ๋ณต์ œํ•˜๋ฉฐ, ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—๋Š” **ํ•˜๋‚˜์˜ Uvicorn ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
+* ์ด๋ฅผ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” **ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค**
+    * ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๊ฐ€ **๋ณต์ œ๋ฅผ ๋Œ€์‹  ์ฒ˜๋ฆฌ**ํ•ด์ค„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ์‹คํ–‰ํ•  **ํ”„๋กœ์„ธ์Šค**๋‚˜ ์‚ฌ์šฉํ•  **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋ฅผ ์ •์˜ํ•˜๊ฒŒ ํ•ด์ค„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์–ด๋–ค ๊ฒฝ์šฐ๋“  ๋Œ€๊ฐœ **๋‹จ์ผ Uvicorn ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ณ , ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๊ฐ€ ์ด๋ฅผ ๋ณต์ œํ•˜๋Š” ์—ญํ• ์„ ๋งก์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+**์ปจํ…Œ์ด๋„ˆ**, Docker, Kubernetes์— ๋Œ€ํ•œ ์ผ๋ถ€ ๋‚ด์šฉ์ด ์•„์ง์€ ์ž˜ ์ดํ•ด๋˜์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ ์žฅ์—์„œ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€, Docker, Kubernetes ๋“ฑ์„ ๋” ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค: [์ปจํ…Œ์ด๋„ˆ์—์„œ FastAPI - Docker](docker.md){.internal-link target=_blank}.
+
+///
+
+## ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„ { #previous-steps-before-starting }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ **์‹œ์ž‘ํ•˜๊ธฐ ์ „์—** ์–ด๋–ค ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด **๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜**์„ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ์ด๋Ÿฐ ๋‹จ๊ณ„๋Š” **ํ•œ ๋ฒˆ๋งŒ** ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๊ทธ **์‚ฌ์ „ ๋‹จ๊ณ„**๋ฅผ ์ˆ˜ํ–‰ํ•  **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๋‘๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์ดํ›„์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž์ฒด๋ฅผ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**(์—ฌ๋Ÿฌ ์›Œ์ปค)๋กœ ์‹œ์ž‘ํ•˜๋”๋ผ๋„, ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” *๋ฐ˜๋“œ์‹œ* ํ•˜๋‚˜๋งŒ ์‹คํ–‰๋˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ **์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค**๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋ฉด, **๋ณ‘๋ ฌ๋กœ** ์‹คํ–‰ํ•˜๋ฉด์„œ ์ž‘์—…์ด **์ค‘๋ณต**๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ฒ˜๋Ÿผ ๋ฏผ๊ฐํ•œ ์ž‘์—…์ด๋ผ๋ฉด ์„œ๋กœ ์ถฉ๋Œ์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ฌผ๋ก  ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ฒ˜๋ฆฌํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+๋˜ํ•œ ์„ค์ •์— ๋”ฐ๋ผ, ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— **์‚ฌ์ „ ๋‹จ๊ณ„๊ฐ€ ์ „ํ˜€ ํ•„์š” ์—†์„** ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ์ „ํ˜€ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿคท
+
+///
+
+### ์‚ฌ์ „ ๋‹จ๊ณ„ ์ „๋žต ์˜ˆ์‹œ { #examples-of-previous-steps-strategies }
+
+์ด๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด **์‹œ์Šคํ…œ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ์‹**์— ํฌ๊ฒŒ ์ขŒ์šฐ๋˜๋ฉฐ, ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ์‹, ์žฌ์‹œ์ž‘ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ ๋“ฑ๊ณผ๋„ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+๊ฐ€๋Šฅํ•œ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์•ฑ ์ปจํ…Œ์ด๋„ˆ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜๋Š” Kubernetes์˜ โ€œInit Containerโ€
+* ์‚ฌ์ „ ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๋Š” bash ์Šคํฌ๋ฆฝํŠธ
+    * ์ด bash ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹œ์ž‘/์žฌ์‹œ์ž‘ํ•˜๊ณ , ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•๋„ ์—ฌ์ „ํžˆ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ปจํ…Œ์ด๋„ˆ๋กœ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ ์žฅ์—์„œ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค: [์ปจํ…Œ์ด๋„ˆ์—์„œ FastAPI - Docker](docker.md){.internal-link target=_blank}.
+
+///
+
+## ๋ฆฌ์†Œ์Šค ํ™œ์šฉ { #resource-utilization }
+
+์„œ๋ฒ„๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์†Œ๋น„ํ•˜๊ฑฐ๋‚˜ **ํ™œ์šฉ(utilize)**ํ•  ์ˆ˜ ์žˆ๋Š” **๋ฆฌ์†Œ์Šค**์ž…๋‹ˆ๋‹ค. CPU์˜ ๊ณ„์‚ฐ ์‹œ๊ฐ„๊ณผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ RAM ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋Œ€ํ‘œ์ ์ž…๋‹ˆ๋‹ค.
+
+์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค๋ฅผ ์–ผ๋งˆ๋‚˜ ์†Œ๋น„/ํ™œ์šฉํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? โ€œ๋งŽ์ง€ ์•Š๊ฒŒโ€๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” **ํฌ๋ž˜์‹œํ•˜์ง€ ์•Š๋Š” ์„ ์—์„œ ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์ด** ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+์„œ๋ฒ„ 3๋Œ€๋ฅผ ๋น„์šฉ์„ ๋‚ด๊ณ  ์“ฐ๊ณ  ์žˆ๋Š”๋ฐ RAM๊ณผ CPU๋ฅผ ์กฐ๊ธˆ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์•„๋งˆ **๋ˆ์„ ๋‚ญ๋น„**ํ•˜๊ณ  ๐Ÿ’ธ, **์„œ๋ฒ„ ์ „๋ ฅ๋„ ๋‚ญ๋น„**ํ•˜๊ณ  ๐ŸŒŽ, ๊ธฐํƒ€ ๋“ฑ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ๊ฒฝ์šฐ์—๋Š” ์„œ๋ฒ„๋ฅผ 2๋Œ€๋งŒ ๋‘๊ณ , ๊ฐ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค(CPU, ๋ฉ”๋ชจ๋ฆฌ, ๋””์Šคํฌ, ๋„คํŠธ์›Œํฌ ๋Œ€์—ญํญ ๋“ฑ)๋ฅผ ๋” ๋†’์€ ๋น„์œจ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ฐ˜๋Œ€๋กœ ์„œ๋ฒ„ 2๋Œ€๋ฅผ ๋‘๊ณ  CPU์™€ RAM์„ **100%** ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์–ด๋А ์‹œ์ ์— ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๊ฐ€ ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋˜๊ณ , ์„œ๋ฒ„๋Š” ๋””์Šคํฌ๋ฅผ โ€œ๋ฉ”๋ชจ๋ฆฌโ€์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค(์ˆ˜์ฒœ ๋ฐฐ ๋А๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). ๋˜๋Š” ์‹ฌ์ง€์–ด **ํฌ๋ž˜์‹œ**ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ ์–ด๋–ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณ„์‚ฐ์„ ํ•ด์•ผ ํ•˜๋Š”๋ฐ CPU๊ฐ€ ๋‹ค์‹œ ๋น„์›Œ์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ์—๋Š” **์„œ๋ฒ„ ํ•œ ๋Œ€๋ฅผ ์ถ”๊ฐ€**๋กœ ํ™•๋ณดํ•˜๊ณ  ์ผ๋ถ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ทธ์ชฝ์—์„œ ์‹คํ–‰ํ•ด, ๋ชจ๋‘๊ฐ€ **์ถฉ๋ถ„ํ•œ RAM๊ณผ CPU ์‹œ๊ฐ„**์„ ๊ฐ–๋„๋ก ํ•˜๋Š” ํŽธ์ด ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค.
+
+๋˜ ์–ด๋–ค ์ด์œ ๋กœ API ์‚ฌ์šฉ๋Ÿ‰์ด **๊ธ‰์ฆ(spike)**ํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”์ด๋Ÿด์ด ๋˜์—ˆ๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ์„œ๋น„์Šค๋‚˜ ๋ด‡์ด ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™•๋ณดํ•ด๋‘๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ฆฌ์†Œ์Šค ํ™œ์šฉ๋ฅ  ๋ชฉํ‘œ๋กœ **์ž„์˜์˜ ์ˆ˜์น˜**๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด **50%์—์„œ 90% ์‚ฌ์ด**์ฒ˜๋Ÿผ์š”. ์š”์ ์€, ์ด๋Ÿฐ ๊ฒƒ๋“ค์ด ๋ฐฐํฌ๋ฅผ ์กฐ์ •ํ•  ๋•Œ ์ธก์ •ํ•˜๊ณ  ํŠœ๋‹ํ•˜๋Š” ์ฃผ์š” ์ง€ํ‘œ๊ฐ€ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+`htop` ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๋„๊ตฌ๋กœ ์„œ๋ฒ„์˜ CPU์™€ RAM ์‚ฌ์šฉ๋Ÿ‰, ๋˜๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค๋ณ„ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜น์€ ์„œ๋ฒ„ ์—ฌ๋Ÿฌ ๋Œ€์— ๋ถ„์‚ฐ๋  ์ˆ˜๋„ ์žˆ๋Š” ๋” ๋ณต์žกํ•œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## ์š”์•ฝ { #recap }
+
+์—ฌ๊ธฐ๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ์ฃผ์š” ๊ฐœ๋…๋“ค์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค:
+
+* ๋ณด์•ˆ - HTTPS
+* ์‹œ์ž‘ ์‹œ ์‹คํ–‰
+* ์žฌ์‹œ์ž‘
+* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜)
+* ๋ฉ”๋ชจ๋ฆฌ
+* ์‹œ์ž‘ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„
+
+์ด ์•„์ด๋””์–ด๋“ค์„ ์ดํ•ดํ•˜๊ณ  ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ฉด, ๋ฐฐํฌ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์กฐ์ •ํ•  ๋•Œ ํ•„์š”ํ•œ ์ง๊ด€์„ ์–ป๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿค“
+
+๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๋”ฐ๋ผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ์ „๋žต์˜ ๋” ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿš€
diff --git a/docs/ko/docs/deployment/fastapicloud.md b/docs/ko/docs/deployment/fastapicloud.md
new file mode 100644 (file)
index 0000000..9a830b1
--- /dev/null
@@ -0,0 +1,65 @@
+# FastAPI Cloud { #fastapi-cloud }
+
+**ํ•œ ๋ฒˆ์˜ ๋ช…๋ น**์œผ๋กœ FastAPI ์•ฑ์„ <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>์— ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ง์ด๋ผ๋ฉด ๋Œ€๊ธฐ์ž ๋ช…๋‹จ์— ๋“ฑ๋กํ•ด ๋ณด์„ธ์š”. ๐Ÿš€
+
+## ๋กœ๊ทธ์ธํ•˜๊ธฐ { #login }
+
+๋จผ์ € **FastAPI Cloud** ๊ณ„์ •์ด ์ด๋ฏธ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”(๋Œ€๊ธฐ์ž ๋ช…๋‹จ์—์„œ ์ดˆ๋Œ€ํ•ด ๋“œ๋ ธ์„ ๊ฑฐ์˜ˆ์š” ๐Ÿ˜‰).
+
+๊ทธ๋‹ค์Œ ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ fastapi login
+
+You are logged in to FastAPI Cloud ๐Ÿš€
+```
+
+</div>
+
+## ๋ฐฐํฌํ•˜๊ธฐ { #deploy }
+
+์ด์ œ **ํ•œ ๋ฒˆ์˜ ๋ช…๋ น**์œผ๋กœ ์•ฑ์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ fastapi deploy
+
+Deploying to FastAPI Cloud...
+
+โœ… Deployment successful!
+
+๐Ÿ” Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
+```
+
+</div>
+
+์ด๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค! ์ด์ œ ํ•ด๋‹น URL์—์„œ ์•ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ
+
+## FastAPI Cloud ์†Œ๊ฐœ { #about-fastapi-cloud }
+
+**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**๋Š” **FastAPI**๋ฅผ ๋งŒ๋“  ๋™์ผํ•œ ์ €์ž์™€ ํŒ€์ด ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+์ตœ์†Œํ•œ์˜ ๋…ธ๋ ฅ์œผ๋กœ API๋ฅผ **๊ตฌ์ถ•**, **๋ฐฐํฌ**, **์ ‘๊ทผ**ํ•˜๋Š” ๊ณผ์ •์„ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.
+
+FastAPI๋กœ ์•ฑ์„ ๋งŒ๋“ค ๋•Œ์˜ ๋™์ผํ•œ **๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜**์„, ํด๋ผ์šฐ๋“œ์— **๋ฐฐํฌ**ํ•  ๋•Œ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐ŸŽ‰
+
+๋˜ํ•œ ์•ฑ์„ ๋ฐฐํฌํ•  ๋•Œ ๋ณดํ†ต ํ•„์š”ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒƒ๋“ค๋„ ์ฒ˜๋ฆฌํ•ด ์ค๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด:
+
+* HTTPS
+* ์š”์ฒญ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™ ์Šค์ผ€์ผ๋งํ•˜๋Š” ๋ณต์ œ(Replication)
+* ๋“ฑ
+
+FastAPI Cloud๋Š” *FastAPI and friends* ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ์Šคํฐ์„œ์ด์ž ์ž๊ธˆ ์ง€์› ์ œ๊ณต์ž์ž…๋‹ˆ๋‹ค. โœจ
+
+## ๋‹ค๋ฅธ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์— ๋ฐฐํฌํ•˜๊ธฐ { #deploy-to-other-cloud-providers }
+
+FastAPI๋Š” ์˜คํ”ˆ ์†Œ์Šค์ด๋ฉฐ ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ์–ด๋–ค ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์—๋„ FastAPI ์•ฑ์„ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•ด๋‹น ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด์˜ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ผ FastAPI ์•ฑ์„ ๋ฐฐํฌํ•˜์„ธ์š”. ๐Ÿค“
+
+## ์ž์ฒด ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜๊ธฐ { #deploy-your-own-server }
+
+๋˜ํ•œ ์ด **Deployment** ๊ฐ€์ด๋“œ์—์„œ ์ดํ›„์— ๋ชจ๋“  ์„ธ๋ถ€์‚ฌํ•ญ์„ ์•Œ๋ ค๋“œ๋ฆด ๊ฑฐ์˜ˆ์š”. ๊ทธ๋ž˜์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€, ๋ฌด์—‡์ด ํ•„์š”ํ•˜๋ฉฐ, ๋ณธ์ธ์˜ ์„œ๋ฒ„๋ฅผ ํฌํ•จํ•ด ์ง์ ‘ FastAPI ์•ฑ์„ ์–ด๋–ป๊ฒŒ ๋ฐฐํฌํ•˜๋Š”์ง€๊นŒ์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿค“
diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md
new file mode 100644 (file)
index 0000000..888ec61
--- /dev/null
@@ -0,0 +1,231 @@
+# HTTPS ์•Œ์•„๋ณด๊ธฐ { #about-https }
+
+HTTPS๋Š” ๊ทธ๋ƒฅ โ€œ์ผœ์ ธ ์žˆ๊ฑฐ๋‚˜โ€ ์•„๋‹ˆ๋ฉด โ€œ๊บผ์ ธ ์žˆ๋Š”โ€ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ›จ์”ฌ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+๋ฐ”์˜๊ฑฐ๋‚˜ ๋ณ„๋กœ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด, ๋‹ค์Œ ์„น์…˜์—์„œ ๋‹ค์–‘ํ•œ ๊ธฐ๋ฒ•์œผ๋กœ ๋ชจ๋“  ๊ฒƒ์„ ์„ค์ •ํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ์•ˆ๋‚ด๋ฅผ ๊ณ„์† ๋ณด์„ธ์š”.
+
+///
+
+์†Œ๋น„์ž ๊ด€์ ์—์„œ **HTTPS์˜ ๊ธฐ๋ณธ์„ ๋ฐฐ์šฐ๋ ค๋ฉด** <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
+
+์ด์ œ **๊ฐœ๋ฐœ์ž ๊ด€์ **์—์„œ HTTPS๋ฅผ ์ƒ๊ฐํ•  ๋•Œ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•  ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, **์„œ๋ฒ„**๊ฐ€ **์ œ3์ž**๊ฐ€ ๋ฐœ๊ธ‰ํ•œ **"์ธ์ฆ์„œ(certificates)"**๋ฅผ **๋ณด์œ **ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+    * ์ด ์ธ์ฆ์„œ๋Š” ์‹ค์ œ๋กœ ์ œ3์ž๊ฐ€ โ€œ์ƒ์„ฑโ€ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ œ3์ž๋กœ๋ถ€ํ„ฐ **๋ฐœ๊ธ‰/ํš๋“**ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+* ์ธ์ฆ์„œ์—๋Š” **์œ ํšจ ๊ธฐ๊ฐ„**์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+    * ์ฆ‰, **๋งŒ๋ฃŒ**๋ฉ๋‹ˆ๋‹ค.
+    * ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋ฉด ์ œ3์ž๋กœ๋ถ€ํ„ฐ ๋‹ค์‹œ **๊ฐฑ์‹ **ํ•ด์„œ **์žฌ๋ฐœ๊ธ‰/์žฌํš๋“**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+* ์—ฐ๊ฒฐ์˜ ์•”ํ˜ธํ™”๋Š” **TCP ๋ ˆ๋ฒจ**์—์„œ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.
+    * ์ด๋Š” **HTTP๋ณด๋‹ค ํ•œ ๊ณ„์ธต ์•„๋ž˜**์ž…๋‹ˆ๋‹ค.
+    * ๋”ฐ๋ผ์„œ **์ธ์ฆ์„œ์™€ ์•”ํ˜ธํ™”** ์ฒ˜๋ฆฌ๋Š” **HTTP ์ด์ „**์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
+* **TCP๋Š” "๋„๋ฉ”์ธ"์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.** IP ์ฃผ์†Œ๋งŒ ์••๋‹ˆ๋‹ค.
+    * ์–ด๋–ค **ํŠน์ • ๋„๋ฉ”์ธ**์„ ์š”์ฒญํ–ˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋Š” **HTTP ๋ฐ์ดํ„ฐ**์— ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+* **HTTPS ์ธ์ฆ์„œ**๋Š” ํŠน์ • **๋„๋ฉ”์ธ**์„ โ€œ์ธ์ฆโ€ํ•˜์ง€๋งŒ, ํ”„๋กœํ† ์ฝœ๊ณผ ์•”ํ˜ธํ™”๋Š” TCP ๋ ˆ๋ฒจ์—์„œ ์ผ์–ด๋‚˜๋ฉฐ, ์–ด๋–ค ๋„๋ฉ”์ธ์„ ๋‹ค๋ฃจ๋Š”์ง€ **์•Œ๊ธฐ ์ „์—** ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
+* **๊ธฐ๋ณธ์ ์œผ๋กœ** ์ด๋Š” 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>**๋ผ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+    * ์ด 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>**๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
+
+TLS Termination Proxy๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* Traefik (์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ)
+* Caddy (์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ)
+* Nginx
+* HAProxy
+
+## Let's Encrypt { #lets-encrypt }
+
+Let's Encrypt ์ด์ „์—๋Š” ์ด๋Ÿฌํ•œ **HTTPS ์ธ์ฆ์„œ**๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ œ3์ž์— ์˜ํ•ด ํŒ๋งค๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ธ์ฆ์„œ๋ฅผ ํš๋“ํ•˜๋Š” ๊ณผ์ •์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ , ๊ฝค ๋งŽ์€ ์„œ๋ฅ˜ ์ž‘์—…์ด ํ•„์š”ํ–ˆ์œผ๋ฉฐ, ์ธ์ฆ์„œ๋„ ์ƒ๋‹นํžˆ ๋น„์ŒŒ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๊ทธ ํ›„ **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>**๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” Linux Foundation์˜ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ํ‘œ์ค€ ์•”ํ˜ธํ•™์  ๋ณด์•ˆ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋Š” **HTTPS ์ธ์ฆ์„œ**๋ฅผ **๋ฌด๋ฃŒ๋กœ**, ์ž๋™ํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์ธ์ฆ์„œ๋“ค์€ ์ˆ˜๋ช…์ด ์งง๊ณ (์•ฝ 3๊ฐœ์›”) ๊ทธ๋ž˜์„œ ์œ ํšจ ๊ธฐ๊ฐ„์ด ์งง์€ ๋งŒํผ **์‹ค์ œ๋กœ ๋ณด์•ˆ์ด ๋” ์ข‹์•„์ง€๊ธฐ๋„** ํ•ฉ๋‹ˆ๋‹ค.
+
+๋„๋ฉ”์ธ์€ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฒ€์ฆ๋˜๋ฉฐ ์ธ์ฆ์„œ๋Š” ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด๋กœ ์ธํ•ด ์ธ์ฆ์„œ ๊ฐฑ์‹ ๋„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ชฉํ‘œ๋Š” ์ธ์ฆ์„œ์˜ ๋ฐœ๊ธ‰๊ณผ ๊ฐฑ์‹ ์„ ์ž๋™ํ™”ํ•˜์—ฌ **๋ฌด๋ฃŒ๋กœ, ์˜๊ตฌํžˆ, ์•ˆ์ „ํ•œ HTTPS**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+## ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ HTTPS { #https-for-developers }
+
+๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ค‘์š”ํ•œ ๊ฐœ๋…๋“ค์„ ์ค‘์‹ฌ์œผ๋กœ, HTTPS API๊ฐ€ ๋‹จ๊ณ„๋ณ„๋กœ ์–ด๋–ป๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+### ๋„๋ฉ”์ธ ์ด๋ฆ„ { #domain-name }
+
+์•„๋งˆ๋„ ์‹œ์ž‘์€ **๋„๋ฉ”์ธ ์ด๋ฆ„**์„ **ํš๋“**ํ•˜๋Š” ๊ฒƒ์ผ ๊ฒ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ DNS ์„œ๋ฒ„(์•„๋งˆ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ์ œ๊ณต์—…์ฒด)์—์„œ ์ด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+๋Œ€๊ฐœ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„(๊ฐ€์ƒ ๋จธ์‹ ) ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ณ , ๊ฑฐ๊ธฐ์—๋Š” <abbr title="That doesn't change - ๋ณ€ํ•˜์ง€ ์•Š์Œ">fixed</abbr> **๊ณต๊ฐœ IP ์ฃผ์†Œ**๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+DNS ์„œ๋ฒ„(๋“ค)์—์„œ **๋„๋ฉ”์ธ**์ด ์„œ๋ฒ„์˜ **๊ณต๊ฐœ IP ์ฃผ์†Œ**๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ ˆ์ฝ”๋“œ(โ€œ`A record`โ€)๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+๋ณดํ†ต์€ ์ฒ˜์Œ ํ•œ ๋ฒˆ, ๋ชจ๋“  ๊ฒƒ์„ ์„ค์ •ํ•  ๋•Œ๋งŒ ์ด ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+๋„๋ฉ”์ธ ์ด๋ฆ„ ๋ถ€๋ถ„์€ HTTPS๋ณด๋‹ค ํ›จ์”ฌ ์ด์ „ ๋‹จ๊ณ„์ง€๋งŒ, ๋ชจ๋“  ๊ฒƒ์ด ๋„๋ฉ”์ธ๊ณผ IP ์ฃผ์†Œ์— ์˜์กดํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+### DNS { #dns }
+
+์ด์ œ ์‹ค์ œ HTTPS ๋ถ€๋ถ„์— ์ง‘์ค‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๋จผ์ € ๋ธŒ๋ผ์šฐ์ €๋Š” **DNS ์„œ๋ฒ„**์— ์งˆ์˜ํ•˜์—ฌ, ์—ฌ๊ธฐ์„œ๋Š” `someapp.example.com`์ด๋ผ๋Š” **๋„๋ฉ”์ธ์— ๋Œ€ํ•œ IP**๊ฐ€ ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
+
+DNS ์„œ๋ฒ„๋Š” ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ํŠน์ • **IP ์ฃผ์†Œ**๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์ด๋Š” DNS ์„œ๋ฒ„์— ์„ค์ •ํ•ด ๋‘”, ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ณต๊ฐœ IP ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https01.drawio.svg">
+
+### TLS ํ•ธ๋“œ์…ฐ์ดํฌ ์‹œ์ž‘ { #tls-handshake-start }
+
+๊ทธ ๋‹ค์Œ ๋ธŒ๋ผ์šฐ์ €๋Š” **ํฌํŠธ 443**(HTTPS ํฌํŠธ)์—์„œ ํ•ด๋‹น IP ์ฃผ์†Œ์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ†ต์‹ ์˜ ์ฒซ ๋ถ€๋ถ„์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•˜๊ณ , ์‚ฌ์šฉํ•  ์•”ํ˜ธํ™” ํ‚ค ๋“ฑ์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https02.drawio.svg">
+
+ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ TLS ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ด ๊ณผ์ •์„ **TLS ํ•ธ๋“œ์…ฐ์ดํฌ**๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
+
+### SNI ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๋Š” TLS { #tls-with-sni-extension }
+
+์„œ๋ฒ„์—์„œ๋Š” ํŠน์ • **IP ์ฃผ์†Œ**์˜ ํŠน์ • **ํฌํŠธ**์—์„œ **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ** ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ IP ์ฃผ์†Œ์—์„œ ๋‹ค๋ฅธ ํฌํŠธ๋กœ ๋ฆฌ์Šค๋‹ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, IP ์ฃผ์†Œ์™€ ํฌํŠธ ์กฐํ•ฉ๋งˆ๋‹ค ํ•˜๋‚˜๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
+
+TLS(HTTPS)๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํŠน์ • ํฌํŠธ `443`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ํฌํŠธ๋Š” ์ด๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด ํฌํŠธ์—์„œ ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๊ทธ ์—ญํ• ์„ ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” **TLS Termination Proxy**๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
+
+TLS Termination Proxy๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ **TLS ์ธ์ฆ์„œ**(HTTPS ์ธ์ฆ์„œ)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์•ž์—์„œ ์„ค๋ช…ํ•œ **SNI ํ™•์žฅ**์„ ์‚ฌ์šฉํ•ด, TLS Termination Proxy๋Š” ์ด ์—ฐ๊ฒฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” TLS(HTTPS) ์ธ์ฆ์„œ๋“ค ์ค‘์—์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๋„๋ฉ”์ธ๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ์šฐ์—๋Š” `someapp.example.com`์— ๋Œ€ํ•œ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https03.drawio.svg">
+
+ํด๋ผ์ด์–ธํŠธ๋Š” ์ด๋ฏธ ํ•ด๋‹น TLS ์ธ์ฆ์„œ๋ฅผ ์ƒ์„ฑํ•œ ์ฃผ์ฒด(์—ฌ๊ธฐ์„œ๋Š” Let's Encrypt์ด์ง€๋งŒ, ์ด๋Š” ๋’ค์—์„œ ๋‹ค์‹œ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค)๋ฅผ **์‹ ๋ขฐ**ํ•˜๋ฏ€๋กœ, ์ธ์ฆ์„œ๊ฐ€ ์œ ํšจํ•œ์ง€ **๊ฒ€์ฆ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ด ํด๋ผ์ด์–ธํŠธ์™€ TLS Termination Proxy๋Š” ๋‚˜๋จธ์ง€ **TCP ํ†ต์‹ **์„ ์–ด๋–ป๊ฒŒ **์•”ํ˜ธํ™”ํ• ์ง€ ๊ฒฐ์ •**ํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ์จ **TLS ํ•ธ๋“œ์…ฐ์ดํฌ** ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
+
+์ดํ›„ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” TLS๊ฐ€ ์ œ๊ณตํ•˜๋Š” **์•”ํ˜ธํ™”๋œ TCP ์—ฐ๊ฒฐ**์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•ด ์‹ค์ œ **HTTP ํ†ต์‹ **์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์ด ๋ฐ”๋กœ **HTTPS**์ž…๋‹ˆ๋‹ค. ์ˆœ์ˆ˜(์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€) TCP ์—ฐ๊ฒฐ ๋Œ€์‹  **์•ˆ์ „ํ•œ TLS ์—ฐ๊ฒฐ** ์•ˆ์—์„œ **HTTP**๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+ํ†ต์‹ ์˜ ์•”ํ˜ธํ™”๋Š” HTTP ๋ ˆ๋ฒจ์ด ์•„๋‹ˆ๋ผ **TCP ๋ ˆ๋ฒจ**์—์„œ ์ผ์–ด๋‚œ๋‹ค๋Š” ์ ์— ์ฃผ์˜ํ•˜์„ธ์š”.
+
+///
+
+### HTTPS ์š”์ฒญ { #https-request }
+
+์ด์ œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„(๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ๋ธŒ๋ผ์šฐ์ €์™€ TLS Termination Proxy)๊ฐ€ **์•”ํ˜ธํ™”๋œ TCP ์—ฐ๊ฒฐ**์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ์œผ๋‹ˆ **HTTP ํ†ต์‹ **์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ํด๋ผ์ด์–ธํŠธ๋Š” **HTTPS ์š”์ฒญ**์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด๋Š” ์•”ํ˜ธํ™”๋œ TLS ์—ฐ๊ฒฐ์„ ํ†ตํ•ด ์ „๋‹ฌ๋˜๋Š” HTTP ์š”์ฒญ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https04.drawio.svg">
+
+### ์š”์ฒญ ๋ณตํ˜ธํ™” { #decrypt-the-request }
+
+TLS Termination Proxy๋Š” ํ•ฉ์˜๋œ ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•ด **์š”์ฒญ์„ ๋ณตํ˜ธํ™”**ํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค(์˜ˆ: FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” Uvicorn ํ”„๋กœ์„ธ์Šค)์— **์ผ๋ฐ˜(๋ณตํ˜ธํ™”๋œ) HTTP ์š”์ฒญ**์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https05.drawio.svg">
+
+### HTTP ์‘๋‹ต { #http-response }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  **์ผ๋ฐ˜(์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€) HTTP ์‘๋‹ต**์„ TLS Termination Proxy๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https06.drawio.svg">
+
+### HTTPS ์‘๋‹ต { #https-response }
+
+๊ทธ ๋‹ค์Œ TLS Termination Proxy๋Š” ์ด์ „์— ํ•ฉ์˜ํ•œ ์•”ํ˜ธํ™”( `someapp.example.com` ์ธ์ฆ์„œ๋กœ ์‹œ์ž‘๋œ ๊ฒƒ)๋ฅผ ์‚ฌ์šฉํ•ด **์‘๋‹ต์„ ์•”ํ˜ธํ™”**ํ•˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๋กœ ๋‹ค์‹œ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
+
+์ดํ›„ ๋ธŒ๋ผ์šฐ์ €๋Š” ์‘๋‹ต์ด ์œ ํšจํ•œ์ง€, ์˜ฌ๋ฐ”๋ฅธ ์•”ํ˜ธํ™” ํ‚ค๋กœ ์•”ํ˜ธํ™”๋˜์—ˆ๋Š”์ง€ ๋“ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ **์‘๋‹ต์„ ๋ณตํ˜ธํ™”**ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https07.drawio.svg">
+
+ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)๋Š” ์•ž์„œ **HTTPS ์ธ์ฆ์„œ**๋กœ ํ•ฉ์˜ํ•œ ์•”ํ˜ธํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ํ•ด๋‹น ์‘๋‹ต์ด ์˜ฌ๋ฐ”๋ฅธ ์„œ๋ฒ„์—์„œ ์™”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ { #multiple-applications }
+
+๊ฐ™์€ ์„œ๋ฒ„(๋˜๋Š” ์—ฌ๋Ÿฌ ์„œ๋ฒ„)์—๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ API ํ”„๋กœ๊ทธ๋žจ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ฒ˜๋Ÿผ **์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜**์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํŠน์ • IP์™€ ํฌํŠธ ์กฐํ•ฉ์€ ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(์˜ˆ์‹œ์—์„œ๋Š” TLS Termination Proxy), ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/ํ”„๋กœ์„ธ์Šค๋„ **๊ณต๊ฐœ IP์™€ ํฌํŠธ ์กฐํ•ฉ**์„ ๋™์ผํ•˜๊ฒŒ ์“ฐ๋ ค๊ณ ๋งŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์„œ๋ฒ„์—์„œ ํ•จ๊ป˜ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https08.drawio.svg">
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด TLS Termination Proxy๊ฐ€ **์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ**์— ๋Œ€ํ•œ HTTPS์™€ ์ธ์ฆ์„œ๋ฅผ **์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜**์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ ๊ฒฝ์šฐ์— ๋งž๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์ธ์ฆ์„œ ๊ฐฑ์‹  { #certificate-renewal }
+
+๋ฏธ๋ž˜์˜ ์–ด๋А ์‹œ์ ์—๋Š” ๊ฐ ์ธ์ฆ์„œ๊ฐ€ **๋งŒ๋ฃŒ**๋ฉ๋‹ˆ๋‹ค(ํš๋“ ํ›„ ์•ฝ 3๊ฐœ์›”).
+
+๊ทธ ๋‹ค์Œ์—๋Š” ๋˜ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ(๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋ณ„๋„ ํ”„๋กœ๊ทธ๋žจ์ผ ์ˆ˜๋„ ์žˆ๊ณ , ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๊ฐ™์€ TLS Termination Proxy์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค)์ด Let's Encrypt์™€ ํ†ต์‹ ํ•˜์—ฌ ์ธ์ฆ์„œ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
+
+<img src="/img/deployment/https/https.drawio.svg">
+
+**TLS ์ธ์ฆ์„œ**๋Š” IP ์ฃผ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ **๋„๋ฉ”์ธ ์ด๋ฆ„**๊ณผ **์—ฐ๊ฒฐ**๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์ธ์ฆ์„œ๋ฅผ ๊ฐฑ์‹ ํ•˜๋ ค๋ฉด, ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์ด ๊ถŒํ•œ ๊ธฐ๊ด€(Let's Encrypt)์—๊ฒŒ ํ•ด๋‹น ๋„๋ฉ”์ธ์„ ์‹ค์ œ๋กœ **โ€œ์†Œ์œ โ€ํ•˜๊ณ  ์ œ์–ดํ•˜๊ณ  ์žˆ์Œ**์„ **์ฆ๋ช…**ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์œ„ํ•ด, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์–‘ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”๊ตฌ๋ฅผ ์ˆ˜์šฉํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋„๋ฆฌ ์“ฐ์ด๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* **์ผ๋ถ€ DNS ๋ ˆ์ฝ”๋“œ ์ˆ˜์ •**.
+    * ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์ด DNS ์ œ๊ณต์—…์ฒด์˜ API๋ฅผ ์ง€์›ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์‚ฌ์šฉํ•˜๋Š” DNS ์ œ๊ณต์—…์ฒด์— ๋”ฐ๋ผ ๊ฐ€๋Šฅํ•  ์ˆ˜๋„, ์•„๋‹ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+* ๋„๋ฉ”์ธ๊ณผ ์—ฐ๊ฒฐ๋œ ๊ณต๊ฐœ IP ์ฃผ์†Œ์—์„œ **์„œ๋ฒ„๋กœ ์‹คํ–‰**(์ ์–ด๋„ ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ ๊ณผ์ • ๋™์•ˆ).
+    * ์•ž์—์„œ ๋งํ–ˆ๋“ฏ ํŠน์ • IP์™€ ํฌํŠธ์—์„œ๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋ฆฌ์Šค๋‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+    * ์ด๊ฒƒ์ด ๋™์ผํ•œ TLS Termination Proxy๊ฐ€ ์ธ์ฆ์„œ ๊ฐฑ์‹  ๊ณผ์ •๊นŒ์ง€ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•œ ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
+    * ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด TLS Termination Proxy๋ฅผ ์ž ์‹œ ์ค‘์ง€ํ•˜๊ณ , ๊ฐฑ์‹  ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•ด ์ธ์ฆ์„œ๋ฅผ ํš๋“ํ•œ ๋‹ค์Œ, TLS Termination Proxy์— ์ธ์ฆ์„œ๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋‹ค์‹œ TLS Termination Proxy๋ฅผ ์žฌ์‹œ์ž‘ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” TLS Termination Proxy๊ฐ€ ๊บผ์ ธ ์žˆ๋Š” ๋™์•ˆ ์•ฑ(๋“ค)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์•ฑ์„ ๊ณ„์† ์ œ๊ณตํ•˜๋ฉด์„œ ์ด ๊ฐฑ์‹  ๊ณผ์ •์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„(์˜ˆ: Uvicorn)์—์„œ TLS ์ธ์ฆ์„œ๋ฅผ ์ง์ ‘ ์“ฐ๋Š” ๋Œ€์‹  TLS Termination Proxy๋กœ HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” **๋ณ„๋„์˜ ์‹œ์Šคํ…œ**์„ ๋‘๊ณ  ์‹ถ์–ด์ง€๋Š” ์ฃผ์š” ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
+
+## ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” { #proxy-forwarded-headers }
+
+ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•ด HTTPS๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**(์˜ˆ: FastAPI CLI๋ฅผ ํ†ตํ•œ Uvicorn)๋Š” HTTPS ๊ณผ์ •์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ์•Œ์ง€ ๋ชปํ•˜๊ณ  **TLS Termination Proxy**์™€๋Š” ์ผ๋ฐ˜ HTTP๋กœ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด **ํ”„๋ก์‹œ**๋Š” ๋ณดํ†ต ์š”์ฒญ์„ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, ์š”์ฒญ์ด ํ”„๋ก์‹œ์— ์˜ํ•ด **์ „๋‹ฌ(forwarded)**๋˜๊ณ  ์žˆ์Œ์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๊ฐ€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์ผ๋ถ€ HTTP ํ—ค๋”๋ฅผ ์ฆ‰์„์—์„œ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+ํ”„๋ก์‹œ ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* <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>
+
+///
+
+๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๋Š” ์ž์‹ ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” **ํ”„๋ก์‹œ** ๋’ค์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชจ๋ฅด๋ฏ€๋กœ, ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๊ทธ ํ—ค๋”๋“ค์„ ์‹ ๋ขฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๊ฐ€ **ํ”„๋ก์‹œ**๊ฐ€ ๋ณด๋‚ธ *forwarded* ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FastAPI CLI๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, *CLI Option* `--forwarded-allow-ips`๋ฅผ ์‚ฌ์šฉํ•ด ์–ด๋–ค IP์—์„œ ์˜จ *forwarded* ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ• ์ง€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด **์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„**๊ฐ€ ์‹ ๋ขฐํ•˜๋Š” **ํ”„๋ก์‹œ**๋กœ๋ถ€ํ„ฐ๋งŒ ํ†ต์‹ ์„ ๋ฐ›๋Š”๋‹ค๋ฉด, `--forwarded-allow-ips="*"`๋กœ ์„ค์ •ํ•ด ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  IP๋ฅผ ์‹ ๋ขฐํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด์ฐจํ”ผ **ํ”„๋ก์‹œ**๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” IP์—์„œ๋งŒ ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ž์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ณต๊ฐœ URL์ด ๋ฌด์—‡์ธ์ง€, HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€, ๋„๋ฉ”์ธ์ด ๋ฌด์—‡์ธ์ง€ ๋“ฑ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ด์— ๋Œ€ํ•ด์„œ๋Š” [ํ”„๋ก์‹œ ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ธฐ - ํ”„๋ก์‹œ ์ „๋‹ฌ ํ—ค๋” ํ™œ์„ฑํ™”](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} ๋ฌธ์„œ์—์„œ ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## ์š”์•ฝ { #recap }
+
+**HTTPS**๋Š” ๋งค์šฐ ์ค‘์š”ํ•˜๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ƒ๋‹นํžˆ **ํ•ต์‹ฌ์ **์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ HTTPS์™€ ๊ด€๋ จํ•ด ํ•ด์•ผ ํ•˜๋Š” ๋…ธ๋ ฅ์˜ ๋Œ€๋ถ€๋ถ„์€ ๊ฒฐ๊ตญ **์ด ๊ฐœ๋…๋“ค์„ ์ดํ•ด**ํ•˜๊ณ  ๊ทธ๊ฒƒ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ **๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ HTTPS**์˜ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ์•Œ๊ณ  ๋‚˜๋ฉด, ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•˜๊ณ  ์„ค์ •ํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ **HTTPS** ์„ค์ • ๋ฐฉ๋ฒ•์„ ์—ฌ๋Ÿฌ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋กœ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ”’
diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md
new file mode 100644 (file)
index 0000000..e85dd02
--- /dev/null
@@ -0,0 +1,157 @@
+# ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ { #run-a-server-manually }
+
+## `fastapi run` ๋ช…๋ น ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-fastapi-run-command }
+
+์š”์•ฝํ•˜๋ฉด, `fastapi run`์„ ์‚ฌ์šฉํ•ด FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น„์Šคํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
+
+  <span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span>  Starting production server ๐Ÿš€
+
+             Searching for package file structure from directories
+             with <font color="#3465A4">__init__.py</font> files
+             Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
+
+   <span style="background-color:#007166"><font color="#D3D7CF"> module </font></span>  ๐Ÿ main.py
+
+     <span style="background-color:#007166"><font color="#D3D7CF"> code </font></span>  Importing the FastAPI app object from the module with
+             the following code:
+
+             <u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
+
+      <span style="background-color:#007166"><font color="#D3D7CF"> app </font></span>  Using import string: <font color="#3465A4">main:app</font>
+
+   <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span>  Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font>
+   <span style="background-color:#007166"><font color="#D3D7CF"> server </font></span>  Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000/docs</u></font>
+
+             Logs:
+
+     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Started server process <b>[</b><font color="#34E2E2"><b>2306215</b></font><b>]</b>
+     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Waiting for application startup.
+     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Application startup complete.
+     <span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span>  Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font> <b>(</b>Press CTRL+C
+             to quit<b>)</b>
+```
+
+</div>
+
+๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” ์ด๊ฒƒ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜Ž
+
+์˜ˆ๋ฅผ ๋“ค์–ด ์ด ๋ช…๋ น์€ ์ปจํ…Œ์ด๋„ˆ๋‚˜ ์„œ๋ฒ„ ๋“ฑ์—์„œ **FastAPI** ์•ฑ์„ ์‹œ์ž‘ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## ASGI ์„œ๋ฒ„ { #asgi-servers }
+
+์ด์ œ ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+FastAPI๋Š” <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”, Python ์›น ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. FastAPI๋Š” ASGI ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.
+
+์›๊ฒฉ ์„œ๋ฒ„ ๋จธ์‹ ์—์„œ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(๋˜๋Š” ๋‹ค๋ฅธ ASGI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜)์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํ•ต์‹ฌ ์š”์†Œ๋Š” **Uvicorn** ๊ฐ™์€ ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. `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์€ ๊ฐ€๋ณ๊ณ  ๋‹ค์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋Ÿฐํƒ€์ž„์ž…๋‹ˆ๋‹ค.
+
+## ์„œ๋ฒ„ ๋จธ์‹ ๊ณผ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ { #server-machine-and-server-program }
+
+์ด๋ฆ„์— ๊ด€ํ•ด ๊ธฐ์–ตํ•ด ๋‘˜ ์ž‘์€ ๋””ํ…Œ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’ก
+
+"**server**"๋ผ๋Š” ๋‹จ์–ด๋Š” ๋ณดํ†ต ์›๊ฒฉ/ํด๋ผ์šฐ๋“œ ์ปดํ“จํ„ฐ(๋ฌผ๋ฆฌ ๋˜๋Š” ๊ฐ€์ƒ ๋จธ์‹ )์™€, ๊ทธ ๋จธ์‹ ์—์„œ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn) ๋‘˜ ๋‹ค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+์ผ๋ฐ˜์ ์œผ๋กœ "server"๋ฅผ ์ฝ์„ ๋•Œ, ์ด ๋‘ ๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”.
+
+์›๊ฒฉ ๋จธ์‹ ์„ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ๋Š” **server**๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด์ง€๋งŒ, **machine**, **VM**(virtual machine), **node**๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ ๋ณดํ†ต Linux๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์›๊ฒฉ ๋จธ์‹ ์˜ ํ•œ ํ˜•ํƒœ๋ฅผ ๋œปํ•˜๋ฉฐ, ๊ทธ๊ณณ์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
+
+## ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์„ค์น˜ํ•˜๊ธฐ { #install-the-server-program }
+
+FastAPI๋ฅผ ์„ค์น˜ํ•˜๋ฉด ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์ธ Uvicorn์ด ํ•จ๊ป˜ ์„ค์น˜๋˜๋ฉฐ, `fastapi run` ๋ช…๋ น์œผ๋กœ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ASGI ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+[๊ฐ€์ƒ ํ™˜๊ฒฝ](../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, ์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค์น˜ํ•˜์„ธ์š”.
+
+์˜ˆ๋ฅผ ๋“ค์–ด Uvicorn์„ ์„ค์น˜ํ•˜๋ ค๋ฉด:
+
+<div class="termy">
+
+```console
+$ pip install "uvicorn[standard]"
+
+---> 100%
+```
+
+</div>
+
+๋‹ค๋ฅธ ์–ด๋–ค ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ๋„ ๋น„์Šทํ•œ ๊ณผ์ •์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+`standard`๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด Uvicorn์ด ๊ถŒ์žฅ๋˜๋Š” ์ถ”๊ฐ€ ์˜์กด์„ฑ ๋ช‡ ๊ฐ€์ง€๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” `asyncio`๋ฅผ ๊ณ ์„ฑ๋Šฅ์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๋“œ๋กญ์ธ ๋Œ€์ฒด์žฌ์ธ `uvloop`๊ฐ€ ํฌํ•จ๋˜๋ฉฐ, ํฐ ๋™์‹œ์„ฑ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+`pip install "fastapi[standard]"` ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ FastAPI๋ฅผ ์„ค์น˜ํ•˜๋ฉด `uvicorn[standard]`๋„ ํ•จ๊ป˜ ์„ค์น˜๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ํ•˜๊ธฐ { #run-the-server-program }
+
+ASGI ์„œ๋ฒ„๋ฅผ ์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ–ˆ๋‹ค๋ฉด, ๋ณดํ†ต FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž„ํฌํŠธํ•˜๊ธฐ ์œ„ํ•ด ํŠน๋ณ„ํ•œ ํ˜•์‹์˜ import string์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
+
+<div class="termy">
+
+```console
+$ uvicorn main:app --host 0.0.0.0 --port 80
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
+```
+
+</div>
+
+/// note | ์ฐธ๊ณ 
+
+`uvicorn main:app` ๋ช…๋ น์€ ๋‹ค์Œ์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค:
+
+* `main`: ํŒŒ์ผ `main.py`(Python "module").
+* `app`: `main.py` ์•ˆ์—์„œ `app = FastAPI()` ๋ผ์ธ์œผ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด.
+
+์ด๋Š” ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค:
+
+```Python
+from main import app
+```
+
+///
+
+๊ฐ ASGI ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์˜ ๋Œ€์•ˆ๋„ ๋น„์Šทํ•œ ๋ช…๋ น์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ฐ์ž์˜ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
+
+/// warning | ๊ฒฝ๊ณ 
+
+Uvicorn๊ณผ ๋‹ค๋ฅธ ์„œ๋ฒ„๋Š” ๊ฐœ๋ฐœ ์ค‘์— ์œ ์šฉํ•œ `--reload` ์˜ต์…˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
+
+`--reload` ์˜ต์…˜์€ ํ›จ์”ฌ ๋” ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์†Œ๋น„ํ•˜๊ณ , ๋” ๋ถˆ์•ˆ์ •ํ•ฉ๋‹ˆ๋‹ค.
+
+**๊ฐœ๋ฐœ** ์ค‘์—๋Š” ํฐ ๋„์›€์ด ๋˜์ง€๋งŒ, **ํ”„๋กœ๋•์…˜**์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ **๋ง์•„์•ผ** ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ๋ฐฐํฌ ๊ฐœ๋… { #deployment-concepts }
+
+์ด ์˜ˆ์ œ๋“ค์€ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: Uvicorn)์„ ์‹คํ–‰ํ•˜์—ฌ **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹œ์ž‘ํ•˜๊ณ , ์‚ฌ์ „์— ์ •ํ•œ ํฌํŠธ(์˜ˆ: `80`)์—์„œ ๋ชจ๋“  IP(`0.0.0.0`)๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ๋ฐ›๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์ด ๊ธฐ๋ณธ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณดํ†ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถ”๊ฐ€ ์‚ฌํ•ญ๋“ค๋„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
+
+* ๋ณด์•ˆ - HTTPS
+* ์‹œ์ž‘ ์‹œ ์ž๋™ ์‹คํ–‰
+* ์žฌ์‹œ์ž‘
+* ๋ณต์ œ(์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์ˆ˜)
+* ๋ฉ”๋ชจ๋ฆฌ
+* ์‹œ์ž‘ ์ „ ์„ ํ–‰ ๋‹จ๊ณ„
+
+๋‹ค์Œ ์žฅ๋“ค์—์„œ ์ด ๊ฐ๊ฐ์˜ ๊ฐœ๋…์„ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•ด์•ผ ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์ „๋žต์˜ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋” ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿš€
diff --git a/docs/ko/docs/how-to/authentication-error-status-code.md b/docs/ko/docs/how-to/authentication-error-status-code.md
new file mode 100644 (file)
index 0000000..47120ca
--- /dev/null
@@ -0,0 +1,17 @@
+# ์ด์ „ 403 ์ธ์ฆ ์˜ค๋ฅ˜ ์ƒํƒœ ์ฝ”๋“œ ์‚ฌ์šฉํ•˜๊ธฐ { #use-old-403-authentication-error-status-codes }
+
+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` ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์–ด๋–ค ์ด์œ ๋กœ๋“  ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด์ „ ๋™์ž‘์— ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋ณด์•ˆ ํด๋ž˜์Šค์—์„œ `make_not_authenticated_error` ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์ด์ „ ๋™์ž‘์œผ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ๋ณธ๊ฐ’์ธ `401 Unauthorized` ์˜ค๋ฅ˜ ๋Œ€์‹  `403 Forbidden` ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” `HTTPBearer`์˜ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
+
+/// tip | ํŒ
+
+ํ•จ์ˆ˜๋Š” ์˜ˆ์™ธ๋ฅผ `raise`ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์˜ˆ์™ธ ์ธ์Šคํ„ด์Šค๋ฅผ `return`ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š”(`raise`) ์ž‘์—…์€ ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
+
+///
diff --git a/docs/ko/docs/how-to/custom-docs-ui-assets.md b/docs/ko/docs/how-to/custom-docs-ui-assets.md
new file mode 100644 (file)
index 0000000..d6383c2
--- /dev/null
@@ -0,0 +1,185 @@
+# ์ปค์Šคํ…€ Docs UI ์ •์  ์—์…‹(์ž์ฒด ํ˜ธ์ŠคํŒ…) { #custom-docs-ui-static-assets-self-hosting }
+
+API ๋ฌธ์„œ๋Š” **Swagger UI**์™€ **ReDoc**์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๊ฐ๊ฐ JavaScript์™€ CSS ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ํŒŒ์ผ์€ <abbr title="Content Delivery Network - ์ฝ˜ํ…์ธ  ์ „์†ก ๋„คํŠธ์›Œํฌ: ์ผ๋ฐ˜์ ์œผ๋กœ ์—ฌ๋Ÿฌ ์„œ๋ฒ„๋กœ ๊ตฌ์„ฑ๋˜์–ด JavaScript์™€ CSS ๊ฐ™์€ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต ํด๋ผ์ด์–ธํŠธ์— ๋” ๊ฐ€๊นŒ์šด ์„œ๋ฒ„์—์„œ ํŒŒ์ผ์„ ์ œ๊ณตํ•ด ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.">CDN</abbr>์—์„œ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠน์ • CDN์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ํŒŒ์ผ์„ ์ง์ ‘ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## JavaScript์™€ CSS์šฉ ์ปค์Šคํ…€ CDN { #custom-cdn-for-javascript-and-css }
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ <abbr title="Content Delivery Network">CDN</abbr>์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด `https://unpkg.com/`์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
+
+์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ๊ตญ๊ฐ€์—์„œ ์ผ๋ถ€ URL์„ ์ œํ•œํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์ž๋™ ๋ฌธ์„œ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-the-automatic-docs }
+
+์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ์ž๋™ ๋ฌธ์„œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž๋™ ๋ฌธ์„œ๋Š” ๊ธฐ๋ณธ CDN์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”:
+
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
+
+### ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs }
+
+์ด์ œ ์ปค์Šคํ…€ ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+FastAPI ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์šฉ HTML ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* `openapi_url`: ๋ฌธ์„œ HTML ํŽ˜์ด์ง€๊ฐ€ API์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” `app.openapi_url` ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `title`: API์˜ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.
+* `oauth2_redirect_url`: ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์„œ `app.swagger_ui_oauth2_redirect_url`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `swagger_js_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **JavaScript** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์ปค์Šคํ…€ CDN URL์ž…๋‹ˆ๋‹ค.
+* `swagger_css_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **CSS** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์ปค์Šคํ…€ CDN URL์ž…๋‹ˆ๋‹ค.
+
+ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค...
+
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
+
+/// tip | ํŒ
+
+`swagger_ui_redirect`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋„์›€์ด ๋˜๋Š” ํ—ฌํผ์ž…๋‹ˆ๋‹ค.
+
+API๋ฅผ OAuth2 provider์™€ ํ†ตํ•ฉํ•˜๋ฉด ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค ํš๋“ํ•œ ์ž๊ฒฉ ์ฆ๋ช…์œผ๋กœ API ๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ OAuth2 ์ธ์ฆ์„ ์‚ฌ์šฉํ•ด API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์œ„ํ•ด ์ด "redirect" ํ—ฌํผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### ํ…Œ์ŠคํŠธ์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋งŒ๋“ค๊ธฐ { #create-a-path-operation-to-test-it }
+
+์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”:
+
+{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
+
+### ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #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์—์„œ ์—์…‹์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## ๋ฌธ์„œ์šฉ JavaScript์™€ CSS ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๊ธฐ { #self-hosting-javascript-and-css-for-docs }
+
+JavaScript์™€ CSS๋ฅผ ์ž์ฒด ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜คํ”„๋ผ์ธ ์ƒํƒœ์ด๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์ธํ„ฐ๋„ท์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ํ™˜๊ฒฝ, ๋˜๋Š” ๋กœ์ปฌ ๋„คํŠธ์›Œํฌ์—์„œ๋„ ์•ฑ์ด ๊ณ„์† ๋™์ž‘ํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์„œ๋Š” ๋™์ผํ•œ FastAPI ์•ฑ์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ ์ง์ ‘ ์ œ๊ณตํ•˜๊ณ , ๋ฌธ์„œ๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค.
+
+### ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ { #project-file-structure }
+
+ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค:
+
+```
+.
+โ”œโ”€โ”€ app
+โ”‚   โ”œโ”€โ”€ __init__.py
+โ”‚   โ”œโ”€โ”€ main.py
+```
+
+์ด์ œ ํ•ด๋‹น ์ •์  ํŒŒ์ผ์„ ์ €์žฅํ•  ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“œ์„ธ์š”.
+
+์ƒˆ ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```
+.
+โ”œโ”€โ”€ app
+โ”‚ย ย  โ”œโ”€โ”€ __init__.py
+โ”‚ย ย  โ”œโ”€โ”€ main.py
+โ””โ”€โ”€ static/
+```
+
+### ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œํ•˜๊ธฐ { #download-the-files }
+
+๋ฌธ์„œ์— ํ•„์š”ํ•œ ์ •์  ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•ด์„œ `static/` ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋„ฃ์œผ์„ธ์š”.
+
+๊ฐ ๋งํฌ๋ฅผ ์šฐํด๋ฆญํ•œ ๋’ค "๋งํฌ๋ฅผ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์ €์žฅ..."๊ณผ ๋น„์Šทํ•œ ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+**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>
+
+**ReDoc**์€ ๋‹ค์Œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+* <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
+
+์ดํ›„ ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```
+.
+โ”œโ”€โ”€ app
+โ”‚ย ย  โ”œโ”€โ”€ __init__.py
+โ”‚ย ย  โ”œโ”€โ”€ main.py
+โ””โ”€โ”€ static
+    โ”œโ”€โ”€ redoc.standalone.js
+    โ”œโ”€โ”€ swagger-ui-bundle.js
+    โ””โ”€โ”€ swagger-ui.css
+```
+
+### ์ •์  ํŒŒ์ผ ์ œ๊ณตํ•˜๊ธฐ { #serve-the-static-files }
+
+* `StaticFiles`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค.
+* ํŠน์ • ๊ฒฝ๋กœ์— `StaticFiles()` ์ธ์Šคํ„ด์Šค๋ฅผ "๋งˆ์šดํŠธ(mount)"ํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
+
+### ์ •์  ํŒŒ์ผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #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>๋กœ ์ด๋™ํ•˜์„ธ์š”.
+
+**ReDoc**์šฉ ๋งค์šฐ ๊ธด JavaScript ํŒŒ์ผ์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```JavaScript
+/*! For license information please see redoc.standalone.js.LICENSE.txt */
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
+...
+```
+
+์ด๋Š” ์•ฑ์—์„œ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฌธ์„œ์šฉ ์ •์  ํŒŒ์ผ์„ ์˜ฌ๋ฐ”๋ฅธ ์œ„์น˜์— ๋ฐฐ์น˜ํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•ด ์ค๋‹ˆ๋‹ค.
+
+์ด์ œ ๋ฌธ์„œ๊ฐ€ ์ด ์ •์  ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์•ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์ •์  ํŒŒ์ผ์„ ์œ„ํ•œ ์ž๋™ ๋ฌธ์„œ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ { #disable-the-automatic-docs-for-static-files }
+
+์ปค์Šคํ…€ CDN์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์ฒซ ๋‹จ๊ณ„๋Š” ์ž๋™ ๋ฌธ์„œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž๋™ ๋ฌธ์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ CDN์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด `FastAPI` ์•ฑ์„ ์ƒ์„ฑํ•  ๋•Œ ํ•ด๋‹น URL์„ `None`์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”:
+
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
+
+### ์ •์  ํŒŒ์ผ์„ ์œ„ํ•œ ์ปค์Šคํ…€ ๋ฌธ์„œ ํฌํ•จํ•˜๊ธฐ { #include-the-custom-docs-for-static-files }
+
+๊ทธ๋ฆฌ๊ณ  ์ปค์Šคํ…€ CDN์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ, ์ด์ œ ์ปค์Šคํ…€ ๋ฌธ์„œ๋ฅผ ์œ„ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋‹ค์‹œ ํ•œ ๋ฒˆ, FastAPI ๋‚ด๋ถ€ ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•ด ๋ฌธ์„œ์šฉ HTML ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* `openapi_url`: ๋ฌธ์„œ HTML ํŽ˜์ด์ง€๊ฐ€ API์˜ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” `app.openapi_url` ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `title`: API์˜ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.
+* `oauth2_redirect_url`: ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ์„œ `app.swagger_ui_oauth2_redirect_url`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* `swagger_js_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **JavaScript** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. **์ด์ œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค**.
+* `swagger_css_url`: Swagger UI ๋ฌธ์„œ์˜ HTML์ด **CSS** ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” URL์ž…๋‹ˆ๋‹ค. **์ด์ œ๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์ด ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค**.
+
+ReDoc๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค...
+
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
+
+/// tip | ํŒ
+
+`swagger_ui_redirect`์— ๋Œ€ํ•œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋Š” OAuth2๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋„์›€์ด ๋˜๋Š” ํ—ฌํผ์ž…๋‹ˆ๋‹ค.
+
+API๋ฅผ OAuth2 provider์™€ ํ†ตํ•ฉํ•˜๋ฉด ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค ํš๋“ํ•œ ์ž๊ฒฉ ์ฆ๋ช…์œผ๋กœ API ๋ฌธ์„œ๋กœ ๋‹ค์‹œ ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ OAuth2 ์ธ์ฆ์„ ์‚ฌ์šฉํ•ด API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+Swagger UI๊ฐ€ ์ด ๊ณผ์ •์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•ด ์ฃผ์ง€๋งŒ, ์ด๋ฅผ ์œ„ํ•ด ์ด "redirect" ํ—ฌํผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+### ์ •์  ํŒŒ์ผ ํ…Œ์ŠคํŠธ์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ๋งŒ๋“ค๊ธฐ { #create-a-path-operation-to-test-static-files }
+
+์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“œ์„ธ์š”:
+
+{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
+
+### ์ •์  ํŒŒ์ผ 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>์—์„œ ๋ฌธ์„œ์— ์ ‘์†ํ•œ ๋’ค ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•ด ๋ณด์„ธ์š”.
+
+์ธํ„ฐ๋„ท์ด ์—†์–ด๋„ API ๋ฌธ์„œ๋ฅผ ๋ณด๊ณ , API์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/how-to/custom-request-and-route.md b/docs/ko/docs/how-to/custom-request-and-route.md
new file mode 100644 (file)
index 0000000..335193b
--- /dev/null
@@ -0,0 +1,109 @@
+# ์ปค์Šคํ…€ Request ๋ฐ APIRoute ํด๋ž˜์Šค { #custom-request-and-apiroute-class }
+
+์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” `Request`์™€ `APIRoute` ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋กœ์ง์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํŠนํžˆ, ์ด๋Š” middleware์— ์žˆ๋Š” ๋กœ์ง์˜ ์ข‹์€ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „์— ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค.
+
+/// danger | ์œ„ํ—˜
+
+์ด ๊ธฐ๋Šฅ์€ "๊ณ ๊ธ‰" ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
+
+**FastAPI**๋ฅผ ์ด์ œ ๋ง‰ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด ์ด ์„น์…˜์€ ๊ฑด๋„ˆ๋›ฐ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
+
+///
+
+## ์‚ฌ์šฉ ์‚ฌ๋ก€ { #use-cases }
+
+์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:
+
+* JSON์ด ์•„๋‹Œ ์š”์ฒญ ๋ฐ”๋””๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ(์˜ˆ: <a href="https://msgpack.org/index.html" class="external-link" target="_blank">`msgpack`</a>).
+* gzip์œผ๋กœ ์••์ถ•๋œ ์š”์ฒญ ๋ฐ”๋”” ์••์ถ• ํ•ด์ œํ•˜๊ธฐ.
+* ๋ชจ๋“  ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ž๋™์œผ๋กœ ๋กœ๊น…ํ•˜๊ธฐ.
+
+## ์ปค์Šคํ…€ ์š”์ฒญ ๋ฐ”๋”” ์ธ์ฝ”๋”ฉ ์ฒ˜๋ฆฌํ•˜๊ธฐ { #handling-custom-request-body-encodings }
+
+์ปค์Šคํ…€ `Request` ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด gzip ์š”์ฒญ์˜ ์••์ถ•์„ ํ•ด์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ปค์Šคํ…€ ์š”์ฒญ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ `APIRoute` ์„œ๋ธŒํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+### ์ปค์Šคํ…€ `GzipRequest` ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ { #create-a-custom-gziprequest-class }
+
+/// tip | ํŒ
+
+์ด ์˜ˆ์‹œ๋Š” ๋™์ž‘ ๋ฐฉ์‹ ์‹œ์—ฐ์„ ์œ„ํ•œ ์žฅ๋‚œ๊ฐ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. Gzip ์ง€์›์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์ œ๊ณต๋˜๋Š” [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank}๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+๋จผ์ €, `GzipRequest` ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” `Request.body()` ๋ฉ”์„œ๋“œ๋ฅผ ๋ฎ์–ด์จ์„œ, ์ ์ ˆํ•œ ํ—ค๋”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฐ”๋””๋ฅผ ์••์ถ• ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
+
+ํ—ค๋”์— `gzip`์ด ์—†์œผ๋ฉด ๋ฐ”๋””๋ฅผ ์••์ถ• ํ•ด์ œํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋™์ผํ•œ route ํด๋ž˜์Šค๊ฐ€ gzip์œผ๋กœ ์••์ถ•๋œ ์š”์ฒญ๊ณผ ์••์ถ•๋˜์ง€ ์•Š์€ ์š”์ฒญ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}
+
+### ์ปค์Šคํ…€ `GzipRoute` ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ { #create-a-custom-gziproute-class }
+
+๋‹ค์Œ์œผ๋กœ, `GzipRequest`๋ฅผ ํ™œ์šฉํ•˜๋Š” `fastapi.routing.APIRoute`์˜ ์ปค์Šคํ…€ ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
+
+์ด๋ฒˆ์—๋Š” `APIRoute.get_route_handler()` ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์š”์ฒญ์„ ๋ฐ›์•„ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์„œ๋Š” ์›๋ณธ ์š”์ฒญ์œผ๋กœ๋ถ€ํ„ฐ `GzipRequest`๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *}
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+`Request`์—๋Š” `request.scope` ์†์„ฑ์ด ์žˆ๋Š”๋ฐ, ์ด๋Š” ์š”์ฒญ๊ณผ ๊ด€๋ จ๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” Python `dict`์ž…๋‹ˆ๋‹ค.
+
+`Request`์—๋Š” ๋˜ํ•œ `request.receive`๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๋Š” ์š”์ฒญ์˜ ๋ฐ”๋””๋ฅผ "๋ฐ›๊ธฐ(receive)" ์œ„ํ•œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
+
+`scope` `dict`์™€ `receive` ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ ASGI ๋ช…์„ธ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ด ๋‘ ๊ฐ€์ง€, `scope`์™€ `receive`๊ฐ€ ์ƒˆ๋กœ์šด `Request` ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค.
+
+`Request`์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณด๋ ค๋ฉด <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">Starlette์˜ Requests ๋ฌธ์„œ</a>๋ฅผ ํ™•์ธํ•˜์„ธ์š”.
+
+///
+
+`GzipRequest.get_route_handler`๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ํ•˜๋Š” ์œ ์ผํ•œ ๊ฒƒ์€ `Request`๋ฅผ `GzipRequest`๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ์šฐ๋ฆฌ์˜ `GzipRequest`๊ฐ€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์ „์—(ํ•„์š”ํ•˜๋‹ค๋ฉด) ๋ฐ์ดํ„ฐ์˜ ์••์ถ• ํ•ด์ œ๋ฅผ ๋‹ด๋‹นํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ์ดํ›„์˜ ๋ชจ๋“  ์ฒ˜๋ฆฌ ๋กœ์ง์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `GzipRequest.body`์—์„œ ๋ณ€๊ฒฝ์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•„์š”ํ•  ๋•Œ **FastAPI**๊ฐ€ ๋กœ๋“œํ•˜๋Š” ์‹œ์ ์— ์š”์ฒญ ๋ฐ”๋””๋Š” ์ž๋™์œผ๋กœ ์••์ถ• ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.
+
+## ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์š”์ฒญ ๋ฐ”๋”” ์ ‘๊ทผํ•˜๊ธฐ { #accessing-the-request-body-in-an-exception-handler }
+
+/// tip | ํŒ
+
+๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด `RequestValidationError`์— ๋Œ€ํ•œ ์ปค์Šคํ…€ ํ•ธ๋“ค๋Ÿฌ์—์„œ `body`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์•„๋งˆ ํ›จ์”ฌ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค([์˜ค๋ฅ˜ ์ฒ˜๋ฆฌํ•˜๊ธฐ](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
+
+ํ•˜์ง€๋งŒ ์ด ์˜ˆ์‹œ๋„ ์—ฌ์ „ํžˆ ์œ ํšจํ•˜๋ฉฐ, ๋‚ด๋ถ€ ์ปดํฌ๋„ŒํŠธ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
+
+///
+
+๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์š”์ฒญ ๋ฐ”๋””์— ์ ‘๊ทผํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•„์š”ํ•œ ๊ฒƒ์€ `try`/`except` ๋ธ”๋ก ์•ˆ์—์„œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค:
+
+{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
+
+์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ `Request` ์ธ์Šคํ„ด์Šค๋Š” ์—ฌ์ „ํžˆ ์Šค์ฝ”ํ”„ ์•ˆ์— ๋‚จ์•„ ์žˆ์œผ๋ฏ€๋กœ, ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์š”์ฒญ ๋ฐ”๋””๋ฅผ ์ฝ๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}
+
+## ๋ผ์šฐํ„ฐ์—์„œ์˜ ์ปค์Šคํ…€ `APIRoute` ํด๋ž˜์Šค { #custom-apiroute-class-in-a-router }
+
+`APIRouter`์˜ `route_class` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” `router` ์•„๋ž˜์˜ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋“ค์ด ์ปค์Šคํ…€ `TimedRoute` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์‘๋‹ต์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„์„ ๋‹ด์€ ์ถ”๊ฐ€ `X-Response-Time` ํ—ค๋”๊ฐ€ ์‘๋‹ต์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}
diff --git a/docs/ko/docs/how-to/extending-openapi.md b/docs/ko/docs/how-to/extending-openapi.md
new file mode 100644 (file)
index 0000000..d04d6c2
--- /dev/null
@@ -0,0 +1,80 @@
+# OpenAPI ํ™•์žฅํ•˜๊ธฐ { #extending-openapi }
+
+์ƒ์„ฑ๋œ OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ์„น์…˜์—์„œ ๊ทธ ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ์ผ๋ฐ˜์ ์ธ ๊ณผ์ • { #the-normal-process }
+
+์ผ๋ฐ˜์ ์ธ(๊ธฐ๋ณธ) ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
+
+`FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์ธ์Šคํ„ด์Šค)์—๋Š” OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” `.openapi()` ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ `/openapi.json`(๋˜๋Š” `openapi_url`์— ์„ค์ •ํ•œ ๊ฒฝ๋กœ)์šฉ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.
+
+์ด ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ `.openapi()` ๋ฉ”์„œ๋“œ ๊ฒฐ๊ณผ๋ฅผ JSON ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.
+
+๊ธฐ๋ณธ์ ์œผ๋กœ `.openapi()` ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœํผํ‹ฐ `.openapi_schema`์— ๋‚ด์šฉ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์žˆ์œผ๋ฉด ๊ทธ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์—†์œผ๋ฉด `fastapi.openapi.utils.get_openapi`์— ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  `get_openapi()` ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค:
+
+* `title`: ๋ฌธ์„œ์— ํ‘œ์‹œ๋˜๋Š” OpenAPI ์ œ๋ชฉ.
+* `version`: API ๋ฒ„์ „. ์˜ˆ: `2.5.0`.
+* `openapi_version`: ์‚ฌ์šฉ๋˜๋Š” OpenAPI ์ŠคํŽ™ ๋ฒ„์ „. ๊ธฐ๋ณธ๊ฐ’์€ ์ตœ์‹ ์ธ `3.1.0`.
+* `summary`: API์— ๋Œ€ํ•œ ์งง์€ ์š”์•ฝ.
+* `description`: API ์„ค๋ช…. markdown์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฌธ์„œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+* `routes`: ๋ผ์šฐํŠธ ๋ชฉ๋ก. ๊ฐ๊ฐ ๋“ฑ๋ก๋œ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์ž…๋‹ˆ๋‹ค. `app.routes`์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+`summary` ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” OpenAPI 3.1.0 ์ด์ƒ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI 0.99.0 ์ด์ƒ์—์„œ ์ง€์›๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ๊ธฐ๋ณธ๊ฐ’ ๋ฎ์–ด์“ฐ๊ธฐ { #overriding-the-defaults }
+
+์œ„ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด 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>์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+### ์ผ๋ฐ˜์ ์ธ **FastAPI** { #normal-fastapi }
+
+๋จผ์ €, ํ‰์†Œ์ฒ˜๋Ÿผ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ชจ๋‘ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
+
+### OpenAPI ์Šคํ‚ค๋งˆ ์ƒ์„ฑํ•˜๊ธฐ { #generate-the-openapi-schema }
+
+๊ทธ๋‹ค์Œ `custom_openapi()` ํ•จ์ˆ˜ ์•ˆ์—์„œ, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
+
+### OpenAPI ์Šคํ‚ค๋งˆ ์ˆ˜์ •ํ•˜๊ธฐ { #modify-the-openapi-schema }
+
+์ด์ œ OpenAPI ์Šคํ‚ค๋งˆ์˜ `info` "object"์— ์ปค์Šคํ…€ `x-logo`๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ReDoc ํ™•์žฅ์„ ๋”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
+
+### OpenAPI ์Šคํ‚ค๋งˆ ์บ์‹œํ•˜๊ธฐ { #cache-the-openapi-schema }
+
+์ƒ์„ฑํ•œ ์Šคํ‚ค๋งˆ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ "cache"๋กœ `.openapi_schema` ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ API ๋ฌธ์„œ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์Šคํ‚ค๋งˆ๋ฅผ ๋งค๋ฒˆ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+์Šคํ‚ค๋งˆ๋Š” ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ๋˜๊ณ , ์ดํ›„ ์š”์ฒญ์—์„œ๋Š” ๊ฐ™์€ ์บ์‹œ๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
+
+### ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-method }
+
+์ด์ œ `.openapi()` ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ ํ•จ์ˆ˜๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
+
+### ํ™•์ธํ•˜๊ธฐ { #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** ๋กœ๊ณ )๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/extending-openapi/image01.png">
diff --git a/docs/ko/docs/how-to/general.md b/docs/ko/docs/how-to/general.md
new file mode 100644 (file)
index 0000000..a18dc68
--- /dev/null
@@ -0,0 +1,39 @@
+# ์ผ๋ฐ˜ - ์‚ฌ์šฉ ๋ฐฉ๋ฒ• - ๋ ˆ์‹œํ”ผ { #general-how-to-recipes }
+
+์ผ๋ฐ˜์ ์ด๊ฑฐ๋‚˜ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์งˆ๋ฌธ์— ๋Œ€ํ•ด, ๋ฌธ์„œ์˜ ๋‹ค๋ฅธ ์œ„์น˜๋กœ ์•ˆ๋‚ดํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํฌ์ธํ„ฐ๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.
+
+## ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง - ๋ณด์•ˆ { #filter-data-security }
+
+๋ฐ˜ํ™˜ํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณผ๋„ํ•˜๊ฒŒ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด, [ํŠœํ† ๋ฆฌ์–ผ - ์‘๋‹ต ๋ชจ๋ธ - ๋ฐ˜ํ™˜ ํƒ€์ž…](../tutorial/response-model.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## ๋ฌธ์„œํ™” ํƒœ๊ทธ - OpenAPI { #documentation-tags-openapi }
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฌธ์„œ UI์—์„œ ์ด๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ํƒœ๊ทธ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## ๋ฌธ์„œํ™” ์š”์•ฝ ๋ฐ ์„ค๋ช… - OpenAPI { #documentation-summary-and-description-openapi }
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ์š”์•ฝ๊ณผ ์„ค๋ช…์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๋ฌธ์„œ UI์— ํ‘œ์‹œํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์š”์•ฝ ๋ฐ ์„ค๋ช…](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## ๋ฌธ์„œํ™” ์‘๋‹ต ์„ค๋ช… - OpenAPI { #documentation-response-description-openapi }
+
+๋ฌธ์„œ UI์— ํ‘œ์‹œ๋˜๋Š” ์‘๋‹ต์˜ ์„ค๋ช…์„ ์ •์˜ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์‘๋‹ต ์„ค๋ช…](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## ๋ฌธ์„œํ™” *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ* ์ง€์› ์ค‘๋‹จํ•˜๊ธฐ - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ์ง€์› ์ค‘๋‹จ(deprecate)์œผ๋กœ ํ‘œ์‹œํ•˜๊ณ , ๋ฌธ์„œ UI์— ๋ณด์—ฌ์ฃผ๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ๊ตฌ์„ฑ - ์ง€์› ์ค‘๋‹จ](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## ์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  JSON ํ˜ธํ™˜์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ { #convert-any-data-to-json-compatible }
+
+์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  JSON ํ˜ธํ™˜ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - JSON ํ˜ธํ™˜ ์ธ์ฝ”๋”](../tutorial/encoder.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## OpenAPI ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ - ๋ฌธ์„œ { #openapi-metadata-docs }
+
+๋ผ์ด์„ ์Šค, ๋ฒ„์ „, ์—ฐ๋ฝ์ฒ˜ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•ด OpenAPI ์Šคํ‚ค๋งˆ์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## OpenAPI ์‚ฌ์šฉ์ž ์ •์˜ URL { #openapi-custom-url }
+
+OpenAPI URL์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ(๋˜๋Š” ์ œ๊ฑฐ)ํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+## OpenAPI ๋ฌธ์„œ URL { #openapi-docs-urls }
+
+์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ๋ฌธ์„œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์‚ฌ์šฉํ•˜๋Š” URL์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด [ํŠœํ† ๋ฆฌ์–ผ - ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋ฌธ์„œ URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
diff --git a/docs/ko/docs/how-to/graphql.md b/docs/ko/docs/how-to/graphql.md
new file mode 100644 (file)
index 0000000..3cc467e
--- /dev/null
@@ -0,0 +1,60 @@
+# GraphQL { #graphql }
+
+**FastAPI**๋Š” **ASGI** ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฏ€๋กœ, ASGI์™€๋„ ํ˜ธํ™˜๋˜๋Š” ์–ด๋–ค **GraphQL** ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“  ๋งค์šฐ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ผ๋ฐ˜ FastAPI **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ**์™€ GraphQL์„ ํ•จ๊ป˜ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+**GraphQL**์€ ๋ช‡ ๊ฐ€์ง€ ๋งค์šฐ ํŠน์ •ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
+
+์ผ๋ฐ˜์ ์ธ **web API**์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ **์žฅ์ **๊ณผ **๋‹จ์ **์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๋Ÿฌ๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ **์ด์ **์ด **๋‹จ์ **์„ ์ƒ์‡„ํ•˜๋Š”์ง€ ๊ผญ ํ‰๊ฐ€ํ•ด ๋ณด์„ธ์š”. ๐Ÿค“
+
+///
+
+## GraphQL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ { #graphql-libraries }
+
+๋‹ค์Œ์€ **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๋กœ GraphQL ์‚ฌ์šฉํ•˜๊ธฐ { #graphql-with-strawberry }
+
+**GraphQL**๋กœ ์ž‘์—…ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ์ž‘์—…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, <a href="https://strawberry.rocks/" class="external-link" target="_blank">**Strawberry**</a>๋ฅผ **๊ถŒ์žฅ**ํ•ฉ๋‹ˆ๋‹ค. **FastAPI**์˜ ์„ค๊ณ„์™€ ๊ฐ€์žฅ ๊ฐ€๊น๊ณ , ๋ชจ๋“  ๊ฒƒ์ด **type annotations**์— ๊ธฐ๋ฐ˜ํ•ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ œ๊ฒŒ ๋ฌป๋Š”๋‹ค๋ฉด ์•„๋งˆ **Strawberry**๋ฅผ ๋จผ์ € ์‹œ๋„ํ•ด ๋ณด๋ผ๊ณ  ์ œ์•ˆํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋‹ค์Œ์€ Strawberry๋ฅผ FastAPI์™€ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค:
+
+{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *}
+
+<a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry ๋ฌธ์„œ</a>์—์„œ Strawberry์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">FastAPI์—์„œ Strawberry ์‚ฌ์šฉ</a>์— ๋Œ€ํ•œ ๋ฌธ์„œ๋„ ํ™•์ธํ•ด ๋ณด์„ธ์š”.
+
+## Starlette์˜ ์˜ˆ์ „ `GraphQLApp` { #older-graphqlapp-from-starlette }
+
+์ด์ „ ๋ฒ„์ „์˜ Starlette์—๋Š” <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>๊ณผ ํ†ตํ•ฉํ•˜๊ธฐ ์œ„ํ•œ `GraphQLApp` ํด๋ž˜์Šค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์€ Starlette์—์„œ deprecated ๋˜์—ˆ์ง€๋งŒ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋˜ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฐ™์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃจ๊ณ  **๊ฑฐ์˜ ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค**๋ฅผ ๊ฐ€์ง„ <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a>๋กœ ์‰ฝ๊ฒŒ **๋งˆ์ด๊ทธ๋ ˆ์ด์…˜**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+GraphQL์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ปค์Šคํ…€ ํด๋ž˜์Šค์™€ ํƒ€์ž… ๋Œ€์‹  type annotations์— ๊ธฐ๋ฐ˜ํ•œ <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a>๋ฅผ ์—ฌ์ „ํžˆ ํ™•์ธํ•ด ๋ณด์‹œ๊ธธ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ๋” ์•Œ์•„๋ณด๊ธฐ { #learn-more }
+
+<a href="https://graphql.org/" class="external-link" target="_blank">๊ณต์‹ GraphQL ๋ฌธ์„œ</a>์—์„œ **GraphQL**์— ๋Œ€ํ•ด ๋” ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ๋„ ํ•ด๋‹น ๋งํฌ์—์„œ ๋” ์ž์„ธํžˆ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/how-to/index.md b/docs/ko/docs/how-to/index.md
new file mode 100644 (file)
index 0000000..9321c48
--- /dev/null
@@ -0,0 +1,13 @@
+# How To - ๋ ˆ์‹œํ”ผ { #how-to-recipes }
+
+์—ฌ๊ธฐ์—์„œ๋Š” **์—ฌ๋Ÿฌ ์ฃผ์ œ**์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ๋ ˆ์‹œํ”ผ(โ€œhow toโ€ ๊ฐ€์ด๋“œ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋Œ€๋ถ€๋ถ„์˜ ์•„์ด๋””์–ด๋Š” ์–ด๋А ์ •๋„ **์„œ๋กœ ๋…๋ฆฝ์ **์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ **์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ**์— ์ง์ ‘ ์ ์šฉ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ•™์Šตํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
+
+ํ”„๋กœ์ ํŠธ์— ํฅ๋ฏธ๋กญ๊ณ  ์œ ์šฉํ•ด ๋ณด์ด๋Š” ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด ํ™•์ธํ•ด ๋ณด์„ธ์š”. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์•„๋งˆ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+**FastAPI๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ํ•™์Šต**ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด(๊ถŒ์žฅ), ๋Œ€์‹  [ํŠœํ† ๋ฆฌ์–ผ - ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ](../tutorial/index.md){.internal-link target=_blank}๋ฅผ ์žฅ๋ณ„๋กœ ์ฝ์–ด๋ณด์„ธ์š”.
+
+///
diff --git a/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ko/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
new file mode 100644 (file)
index 0000000..6e528ec
--- /dev/null
@@ -0,0 +1,135 @@
+# Pydantic v1์—์„œ Pydantic v2๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ { #migrate-from-pydantic-v1-to-pydantic-v2 }
+
+์˜ค๋ž˜๋œ FastAPI ์•ฑ์ด ์žˆ๋‹ค๋ฉด Pydantic ๋ฒ„์ „ 1์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+FastAPI 0.100.0 ๋ฒ„์ „์€ Pydantic v1 ๋˜๋Š” v2 ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ์„ค์น˜๋˜์–ด ์žˆ๋Š” ์ชฝ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+FastAPI 0.119.0 ๋ฒ„์ „์—์„œ๋Š” v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, Pydantic v2 ๋‚ด๋ถ€์—์„œ Pydantic v1์„(`pydantic.v1`๋กœ) ๋ถ€๋ถ„์ ์œผ๋กœ ์ง€์›ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+FastAPI 0.126.0 ๋ฒ„์ „์—์„œ๋Š” Pydantic v1 ์ง€์›์„ ์ค‘๋‹จํ–ˆ์ง€๋งŒ, `pydantic.v1`์€ ์ž ์‹œ ๋™์•ˆ ๊ณ„์† ์ง€์›ํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+/// warning | ๊ฒฝ๊ณ 
+
+Pydantic ํŒ€์€ **Python 3.14**๋ถ€ํ„ฐ ์ตœ์‹  Python ๋ฒ„์ „์—์„œ Pydantic v1 ์ง€์›์„ ์ค‘๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” `pydantic.v1`๋„ ํฌํ•จ๋˜๋ฉฐ, Python 3.14 ์ด์ƒ์—์„œ๋Š” ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+Python์˜ ์ตœ์‹  ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Pydantic v2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+Pydantic v1์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ค๋ž˜๋œ FastAPI ์•ฑ์ด ์žˆ๋‹ค๋ฉด, ์—ฌ๊ธฐ์„œ๋Š” ์ด๋ฅผ Pydantic v2๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ ์ง„์  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋•๋Š” **FastAPI 0.119.0์˜ ๊ธฐ๋Šฅ**์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ๊ณต์‹ ๊ฐ€์ด๋“œ { #official-guide }
+
+Pydantic์—๋Š” v1์—์„œ v2๋กœ์˜ ๊ณต์‹ <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">Migration Guide</a>๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” ๋ฌด์—‡์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€, ๊ฒ€์ฆ์ด ์ด์ œ ์–ด๋–ป๊ฒŒ ๋” ์ •ํ™•ํ•˜๊ณ  ์—„๊ฒฉํ•ด์กŒ๋Š”์ง€, ๊ฐ€๋Šฅํ•œ ์ฃผ์˜์‚ฌํ•ญ ๋“ฑ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์„ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ฝ์–ด๋ณด๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.
+
+## ํ…Œ์ŠคํŠธ { #tests }
+
+์•ฑ์— ๋Œ€ํ•œ [tests](../tutorial/testing.md){.internal-link target=_blank}๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ง€์†์  ํ†ตํ•ฉ(CI)์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ๋„ ๋ชจ๋“  ๊ฒƒ์ด ๊ธฐ๋Œ€ํ•œ ๋Œ€๋กœ ๊ณ„์† ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## `bump-pydantic` { #bump-pydantic }
+
+๋งŽ์€ ๊ฒฝ์šฐ, ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์—†์ด ์ผ๋ฐ˜์ ์ธ Pydantic ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด Pydantic v1์—์„œ Pydantic v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ณผ์ • ๋Œ€๋ถ€๋ถ„์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ™์€ Pydantic ํŒ€์ด ์ œ๊ณตํ•˜๋Š” <a href="https://github.com/pydantic/bump-pydantic" class="external-link" target="_blank">`bump-pydantic`</a>๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ๋„๊ตฌ๋Š” ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์˜ ๋Œ€๋ถ€๋ถ„์„ ์ž๋™์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋ชจ๋“  ๊ฒƒ์ด ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ž˜ ๋œ๋‹ค๋ฉด ๋์ž…๋‹ˆ๋‹ค. ๐Ÿ˜Ž
+
+## v2 ์•ˆ์˜ Pydantic v1 { #pydantic-v1-in-v2 }
+
+Pydantic v2๋Š” Pydantic v1์˜ ๋ชจ๋“  ๊ฒƒ์„ ์„œ๋ธŒ๋ชจ๋“ˆ `pydantic.v1`๋กœ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” Python 3.13๋ณด๋‹ค ๋†’์€ ๋ฒ„์ „์—์„œ๋Š” ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ฆ‰, Pydantic v2์˜ ์ตœ์‹  ๋ฒ„์ „์„ ์„ค์น˜ํ•œ ๋’ค, ์ด ์„œ๋ธŒ๋ชจ๋“ˆ์—์„œ ์˜ˆ์ „ Pydantic v1 ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ importํ•˜์—ฌ ์˜ˆ์ „ Pydantic v1์„ ์„ค์น˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *}
+
+### v2 ์•ˆ์˜ Pydantic v1์— ๋Œ€ํ•œ FastAPI ์ง€์› { #fastapi-support-for-pydantic-v1-in-v2 }
+
+FastAPI 0.119.0๋ถ€ํ„ฐ๋Š” v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, Pydantic v2 ๋‚ด๋ถ€์˜ Pydantic v1์— ๋Œ€ํ•ด์„œ๋„ ๋ถ€๋ถ„์ ์ธ ์ง€์›์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ Pydantic์„ ์ตœ์‹  v2๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , import๋ฅผ `pydantic.v1` ์„œ๋ธŒ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๊พธ๋ฉด, ๋งŽ์€ ๊ฒฝ์šฐ ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *}
+
+/// warning | ๊ฒฝ๊ณ 
+
+Pydantic ํŒ€์ด Python 3.14๋ถ€ํ„ฐ ์ตœ์‹  Python ๋ฒ„์ „์—์„œ Pydantic v1์„ ๋” ์ด์ƒ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, `pydantic.v1`์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์—ญ์‹œ Python 3.14 ์ด์ƒ์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์—ผ๋‘์— ๋‘์„ธ์š”.
+
+///
+
+### ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2 ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ { #pydantic-v1-and-v2-on-the-same-app }
+
+Pydantic์—์„œ๋Š” Pydantic v2 ๋ชจ๋ธ์˜ ํ•„๋“œ๋ฅผ Pydantic v1 ๋ชจ๋ธ๋กœ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๋ฐ˜๋Œ€๋กœ ํ•˜๋Š” ๊ฒƒ์„ **์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**.
+
+```mermaid
+graph TB
+    subgraph "โŒ Not Supported"
+        direction TB
+        subgraph V2["Pydantic v2 Model"]
+            V1Field["Pydantic v1 Model"]
+        end
+        subgraph V1["Pydantic v1 Model"]
+            V2Field["Pydantic v2 Model"]
+        end
+    end
+
+    style V2 fill:#f9fff3
+    style V1 fill:#fff6f0
+    style V1Field fill:#fff6f0
+    style V2Field fill:#f9fff3
+```
+
+...ํ•˜์ง€๋งŒ ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2๋ฅผ ์‚ฌ์šฉํ•˜๋˜, ๋ชจ๋ธ์„ ๋ถ„๋ฆฌํ•ด์„œ ๋‘˜ ์ˆ˜๋Š” ์žˆ์Šต๋‹ˆ๋‹ค.
+
+```mermaid
+graph TB
+    subgraph "โœ… Supported"
+        direction TB
+        subgraph V2["Pydantic v2 Model"]
+            V2Field["Pydantic v2 Model"]
+        end
+        subgraph V1["Pydantic v1 Model"]
+            V1Field["Pydantic v1 Model"]
+        end
+    end
+
+    style V2 fill:#f9fff3
+    style V1 fill:#fff6f0
+    style V1Field fill:#fff6f0
+    style V2Field fill:#f9fff3
+```
+
+์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” FastAPI ์•ฑ์˜ ๊ฐ™์€ **๊ฒฝ๋กœ ์ฒ˜๋ฆฌ**์—์„œ Pydantic v1๊ณผ v2 ๋ชจ๋ธ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
+
+์œ„ ์˜ˆ์ œ์—์„œ ์ž…๋ ฅ ๋ชจ๋ธ์€ Pydantic v1 ๋ชจ๋ธ์ด๊ณ , ์ถœ๋ ฅ ๋ชจ๋ธ(`response_model=ItemV2`๋กœ ์ •์˜๋จ)์€ Pydantic v2 ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.
+
+### Pydantic v1 ํŒŒ๋ผ๋ฏธํ„ฐ { #pydantic-v1-parameters }
+
+Pydantic v1 ๋ชจ๋ธ๊ณผ ํ•จ๊ป˜ `Body`, `Query`, `Form` ๋“ฑ ํŒŒ๋ผ๋ฏธํ„ฐ์šฉ FastAPI ์ „์šฉ ๋„๊ตฌ ์ผ๋ถ€๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด, Pydantic v2๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋งˆ์น  ๋•Œ๊นŒ์ง€ `fastapi.temp_pydantic_v1_params`์—์„œ importํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *}
+
+### ๋‹จ๊ณ„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ { #migrate-in-steps }
+
+/// tip | ํŒ
+
+๋จผ์ € `bump-pydantic`๋กœ ์‹œ๋„ํ•ด ๋ณด์„ธ์š”. ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•˜๊ณ  ์ž˜ ๋™์ž‘ํ•œ๋‹ค๋ฉด, ํ•œ ๋ฒˆ์˜ ๋ช…๋ น์œผ๋กœ ๋์ž…๋‹ˆ๋‹ค. โœจ
+
+///
+
+`bump-pydantic`๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋งž์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๊ฐ™์€ ์•ฑ์—์„œ Pydantic v1๊ณผ v2 ๋ชจ๋ธ์„ ๋ชจ๋‘ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด Pydantic v2๋กœ ์ ์ง„์ ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋จผ์ € Pydantic์„ ์ตœ์‹  v2๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , ๋ชจ๋“  ๋ชจ๋ธ์˜ import๋ฅผ `pydantic.v1`์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ Pydantic v1์—์„œ v2๋กœ ๋ชจ๋ธ์„ ๊ทธ๋ฃน ๋‹จ์œ„๋กœ, ์ ์ง„์ ์ธ ๋‹จ๊ณ„๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹œ์ž‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿšถ
diff --git a/docs/ko/docs/how-to/separate-openapi-schemas.md b/docs/ko/docs/how-to/separate-openapi-schemas.md
new file mode 100644 (file)
index 0000000..055429c
--- /dev/null
@@ -0,0 +1,102 @@
+# ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ๋Œ€ํ•ด OpenAPI ์Šคํ‚ค๋งˆ๋ฅผ ๋ถ„๋ฆฌํ• ์ง€ ์—ฌ๋ถ€ { #separate-openapi-schemas-for-input-and-output-or-not }
+
+**Pydantic v2**๊ฐ€ ๋ฆด๋ฆฌ์Šค๋œ ์ดํ›„, ์ƒ์„ฑ๋˜๋Š” OpenAPI๋Š” ์ด์ „๋ณด๋‹ค ์กฐ๊ธˆ ๋” ์ •ํ™•ํ•˜๊ณ  **์˜ฌ๋ฐ”๋ฅด๊ฒŒ** ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ๐Ÿ˜Ž
+
+์‹ค์ œ๋กœ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š”, ๊ฐ™์€ Pydantic ๋ชจ๋ธ์— ๋Œ€ํ•ด OpenAPI ์•ˆ์— **๋‘ ๊ฐœ์˜ JSON Schema**๊ฐ€ ์ƒ๊ธฐ๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. **๊ธฐ๋ณธ๊ฐ’(default value)**์ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ, ์ž…๋ ฅ์šฉ๊ณผ ์ถœ๋ ฅ์šฉ์œผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์„ ์œ„ํ•œ Pydantic ๋ชจ๋ธ { #pydantic-models-for-input-and-output }
+
+์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๋Š” Pydantic ๋ชจ๋ธ์ด ์žˆ๋‹ค๊ณ  ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}
+
+### ์ž…๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-input }
+
+์ด ๋ชจ๋ธ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด:
+
+{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *}
+
+...`description` ํ•„๋“œ๋Š” **ํ•„์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค**. `None`์ด๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+### ๋ฌธ์„œ์—์„œ์˜ ์ž…๋ ฅ ๋ชจ๋ธ { #input-model-in-docs }
+
+๋ฌธ์„œ์—์„œ `description` ํ•„๋“œ์— **๋นจ๊ฐ„ ๋ณ„ํ‘œ**๊ฐ€ ์—†๊ณ , ํ•„์ˆ˜๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<div class="screenshot">
+<img src="/img/tutorial/separate-openapi-schemas/image01.png">
+</div>
+
+### ์ถœ๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-output }
+
+ํ•˜์ง€๋งŒ ๊ฐ™์€ ๋ชจ๋ธ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ถœ๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด:
+
+{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}
+
+...`description`์— ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ ํ•„๋“œ์— ๋Œ€ํ•ด **์•„๋ฌด๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋”๋ผ๋„** ์—ฌ์ „ํžˆ ๊ทธ **๊ธฐ๋ณธ๊ฐ’**์ด ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+### ์ถœ๋ ฅ ์‘๋‹ต ๋ฐ์ดํ„ฐ์šฉ ๋ชจ๋ธ { #model-for-output-response-data }
+
+๋ฌธ์„œ์—์„œ ์ง์ ‘ ๋™์ž‘์‹œ์ผœ ์‘๋‹ต์„ ํ™•์ธํ•ด ๋ณด๋ฉด, ์ฝ”๋“œ๊ฐ€ `description` ํ•„๋“œ ์ค‘ ํ•˜๋‚˜์— ์•„๋ฌด๊ฒƒ๋„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๋”๋ผ๋„ JSON ์‘๋‹ต์—๋Š” ๊ธฐ๋ณธ๊ฐ’(`null`)์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<div class="screenshot">
+<img src="/img/tutorial/separate-openapi-schemas/image02.png">
+</div>
+
+์ด๋Š” ํ•ด๋‹น ํ•„๋“œ๊ฐ€ **ํ•ญ์ƒ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค๋Š” ๊ฒƒ**์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๊ทธ ๊ฐ’์ด ๋•Œ๋กœ๋Š” `None`(JSON์—์„œ๋Š” `null`)์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ฆ‰, API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๊ฐ’์ด ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์—†๊ณ , **ํ•„๋“œ๊ฐ€ ํ•ญ์ƒ ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ธฐ๋ณธ๊ฐ’ `None`์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
+
+์ด๋ฅผ OpenAPI์—์„œ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€, ๊ทธ ํ•„๋“œ๋ฅผ **required**๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•ญ์ƒ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+์ด ๋•Œ๋ฌธ์—, ํ•˜๋‚˜์˜ ๋ชจ๋ธ์ด๋ผ๋„ **์ž…๋ ฅ์šฉ์ธ์ง€ ์ถœ๋ ฅ์šฉ์ธ์ง€**์— ๋”ฐ๋ผ JSON Schema๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* **์ž…๋ ฅ**์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜**
+* **์ถœ๋ ฅ**์—์„œ๋Š” **ํ•„์ˆ˜์ž„** (๊ทธ๋ฆฌ๊ณ  ๊ฐ’์€ `None`์ผ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, JSON ์šฉ์–ด๋กœ๋Š” `null`)
+
+### ๋ฌธ์„œ์—์„œ์˜ ์ถœ๋ ฅ์šฉ ๋ชจ๋ธ { #model-for-output-in-docs }
+
+๋ฌธ์„œ์—์„œ ์ถœ๋ ฅ ๋ชจ๋ธ์„ ํ™•์ธํ•ด ๋ณด๋ฉด, `name`๊ณผ `description` **๋‘˜ ๋‹ค** **๋นจ๊ฐ„ ๋ณ„ํ‘œ**๋กœ **ํ•„์ˆ˜**๋กœ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<div class="screenshot">
+<img src="/img/tutorial/separate-openapi-schemas/image03.png">
+</div>
+
+### ๋ฌธ์„œ์—์„œ์˜ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋ธ { #model-for-input-and-output-in-docs }
+
+๋˜ OpenAPI์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  Schemas(JSON Schemas)๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด, `Item-Input` ํ•˜๋‚˜์™€ `Item-Output` ํ•˜๋‚˜, ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`Item-Input`์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉฐ**, ๋นจ๊ฐ„ ๋ณ„ํ‘œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `Item-Output`์—์„œ๋Š” `description`์ด **ํ•„์ˆ˜์ด๋ฉฐ**, ๋นจ๊ฐ„ ๋ณ„ํ‘œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+<div class="screenshot">
+<img src="/img/tutorial/separate-openapi-schemas/image04.png">
+</div>
+
+**Pydantic v2**์˜ ์ด ๊ธฐ๋Šฅ ๋•๋ถ„์— API ๋ฌธ์„œ๋Š” ๋” **์ •๋ฐ€**ํ•ด์ง€๊ณ , ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ์™€ SDK๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ๋“ค๋„ ๋” ์ •๋ฐ€ํ•ด์ ธ์„œ ๋” ๋‚˜์€ **developer experience**์™€ ์ผ๊ด€์„ฑ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰
+
+## ์Šคํ‚ค๋งˆ๋ฅผ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๊ธฐ { #do-not-separate-schemas }
+
+์ด์ œ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” **์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์— ๋Œ€ํ•ด ๊ฐ™์€ ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉ**ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๊ฒฝ์šฐ๋Š”, ์ด๋ฏธ ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ/SDK๊ฐ€ ์žˆ๊ณ , ์•„์ง์€ ๊ทธ ์ž๋™ ์ƒ์„ฑ๋œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ/SDK๋“ค์„ ์ „๋ถ€ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์–ธ์  ๊ฐ€๋Š” ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์ง€๋งŒ, ์ง€๊ธˆ ๋‹น์žฅ์€ ์•„๋‹ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š”, **FastAPI**์—์„œ `separate_input_output_schemas=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ด ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+`separate_input_output_schemas` ์ง€์›์€ FastAPI `0.102.0`์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
+
+///
+
+{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *}
+
+### ๋ฌธ์„œ์—์„œ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋ธ์— ๊ฐ™์€ ์Šคํ‚ค๋งˆ ์‚ฌ์šฉ { #same-schema-for-input-and-output-models-in-docs }
+
+์ด์ œ ๋ชจ๋ธ์— ๋Œ€ํ•ด ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ ๋ชจ๋‘์— ์‚ฌ์šฉ๋˜๋Š” ๋‹จ์ผ ์Šคํ‚ค๋งˆ(์˜ค์ง `Item`๋งŒ)๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, `description`์€ **ํ•„์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒƒ**์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค:
+
+<div class="screenshot">
+<img src="/img/tutorial/separate-openapi-schemas/image05.png">
+</div>
diff --git a/docs/ko/docs/how-to/testing-database.md b/docs/ko/docs/how-to/testing-database.md
new file mode 100644 (file)
index 0000000..2d7798d
--- /dev/null
@@ -0,0 +1,7 @@
+# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ŠคํŠธํ•˜๊ธฐ { #testing-a-database }
+
+๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, SQL, SQLModel์— ๋Œ€ํ•ด์„œ๋Š” <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel ๋ฌธ์„œ</a>์—์„œ ํ•™์Šตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
+
+<a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">FastAPI์—์„œ SQLModel์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ฏธ๋‹ˆ ํŠœํ† ๋ฆฌ์–ผ</a>๋„ ์žˆ์Šต๋‹ˆ๋‹ค. โœจ
+
+ํ•ด๋‹น ํŠœํ† ๋ฆฌ์–ผ์—๋Š” <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/" class="external-link" target="_blank">SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ŠคํŠธ</a>์— ๋Œ€ํ•œ ์„น์…˜๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ž
diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md
new file mode 100644 (file)
index 0000000..cfc3900
--- /dev/null
@@ -0,0 +1,504 @@
+# ๋” ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ์—ฌ๋Ÿฌ ํŒŒ์ผ { #bigger-applications-multiple-files }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ์›น API๋ฅผ ๋งŒ๋“ค ๋•Œ, ๋ชจ๋“  ๊ฒƒ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ญ…๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ๋ชจ๋“  ์œ ์—ฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์กฐํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํŽธ๋ฆฌํ•œ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+Flask๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์…จ๋‹ค๋ฉด, ์ด๋Š” Flask์˜ Blueprints์— ํ•ด๋‹นํ•˜๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.
+
+///
+
+## ์˜ˆ์‹œ ํŒŒ์ผ ๊ตฌ์กฐ { #an-example-file-structure }
+
+๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค:
+
+```
+.
+โ”œโ”€โ”€ app
+โ”‚ย ย  โ”œโ”€โ”€ __init__.py
+โ”‚ย ย  โ”œโ”€โ”€ main.py
+โ”‚ย ย  โ”œโ”€โ”€ dependencies.py
+โ”‚ย ย  โ””โ”€โ”€ routers
+โ”‚ย ย  โ”‚   โ”œโ”€โ”€ __init__.py
+โ”‚ย ย  โ”‚   โ”œโ”€โ”€ items.py
+โ”‚ย ย  โ”‚   โ””โ”€โ”€ users.py
+โ”‚ย ย  โ””โ”€โ”€ internal
+โ”‚ย ย      โ”œโ”€โ”€ __init__.py
+โ”‚ย ย      โ””โ”€โ”€ admin.py
+```
+
+/// tip | ํŒ
+
+`__init__.py` ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค: ๊ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋˜๋Š” ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํ•˜๋‚˜์”ฉ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ํŒŒ์ผ๋“ค์ด ํ•œ ํŒŒ์ผ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ํŒŒ์ผ๋กœ importํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `app/main.py`์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ค„์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```
+from app.routers import items
+```
+
+///
+
+* `app` ๋””๋ ‰ํ„ฐ๋ฆฌ์—๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋น„์–ด ์žˆ๋Š” ํŒŒ์ผ `app/__init__.py`๊ฐ€ ์žˆ์–ด "Python package"(โ€œPython modulesโ€์˜ ๋ชจ์Œ)์ธ `app`์ด ๋ฉ๋‹ˆ๋‹ค.
+* `app/main.py` ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. Python package(`__init__.py` ํŒŒ์ผ์ด ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ) ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ, ์ด package์˜ "module"์ž…๋‹ˆ๋‹ค: `app.main`.
+* `app/dependencies.py` ํŒŒ์ผ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `app/main.py`์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ "module"์ž…๋‹ˆ๋‹ค: `app.dependencies`.
+* `app/routers/` ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์žˆ๊ณ , ์—ฌ๊ธฐ์— ๋˜ `__init__.py` ํŒŒ์ผ์ด ์žˆ์œผ๋ฏ€๋กœ "Python subpackage"์ž…๋‹ˆ๋‹ค: `app.routers`.
+* `app/routers/items.py` ํŒŒ์ผ์€ `app/routers/` package ์•ˆ์— ์žˆ์œผ๋ฏ€๋กœ, submodule์ž…๋‹ˆ๋‹ค: `app.routers.items`.
+* `app/routers/users.py`๋„ ๋™์ผํ•˜๊ฒŒ ๋˜ ๋‹ค๋ฅธ submodule์ž…๋‹ˆ๋‹ค: `app.routers.users`.
+* `app/internal/` ํ•˜์œ„ ๋””๋ ‰ํ„ฐ๋ฆฌ๋„ ์žˆ๊ณ  ์—ฌ๊ธฐ์— `__init__.py`๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋˜ ๋‹ค๋ฅธ "Python subpackage"์ž…๋‹ˆ๋‹ค: `app.internal`.
+* ๊ทธ๋ฆฌ๊ณ  `app/internal/admin.py` ํŒŒ์ผ์€ ๋˜ ๋‹ค๋ฅธ submodule์ž…๋‹ˆ๋‹ค: `app.internal.admin`.
+
+<img src="/img/tutorial/bigger-applications/package.drawio.svg">
+
+๊ฐ™์€ ํŒŒ์ผ ๊ตฌ์กฐ์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+```bash
+.
+โ”œโ”€โ”€ app                  # "app" is a Python package
+โ”‚ย ย  โ”œโ”€โ”€ __init__.py      # this file makes "app" a "Python package"
+โ”‚ย ย  โ”œโ”€โ”€ main.py          # "main" module, e.g. import app.main
+โ”‚ย ย  โ”œโ”€โ”€ dependencies.py  # "dependencies" module, e.g. import app.dependencies
+โ”‚ย ย  โ””โ”€โ”€ routers          # "routers" is a "Python subpackage"
+โ”‚ย ย  โ”‚   โ”œโ”€โ”€ __init__.py  # makes "routers" a "Python subpackage"
+โ”‚ย ย  โ”‚   โ”œโ”€โ”€ items.py     # "items" submodule, e.g. import app.routers.items
+โ”‚ย ย  โ”‚   โ””โ”€โ”€ users.py     # "users" submodule, e.g. import app.routers.users
+โ”‚ย ย  โ””โ”€โ”€ internal         # "internal" is a "Python subpackage"
+โ”‚ย ย      โ”œโ”€โ”€ __init__.py  # makes "internal" a "Python subpackage"
+โ”‚ย ย      โ””โ”€โ”€ admin.py     # "admin" submodule, e.g. import app.internal.admin
+```
+
+## `APIRouter` { #apirouter }
+
+์‚ฌ์šฉ์ž๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ์ „์šฉ ํŒŒ์ผ์ด `/app/routers/users.py`์˜ submodule์ด๋ผ๊ณ  ํ•ด๋ด…์‹œ๋‹ค.
+
+์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž์™€ ๊ด€๋ จ๋œ *path operations*๋ฅผ ๋‚˜๋จธ์ง€ ์ฝ”๋“œ์™€ ๋ถ„๋ฆฌํ•ด ๋‘๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ ๊ฐ™์€ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/์›น API์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค(๊ฐ™์€ "Python Package"์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค).
+
+`APIRouter`๋ฅผ ์‚ฌ์šฉํ•ด ํ•ด๋‹น ๋ชจ๋“ˆ์˜ *path operations*๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### `APIRouter` importํ•˜๊ธฐ { #import-apirouter }
+
+`FastAPI` ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ importํ•˜๊ณ  "instance"๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
+
+### `APIRouter`๋กœ *path operations* ๋งŒ๋“ค๊ธฐ { #path-operations-with-apirouter }
+
+๊ทธ ๋‹ค์Œ ์ด๋ฅผ ์‚ฌ์šฉํ•ด *path operations*๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+
+`FastAPI` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
+
+`APIRouter`๋Š” "๋ฏธ๋‹ˆ `FastAPI`" ํด๋ž˜์Šค๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋™์ผํ•œ ์˜ต์…˜๋“ค์ด ๋ชจ๋‘ ์ง€์›๋ฉ๋‹ˆ๋‹ค.
+
+๋™์ผํ•œ `parameters`, `responses`, `dependencies`, `tags` ๋“ฑ๋“ฑ.
+
+/// tip | ํŒ
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋ณ€์ˆ˜ ์ด๋ฆ„์ด `router`์ด์ง€๋งŒ, ์›ํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ ์ง€์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+์ด์ œ ์ด `APIRouter`๋ฅผ ๋ฉ”์ธ `FastAPI` ์•ฑ์— ํฌํ•จ(include)ํ•  ๊ฒƒ์ด์ง€๋งŒ, ๋จผ์ € dependencies์™€ ๋‹ค๋ฅธ `APIRouter` ํ•˜๋‚˜๋ฅผ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## Dependencies { #dependencies }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ ์œ„์น˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” dependencies๊ฐ€ ์ผ๋ถ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ ์ด๋ฅผ ๋ณ„๋„์˜ `dependencies` ๋ชจ๋“ˆ(`app/dependencies.py`)์— ๋‘ก๋‹ˆ๋‹ค.
+
+์ด์ œ ๊ฐ„๋‹จํ•œ dependency๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ `X-Token` ํ—ค๋”๋ฅผ ์ฝ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
+
+/// tip | ํŒ
+
+์ด ์˜ˆ์‹œ๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ž„์˜๋กœ ๋งŒ๋“  ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์‹ค์ œ ์ƒํ™ฉ์—์„œ๋Š” ํ†ตํ•ฉ๋œ [Security ์œ ํ‹ธ๋ฆฌํ‹ฐ](security/index.md){.internal-link target=_blank}๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## `APIRouter`๊ฐ€ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ๋ชจ๋“ˆ { #another-module-with-apirouter }
+
+์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ "items"๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ „์šฉ endpoint๋“ค๋„ `app/routers/items.py` ๋ชจ๋“ˆ์— ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” ๋‹ค์Œ์— ๋Œ€ํ•œ *path operations*๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* `/items/`
+* `/items/{item_id}`
+
+๊ตฌ์กฐ๋Š” `app/routers/users.py`์™€ ์™„์ „ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์กฐ๊ธˆ ๋” ๋˜‘๋˜‘ํ•˜๊ฒŒ, ์ฝ”๋“œ๋ฅผ ์•ฝ๊ฐ„ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
+
+์ด ๋ชจ๋“ˆ์˜ ๋ชจ๋“  *path operations*์—๋Š” ๋‹ค์Œ์ด ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค:
+
+* ๊ฒฝ๋กœ `prefix`: `/items`.
+* `tags`: (ํƒœ๊ทธ ํ•˜๋‚˜: `items`).
+* ์ถ”๊ฐ€ `responses`.
+* `dependencies`: ๋ชจ๋‘ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  `X-Token` dependency๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ๊ฐ *path operation*๋งˆ๋‹ค ๋งค๋ฒˆ ๋ชจ๋‘ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹ , `APIRouter`์— ํ•œ ๋ฒˆ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
+
+๊ฐ *path operation*์˜ ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ `/`๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๋ฏ€๋กœ:
+
+```Python hl_lines="1"
+@router.get("/{item_id}")
+async def read_item(item_id: str):
+    ...
+```
+
+...prefix์—๋Š” ๋งˆ์ง€๋ง‰ `/`๊ฐ€ ํฌํ•จ๋˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ prefix๋Š” `/items`์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์ด router์— ํฌํ•จ๋œ ๋ชจ๋“  *path operations*์— ์ ์šฉ๋  `tags` ๋ชฉ๋ก๊ณผ ์ถ”๊ฐ€ `responses`๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  router์˜ ๋ชจ๋“  *path operations*์— ์ถ”๊ฐ€๋  `dependencies` ๋ชฉ๋ก๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ๊ฒฝ๋กœ๋“ค๋กœ ๋“ค์–ด์˜ค๋Š” ๊ฐ ์š”์ฒญ๋งˆ๋‹ค ์‹คํ–‰/ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+[*path operation decorator์˜ dependencies*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, *path operation function*์— ์–ด๋–ค ๊ฐ’๋„ ์ „๋‹ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+///
+
+์ตœ์ข…์ ์œผ๋กœ item ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* `/items/`
+* `/items/{item_id}`
+
+...์˜๋„ํ•œ ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.
+
+* ๋‹จ์ผ ๋ฌธ์ž์—ด `"items"`๋ฅผ ํฌํ•จํ•˜๋Š” ํƒœ๊ทธ ๋ชฉ๋ก์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+    * ์ด "tags"๋Š” ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ(OpenAPI ์‚ฌ์šฉ)์— ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+* ๋ชจ๋‘ ๋ฏธ๋ฆฌ ์ •์˜๋œ `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}๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+`APIRouter`์— `dependencies`๋ฅผ ๋‘๋Š” ๊ฒƒ์€ ์˜ˆ๋ฅผ ๋“ค์–ด ์ „์ฒด *path operations* ๊ทธ๋ฃน์— ์ธ์ฆ์„ ์š”๊ตฌํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ์— ๊ฐœ๋ณ„์ ์œผ๋กœ dependencies๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// check | ํ™•์ธ
+
+`prefix`, `tags`, `responses`, `dependencies` ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” (๋‹ค๋ฅธ ๋งŽ์€ ๊ฒฝ์šฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ) ์ฝ”๋“œ ์ค‘๋ณต์„ ํ”ผํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” **FastAPI**์˜ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
+
+///
+
+### dependencies importํ•˜๊ธฐ { #import-the-dependencies }
+
+์ด ์ฝ”๋“œ๋Š” ๋ชจ๋“ˆ `app.routers.items`, ํŒŒ์ผ `app/routers/items.py`์— ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  dependency ํ•จ์ˆ˜๋Š” ๋ชจ๋“ˆ `app.dependencies`, ํŒŒ์ผ `app/dependencies.py`์—์„œ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ž˜์„œ dependencies์— ๋Œ€ํ•ด `..`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒ๋Œ€ import๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
+
+#### ์ƒ๋Œ€ import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-relative-imports-work }
+
+/// tip | ํŒ
+
+import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์„ ์™„๋ฒฝํžˆ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, ์•„๋ž˜ ๋‹ค์Œ ์„น์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”.
+
+///
+
+๋‹ค์Œ๊ณผ ๊ฐ™์ด ์  ํ•˜๋‚˜ `.`๋ฅผ ์“ฐ๋ฉด:
+
+```Python
+from .dependencies import get_token_header
+```
+
+์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ...
+* `dependencies` ๋ชจ๋“ˆ(๊ฐ€์ƒ์˜ ํŒŒ์ผ `app/routers/dependencies.py`)์„ ์ฐพ๊ณ ...
+* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๊ทธ ํŒŒ์ผ์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. dependencies๋Š” `app/dependencies.py` ํŒŒ์ผ์— ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์šฐ๋ฆฌ ์•ฑ/ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ๋‹ค์‹œ ๋– ์˜ฌ๋ ค ๋ณด์„ธ์š”:
+
+<img src="/img/tutorial/bigger-applications/package.drawio.svg">
+
+---
+
+๋‹ค์Œ์ฒ˜๋Ÿผ ์  ๋‘ ๊ฐœ `..`๋ฅผ ์“ฐ๋ฉด:
+
+```Python
+from ..dependencies import get_token_header
+```
+
+์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ...
+* ์ƒ์œ„ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)๋กœ ์˜ฌ๋ผ๊ฐ€๊ณ ...
+* ๊ทธ ์•ˆ์—์„œ `dependencies` ๋ชจ๋“ˆ(ํŒŒ์ผ `app/dependencies.py`)์„ ์ฐพ๊ณ ...
+* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰
+
+---
+
+๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์  ์„ธ ๊ฐœ `...`๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด:
+
+```Python
+from ...dependencies import get_token_header
+```
+
+์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/routers/items.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ...
+* ์ƒ์œ„ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)๋กœ ์˜ฌ๋ผ๊ฐ€๊ณ ...
+* ๊ทธ package์˜ ์ƒ์œ„๋กœ ๋˜ ์˜ฌ๋ผ๊ฐ€๋Š”๋ฐ(์ƒ์œ„ package๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค, `app`์ด ์ตœ์ƒ์œ„์ž…๋‹ˆ๋‹ค ๐Ÿ˜ฑ)...
+* ๊ทธ ์•ˆ์—์„œ `dependencies` ๋ชจ๋“ˆ(ํŒŒ์ผ `app/dependencies.py`)์„ ์ฐพ๊ณ ...
+* ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ `get_token_header`๋ฅผ importํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Š” `app/` ์œ„์ชฝ์˜ ์–ด๋–ค package(์ž์‹ ์˜ `__init__.py` ํŒŒ์ผ ๋“ฑ์„ ๊ฐ€์ง„)์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๊ทธ๋Ÿฐ ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๐Ÿšจ
+
+์ด์ œ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•˜์œผ๋‹ˆ, ์•ฑ์ด ์–ผ๋งˆ๋‚˜ ๋ณต์žกํ•˜๋“  ์ƒ๋Œ€ import๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
+
+### ์ปค์Šคํ…€ `tags`, `responses`, `dependencies` ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-some-custom-tags-responses-and-dependencies }
+
+`APIRouter`์— ์ด๋ฏธ prefix `/items`์™€ `tags=["items"]`๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ *path operation*์— ์ด๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ํŠน์ • *path operation*์—๋งŒ ์ ์šฉ๋  _์ถ”๊ฐ€_ `tags`๋ฅผ ๋”ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ทธ *path operation* ์ „์šฉ์˜ ์ถ”๊ฐ€ `responses`๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
+
+/// tip | ํŒ
+
+์ด ๋งˆ์ง€๋ง‰ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋Š” `["items", "custom"]` ํƒœ๊ทธ ์กฐํ•ฉ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋ฌธ์„œ์—๋Š” `404`์šฉ ์‘๋‹ต๊ณผ `403`์šฉ ์‘๋‹ต, ๋‘ ๊ฐ€์ง€ ๋ชจ๋‘๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ๋ฉ”์ธ `FastAPI` { #the-main-fastapi }
+
+์ด์ œ `app/main.py` ๋ชจ๋“ˆ์„ ๋ด…์‹œ๋‹ค.
+
+์—ฌ๊ธฐ์—์„œ `FastAPI` ํด๋ž˜์Šค๋ฅผ importํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ํŒŒ์ผ์€ ๋ชจ๋“  ๊ฒƒ์„ ํ•˜๋‚˜๋กœ ์—ฎ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฉ”์ธ ํŒŒ์ผ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๋กœ์ง์ด ๊ฐ์ž์˜ ํŠน์ • ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ๋ฉ”์ธ ํŒŒ์ผ์€ ๊ฝค ๋‹จ์ˆœํ•ด์ง‘๋‹ˆ๋‹ค.
+
+### `FastAPI` importํ•˜๊ธฐ { #import-fastapi }
+
+ํ‰์†Œ์ฒ˜๋Ÿผ `FastAPI` ํด๋ž˜์Šค๋ฅผ importํ•˜๊ณ  ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ๊ฐ `APIRouter`์˜ dependencies์™€ ๊ฒฐํ•ฉ๋  [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank}๋„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
+
+### `APIRouter` importํ•˜๊ธฐ { #import-the-apirouter }
+
+์ด์ œ `APIRouter`๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ submodule๋“ค์„ importํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
+
+`app/routers/users.py`์™€ `app/routers/items.py` ํŒŒ์ผ์€ ๊ฐ™์€ Python package `app`์— ์†ํ•œ submodule๋“ค์ด๋ฏ€๋กœ, ์  ํ•˜๋‚˜ `.`๋ฅผ ์‚ฌ์šฉํ•ด "์ƒ๋Œ€ import"๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### import๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹ { #how-the-importing-works }
+
+๋‹ค์Œ ๊ตฌ๋ฌธ์€:
+
+```Python
+from .routers import items, users
+```
+
+์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
+
+* ์ด ๋ชจ๋“ˆ(ํŒŒ์ผ `app/main.py`)์ด ์†ํ•œ ๊ฐ™์€ package(๋””๋ ‰ํ„ฐ๋ฆฌ `app/`)์—์„œ ์‹œ์ž‘ํ•ด์„œ...
+* subpackage `routers`(๋””๋ ‰ํ„ฐ๋ฆฌ `app/routers/`)๋ฅผ ์ฐพ๊ณ ...
+* ๊ทธ ์•ˆ์—์„œ submodule `items`(ํŒŒ์ผ `app/routers/items.py`)์™€ `users`(ํŒŒ์ผ `app/routers/users.py`)๋ฅผ importํ•ฉ๋‹ˆ๋‹ค...
+
+`items` ๋ชจ๋“ˆ์—๋Š” `router` ๋ณ€์ˆ˜(`items.router`)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” `app/routers/items.py` ํŒŒ์ผ์—์„œ ๋งŒ๋“  ๊ฒƒ๊ณผ ๋™์ผํ•˜๋ฉฐ `APIRouter` ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  `users` ๋ชจ๋“ˆ๋„ ๊ฐ™์€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
+
+๋‹ค์Œ์ฒ˜๋Ÿผ importํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python
+from app.routers import items, users
+```
+
+/// info | ์ •๋ณด
+
+์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „์€ "์ƒ๋Œ€ import"์ž…๋‹ˆ๋‹ค:
+
+```Python
+from .routers import items, users
+```
+
+๋‘ ๋ฒˆ์งธ ๋ฒ„์ „์€ "์ ˆ๋Œ€ import"์ž…๋‹ˆ๋‹ค:
+
+```Python
+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>๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.
+
+///
+
+### ์ด๋ฆ„ ์ถฉ๋Œ ํ”ผํ•˜๊ธฐ { #avoid-name-collisions }
+
+submodule `items`๋ฅผ ์ง์ ‘ importํ•˜๊ณ , ๊ทธ ์•ˆ์˜ `router` ๋ณ€์ˆ˜๋งŒ importํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” submodule `users`์—๋„ `router`๋ผ๋Š” ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+๋งŒ์•ฝ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ˆœ์„œ๋Œ€๋กœ importํ–ˆ๋‹ค๋ฉด:
+
+```Python
+from .routers.items import router
+from .routers.users import router
+```
+
+`users`์˜ `router`๊ฐ€ `items`์˜ `router`๋ฅผ ๋ฎ์–ด์จ์„œ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ๊ฐ™์€ ํŒŒ์ผ์—์„œ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก submodule๋“ค์„ ์ง์ ‘ importํ•ฉ๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
+
+### `users`์™€ `items`์šฉ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-the-apirouters-for-users-and-items }
+
+์ด์ œ submodule `users`์™€ `items`์˜ `router`๋ฅผ ํฌํ•จํ•ด ๋ด…์‹œ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
+
+/// info | ์ •๋ณด
+
+`users.router`๋Š” `app/routers/users.py` ํŒŒ์ผ ์•ˆ์˜ `APIRouter`๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`items.router`๋Š” `app/routers/items.py` ํŒŒ์ผ ์•ˆ์˜ `APIRouter`๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+`app.include_router()`๋กœ ๊ฐ `APIRouter`๋ฅผ ๋ฉ”์ธ `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ router์˜ ๋ชจ๋“  route๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๋ถ€๋กœ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+/// note Technical Details | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+๋‚ด๋ถ€์ ์œผ๋กœ๋Š” `APIRouter`์— ์„ ์–ธ๋œ ๊ฐ *path operation*๋งˆ๋‹ค *path operation*์„ ์‹ค์ œ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
+
+์ฆ‰, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋™์ผํ•œ ํ•˜๋‚˜์˜ ์•ฑ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// check | ํ™•์ธ
+
+router๋ฅผ ํฌํ•จ(include)ํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.
+
+์ด ์ž‘์—…์€ ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„์ด๋ฉฐ ์‹œ์ž‘ ์‹œ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. โšก
+
+///
+
+### ์ปค์Šคํ…€ `prefix`, `tags`, `responses`, `dependencies`๋กœ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
+
+์ด์ œ ์กฐ์ง์—์„œ `app/internal/admin.py` ํŒŒ์ผ์„ ๋ฐ›์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค.
+
+์—ฌ๊ธฐ์—๋Š” ์กฐ์ง์—์„œ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ ๊ฐ„์— ๊ณต์œ ํ•˜๋Š” ๊ด€๋ฆฌ์ž์šฉ *path operations*๊ฐ€ ์žˆ๋Š” `APIRouter`๊ฐ€ ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค์šฐ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์™€ ๊ณต์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์–ด `prefix`, `dependencies`, `tags` ๋“ฑ์„ `APIRouter`์— ์ง์ ‘ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
+
+ํ•˜์ง€๋งŒ `APIRouter`๋ฅผ ํฌํ•จํ•  ๋•Œ ์ปค์Šคํ…€ `prefix`๋ฅผ ์ง€์ •ํ•ด ๋ชจ๋“  *path operations*๊ฐ€ `/admin`์œผ๋กœ ์‹œ์ž‘ํ•˜๊ฒŒ ํ•˜๊ณ , ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ด๋ฏธ ๊ฐ€์ง„ `dependencies`๋กœ ๋ณดํ˜ธํ•˜๊ณ , `tags`์™€ `responses`๋„ ํฌํ•จํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
+
+์›๋ž˜ `APIRouter`๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ `app.include_router()`์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์„œ ์ด๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›๋ž˜ `APIRouter`๋Š” ์ˆ˜์ •๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์กฐ์ง ๋‚ด ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ๋™์ผํ•œ `app/internal/admin.py` ํŒŒ์ผ์„ ๊ณ„์† ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ ์•ฑ์—์„œ `admin` ๋ชจ๋“ˆ์˜ ๊ฐ *path operations*๋Š” ๋‹ค์Œ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:
+
+* prefix `/admin`.
+* tag `admin`.
+* dependency `get_token_header`.
+* ์‘๋‹ต `418`. ๐Ÿต
+
+ํ•˜์ง€๋งŒ ์ด๋Š” ์šฐ๋ฆฌ ์•ฑ์—์„œ ๊ทธ `APIRouter`์—๋งŒ ์˜ํ–ฅ์„ ์ฃผ๋ฉฐ, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋“ค์€ ๊ฐ™์€ `APIRouter`๋ฅผ ๋‹ค๋ฅธ ์ธ์ฆ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### *path operation* ํฌํ•จํ•˜๊ธฐ { #include-a-path-operation }
+
+*path operations*๋ฅผ `FastAPI` ์•ฑ์— ์ง์ ‘ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๊ธฐ์„œ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด... ๊ทธ๋ƒฅ ํ•ด๋ด…๋‹ˆ๋‹ค ๐Ÿคท:
+
+{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
+
+๊ทธ๋ฆฌ๊ณ  `app.include_router()`๋กœ ์ถ”๊ฐ€ํ•œ ๋‹ค๋ฅธ ๋ชจ๋“  *path operations*์™€ ํ•จ๊ป˜ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+**์ฐธ๊ณ **: ์ด๋Š” ๋งค์šฐ ๊ธฐ์ˆ ์ ์ธ ์„ธ๋ถ€์‚ฌํ•ญ์ด๋ผ ์•„๋งˆ **๊ทธ๋ƒฅ ๊ฑด๋„ˆ๋›ฐ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค**.
+
+---
+
+`APIRouter`๋Š” "mount"๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ฉฐ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„๊ณผ ๊ฒฉ๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” OpenAPI ์Šคํ‚ค๋งˆ์™€ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ๊ทธ๋“ค์˜ *path operations*๋ฅผ ํฌํ•จ์‹œํ‚ค๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+๋‚˜๋จธ์ง€์™€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฒฉ๋ฆฌํ•ด "mount"ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, *path operations*๋Š” ์ง์ ‘ ํฌํ•จ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ "clone"(์žฌ์ƒ์„ฑ)๋ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ์ž๋™ API ๋ฌธ์„œ ํ™•์ธํ•˜๊ธฐ { #check-the-automatic-api-docs }
+
+์ด์ œ ์•ฑ์„ ์‹คํ–‰ํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ fastapi dev app/main.py
+
+<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>์—์„œ ๋ฌธ์„œ๋ฅผ ์—ฌ์„ธ์š”.
+
+์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ(๋ฐ prefix)์™€ ์˜ฌ๋ฐ”๋ฅธ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด, ๋ชจ๋“  submodule์˜ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•œ ์ž๋™ API ๋ฌธ์„œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/bigger-applications/image01.png">
+
+## ๊ฐ™์€ router๋ฅผ ๋‹ค๋ฅธ `prefix`๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จํ•˜๊ธฐ { #include-the-same-router-multiple-times-with-different-prefix }
+
+`.include_router()`๋ฅผ ์‚ฌ์šฉํ•ด *๊ฐ™์€* router๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ prefix๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด `/api/v1`๊ณผ `/api/latest`์ฒ˜๋Ÿผ ์„œ๋กœ ๋‹ค๋ฅธ prefix๋กœ ๋™์ผํ•œ API๋ฅผ ๋…ธ์ถœํ•  ๋•Œ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ๊ณ ๊ธ‰ ์‚ฌ์šฉ ๋ฐฉ์‹์ด๋ผ ์‹ค์ œ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ํ•„์š”ํ•  ๋•Œ๋ฅผ ์œ„ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
+
+## `APIRouter`์— ๋‹ค๋ฅธ `APIRouter` ํฌํ•จํ•˜๊ธฐ { #include-an-apirouter-in-another }
+
+`APIRouter`๋ฅผ `FastAPI` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ, ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ด `APIRouter`๋ฅผ ๋‹ค๋ฅธ `APIRouter`์— ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python
+router.include_router(other_router)
+```
+
+`FastAPI` ์•ฑ์— `router`๋ฅผ ํฌํ•จํ•˜๊ธฐ ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ๋ž˜์•ผ `other_router`์˜ *path operations*๋„ ํ•จ๊ป˜ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/tutorial/body-updates.md b/docs/ko/docs/tutorial/body-updates.md
new file mode 100644 (file)
index 0000000..3719e1f
--- /dev/null
@@ -0,0 +1,100 @@
+# Body - ์—…๋ฐ์ดํŠธ { #body-updates }
+
+## `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> ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`jsonable_encoder`๋ฅผ ์‚ฌ์šฉํ•ด ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ ์‹œ). ์˜ˆ๋ฅผ ๋“ค์–ด `datetime`์„ `str`๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
+
+{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
+
+`PUT`์€ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ **๋Œ€์ฒด**ํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+### ๋Œ€์ฒด ์‹œ ์ฃผ์˜์‚ฌํ•ญ { #warning-about-replacing }
+
+์ฆ‰, `PUT`์œผ๋กœ ํ•ญ๋ชฉ `bar`๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ body๋ฅผ ๋ณด๋‚ธ๋‹ค๋ฉด:
+
+```Python
+{
+    "name": "Barz",
+    "price": 3,
+    "description": None,
+}
+```
+
+์ด๋ฏธ ์ €์žฅ๋œ ์†์„ฑ `"tax": 20.2`๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ž…๋ ฅ ๋ชจ๋ธ์€ `"tax": 10.5`๋ผ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๋Š” ๊ทธ โ€œ์ƒˆ๋กœ์šดโ€ `tax` ๊ฐ’ `10.5`๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
+
+## `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> ์ž‘์—…์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ *๋ถ€๋ถ„์ ์œผ๋กœ* ์—…๋ฐ์ดํŠธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” ์—…๋ฐ์ดํŠธํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋ณด๋‚ด๊ณ , ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ ๋‘๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
+
+/// note | ์ฐธ๊ณ 
+
+`PATCH`๋Š” `PUT`๋ณด๋‹ค ๋œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ๋œ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ํŒ€์ด ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ์—๋„ `PUT`๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์—ฌ๋Ÿฌ๋ถ„์€ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ **์ž์œ ๋กญ๊ฒŒ** ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, **FastAPI**๋Š” ์–ด๋–ค ์ œํ•œ๋„ ๊ฐ•์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+๋‹ค๋งŒ ์ด ๊ฐ€์ด๋“œ๋Š” ์˜๋„๋œ ์‚ฌ์šฉ ๋ฐฉ์‹์ด ๋Œ€๋žต ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
+
+///
+
+### Pydantic์˜ `exclude_unset` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ { #using-pydantics-exclude-unset-parameter }
+
+๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด Pydantic ๋ชจ๋ธ์˜ `.model_dump()`์—์„œ `exclude_unset` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ˆ: `item.model_dump(exclude_unset=True)`.
+
+์ด๋Š” `item` ๋ชจ๋ธ์„ ๋งŒ๋“ค ๋•Œ ์‹ค์ œ๋กœ ์„ค์ •๋œ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จํ•˜๋Š” `dict`๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ธฐ๋ณธ๊ฐ’์€ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ ๋‹ค์Œ ์ด๋ฅผ ์‚ฌ์šฉํ•ด (์š”์ฒญ์—์„œ ์ „์†ก๋˜์–ด) ์„ค์ •๋œ ๋ฐ์ดํ„ฐ๋งŒ ํฌํ•จํ•˜๊ณ  ๊ธฐ๋ณธ๊ฐ’์€ ์ƒ๋žตํ•œ `dict`๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
+
+### Pydantic์˜ `update` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉํ•˜๊ธฐ { #using-pydantics-update-parameter }
+
+์ด์ œ `.model_copy()`๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ์กด ๋ชจ๋ธ์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ , ์—…๋ฐ์ดํŠธํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋Š” `dict`๋ฅผ `update` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ: `stored_item_model.model_copy(update=update_data)`:
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
+
+### ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ ์š”์•ฝ { #partial-updates-recap }
+
+์ •๋ฆฌํ•˜๋ฉด, ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:
+
+* (์„ ํƒ ์‚ฌํ•ญ) `PUT` ๋Œ€์‹  `PATCH`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+* ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
+* ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ Pydantic ๋ชจ๋ธ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
+* ์ž…๋ ฅ ๋ชจ๋ธ์—์„œ ๊ธฐ๋ณธ๊ฐ’์ด ์ œ์™ธ๋œ `dict`๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค(`exclude_unset` ์‚ฌ์šฉ).
+    * ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋ธ์˜ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ด๋ฏธ ์ €์žฅ๋œ ๊ฐ’์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ์„ค์ •ํ•œ ๊ฐ’๋งŒ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+* ์ €์žฅ๋œ ๋ชจ๋ธ์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ , ๋ฐ›์€ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋กœ ํ•ด๋‹น ์†์„ฑ๋“ค์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค(`update` ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ).
+* ๋ณต์‚ฌํ•œ ๋ชจ๋ธ์„ DB์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `jsonable_encoder` ์‚ฌ์šฉ).
+    * ์ด๋Š” ๋ชจ๋ธ์˜ `.model_dump()` ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, JSON์œผ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์œผ๋กœ ๊ฐ’์ด ํ™•์‹คํžˆ ๋ณ€ํ™˜๋˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: `datetime` โ†’ `str`).
+* ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
+* ์—…๋ฐ์ดํŠธ๋œ ๋ชจ๋ธ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}
+
+/// tip | ํŒ
+
+๋™์ผํ•œ ๊ธฐ๋ฒ•์„ HTTP `PUT` ์ž‘์—…์—์„œ๋„ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์˜ ์˜ˆ์‹œ๋Š” ์ด๋Ÿฐ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ `PATCH`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+/// note | ์ฐธ๊ณ 
+
+์ž…๋ ฅ ๋ชจ๋ธ์€ ์—ฌ์ „ํžˆ ๊ฒ€์ฆ๋œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.
+
+๋”ฐ๋ผ์„œ ๋ชจ๋“  ์†์„ฑ์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด, ๋ชจ๋“  ์†์„ฑ์ด optional๋กœ ํ‘œ์‹œ๋œ(๊ธฐ๋ณธ๊ฐ’์„ ๊ฐ€์ง€๊ฑฐ๋‚˜ `None`์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๊ฐ€์ง€๋Š”) ๋ชจ๋ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+**์—…๋ฐ์ดํŠธ**๋ฅผ ์œ„ํ•œ โ€œ๋ชจ๋“  ๊ฐ’์ด optional์ธโ€ ๋ชจ๋ธ๊ณผ, **์ƒ์„ฑ**์„ ์œ„ํ•œ โ€œํ•„์ˆ˜ ๊ฐ’์ด ์žˆ๋Š”โ€ ๋ชจ๋ธ์„ ๊ตฌ๋ถ„ํ•˜๋ ค๋ฉด [์ถ”๊ฐ€ ๋ชจ๋ธ](extra-models.md){.internal-link target=_blank}์— ์„ค๋ช…๋œ ์•„์ด๋””์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
diff --git a/docs/ko/docs/tutorial/dependencies/sub-dependencies.md b/docs/ko/docs/tutorial/dependencies/sub-dependencies.md
new file mode 100644 (file)
index 0000000..d81ccf0
--- /dev/null
@@ -0,0 +1,105 @@
+# ํ•˜์œ„ ์˜์กด์„ฑ { #sub-dependencies }
+
+**ํ•˜์œ„ ์˜์กด์„ฑ**์„ ๊ฐ€์ง€๋Š” ์˜์กด์„ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•„์š”ํ•œ ๋งŒํผ **๊นŠ๊ฒŒ** ์ค‘์ฒฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ์ผ์€ **FastAPI**๊ฐ€ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+## ์ฒซ ๋ฒˆ์งธ ์˜์กด์„ฑ "dependable" { #first-dependency-dependable }
+
+๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒซ ๋ฒˆ์งธ ์˜์กด์„ฑ("dependable")์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *}
+
+์ด ์˜์กด์„ฑ์€ ์„ ํƒ์  ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ `q`๋ฅผ `str`๋กœ ์„ ์–ธํ•˜๊ณ , ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+๋งค์šฐ ๋‹จ์ˆœํ•œ ์˜ˆ์‹œ(๊ทธ๋‹ค์ง€ ์œ ์šฉํ•˜์ง„ ์•Š์Œ)์ด์ง€๋งŒ, ํ•˜์œ„ ์˜์กด์„ฑ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€์— ์ง‘์ค‘ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.
+
+## ๋‘ ๋ฒˆ์งธ ์˜์กด์„ฑ "dependable"๊ณผ "dependant" { #second-dependency-dependable-and-dependant }
+
+๊ทธ๋‹ค์Œ, ๋˜ ๋‹ค๋ฅธ ์˜์กด์„ฑ ํ•จ์ˆ˜("dependable")๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ•จ์ˆ˜๋Š” ๋™์‹œ์— ์ž๊ธฐ ์ž์‹ ์˜ ์˜์กด์„ฑ๋„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋ž˜์„œ "dependant"์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค):
+
+{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *}
+
+์„ ์–ธ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:
+
+* ์ด ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ์˜์กด์„ฑ("dependable")์ด์ง€๋งŒ, ๋‹ค๋ฅธ ์˜์กด์„ฑ๋„ ํ•˜๋‚˜ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค(์ฆ‰, ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€์— "์˜์กด"ํ•ฉ๋‹ˆ๋‹ค).
+    * `query_extractor`์— ์˜์กดํ•˜๋ฉฐ, ๊ทธ ๋ฐ˜ํ™˜๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ `q`์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.
+* ๋˜ํ•œ ์„ ํƒ์  `last_query` ์ฟ ํ‚ค๋ฅผ `str`๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
+    * ์‚ฌ์šฉ์ž๊ฐ€ ์ฟผ๋ฆฌ `q`๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ด์ „์— ์ฟ ํ‚ค์— ์ €์žฅํ•ด ๋‘” ๋งˆ์ง€๋ง‰ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+## ์˜์กด์„ฑ ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-dependency }
+
+๊ทธ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *}
+
+/// info | ์ •๋ณด
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์—์„œ๋Š” `query_or_cookie_extractor`๋ผ๋Š” ์˜์กด์„ฑ ํ•˜๋‚˜๋งŒ ์„ ์–ธํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.
+
+ํ•˜์ง€๋งŒ **FastAPI**๋Š” `query_or_cookie_extractor`๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋™์•ˆ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด, ๋จผ์ € `query_extractor`๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+```mermaid
+graph TB
+
+query_extractor(["query_extractor"])
+query_or_cookie_extractor(["query_or_cookie_extractor"])
+
+read_query["/items/"]
+
+query_extractor --> query_or_cookie_extractor --> read_query
+```
+
+## ๊ฐ™์€ ์˜์กด์„ฑ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๊ธฐ { #using-the-same-dependency-multiple-times }
+
+๊ฐ™์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์— ๋Œ€ํ•ด ์˜์กด์„ฑ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์„ ์–ธ๋˜๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์—ฌ๋Ÿฌ ์˜์กด์„ฑ์ด ๊ณตํ†ต ํ•˜์œ„ ์˜์กด์„ฑ์„ ๊ฐ–๋Š” ๊ฒฝ์šฐ), **FastAPI**๋Š” ๊ทธ ํ•˜์œ„ ์˜์กด์„ฑ์„ ์š”์ฒญ๋‹น ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ์š”์ฒญ์— ๋Œ€ํ•ด ๋™์ผํ•œ ์˜์กด์„ฑ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹ , ๋ฐ˜ํ™˜๊ฐ’์„ <abbr title="๊ณ„์‚ฐ/์ƒ์„ฑ๋œ ๊ฐ’์„ ์ €์žฅํ•ด ๋‘์—ˆ๋‹ค๊ฐ€, ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ/์‹œ์Šคํ…œ.">"cache"</abbr>์— ์ €์žฅํ•˜๊ณ , ๊ทธ ์š”์ฒญ์—์„œ ํ•ด๋‹น ๊ฐ’์ด ํ•„์š”ํ•œ ๋ชจ๋“  "dependants"์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
+
+๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ, ๊ฐ™์€ ์š”์ฒญ์—์„œ "cached" ๊ฐ’์„ ์“ฐ๋Š” ๋Œ€์‹  ๋งค ๋‹จ๊ณ„๋งˆ๋‹ค(์•„๋งˆ๋„ ์—ฌ๋Ÿฌ ๋ฒˆ) ์˜์กด์„ฑ์ด ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด, `Depends`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ `use_cache=False` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+//// tab | Python 3.9+
+
+```Python hl_lines="1"
+async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
+    return {"fresh_value": fresh_value}
+```
+
+////
+
+//// tab | Python 3.9+ ๋น„ Annotated
+
+/// tip | ํŒ
+
+๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด `Annotated` ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+```Python hl_lines="1"
+async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
+    return {"fresh_value": fresh_value}
+```
+
+////
+
+## ์ •๋ฆฌ { #recap }
+
+์—ฌ๊ธฐ์„œ ์‚ฌ์šฉํ•œ ๊ทธ๋Ÿด๋“ฏํ•œ ์šฉ์–ด๋“ค์„ ์ œ์™ธํ•˜๋ฉด, **Dependency Injection** ์‹œ์Šคํ…œ์€ ๊ฝค ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค.
+
+*๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์™€ ๊ฐ™์€ ํ˜•ํƒœ์˜ ํ•จ์ˆ˜๋“ค์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๋ฉฐ, ์ž„์˜๋กœ ๊นŠ๊ฒŒ ์ค‘์ฒฉ๋œ ์˜์กด์„ฑ "๊ทธ๋ž˜ํ”„"(ํŠธ๋ฆฌ)๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+์ด ๋‹จ์ˆœํ•œ ์˜ˆ์‹œ๋งŒ ๋ณด๋ฉด ๊ทธ๋‹ค์ง€ ์œ ์šฉํ•ด ๋ณด์ด์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ **๋ณด์•ˆ**์— ๊ด€ํ•œ ์ฑ•ํ„ฐ์—์„œ ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์œ ์šฉํ•œ์ง€ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์•„๊ปด์ฃผ๋Š”์ง€๋„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
diff --git a/docs/ko/docs/tutorial/handling-errors.md b/docs/ko/docs/tutorial/handling-errors.md
new file mode 100644 (file)
index 0000000..7cc37e8
--- /dev/null
@@ -0,0 +1,244 @@
+# ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ { #handling-errors }
+
+API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜๋ฅผ ์•Œ๋ ค์•ผ ํ•˜๋Š” ์ƒํ™ฉ์€ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ํด๋ผ์ด์–ธํŠธ๋Š” ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์žˆ๋Š” ๋ธŒ๋ผ์šฐ์ €์ผ ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ๊ณ , IoT ์žฅ์น˜์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํด๋ผ์ด์–ธํŠธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ์•Œ๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ถฉ๋ถ„ํ•œ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.
+* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
+* ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•œ ํ•ญ๋ชฉ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+* ๋“ฑ๋“ฑ.
+
+์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ณดํ†ต **400**๋ฒˆ๋Œ€(400์—์„œ 499) ๋ฒ”์œ„์˜ **HTTP ์ƒํƒœ ์ฝ”๋“œ**๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Š” 200๋ฒˆ๋Œ€ HTTP ์ƒํƒœ ์ฝ”๋“œ(200์—์„œ 299)์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. "200" ์ƒํƒœ ์ฝ”๋“œ๋Š” ์–ด๋–ค ํ˜•ํƒœ๋กœ๋“  ์š”์ฒญ์ด "์„ฑ๊ณต"ํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
+
+400๋ฒˆ๋Œ€ ์ƒํƒœ ์ฝ”๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
+
+**"404 Not Found"** ์˜ค๋ฅ˜(๊ทธ๋ฆฌ๊ณ  ๋†๋‹ด๋“ค)๋„ ๋‹ค๋“ค ๊ธฐ์–ตํ•˜์‹œ์ฃ ?
+
+## `HTTPException` ์‚ฌ์šฉํ•˜๊ธฐ { #use-httpexception }
+
+ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜๊ฐ€ ํฌํ•จ๋œ HTTP ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด `HTTPException`์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+### `HTTPException` ๊ฐ€์ ธ์˜ค๊ธฐ { #import-httpexception }
+
+{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
+
+### ์ฝ”๋“œ์—์„œ `HTTPException` ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ { #raise-an-httpexception-in-your-code }
+
+`HTTPException`์€ API์™€ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง„ ์ผ๋ฐ˜์ ์ธ Python ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค.
+
+Python ์˜ˆ์™ธ์ด๋ฏ€๋กœ `return` ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ `raise` ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋Š” ๋˜ํ•œ, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜* ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ ์•ˆ์—์„œ `HTTPException`์„ `raise`ํ•˜๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ ํ•ด๋‹น ์š”์ฒญ์ด ์ข…๋ฃŒ๋˜๋ฉฐ `HTTPException`์˜ HTTP ์˜ค๋ฅ˜๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
+
+๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์˜ ์ด์ ์€ ์˜์กด์„ฑ๊ณผ ๋ณด์•ˆ์— ๋Œ€ํ•œ ์„น์…˜์—์„œ ๋” ๋ถ„๋ช…ํ•ด์ง‘๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š”, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ID๋กœ ํ•ญ๋ชฉ์„ ์š”์ฒญํ•˜๋ฉด ์ƒํƒœ ์ฝ”๋“œ `404`๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
+
+### ๊ฒฐ๊ณผ ์‘๋‹ต { #the-resulting-response }
+
+ํด๋ผ์ด์–ธํŠธ๊ฐ€ `http://example.com/items/foo`( `item_id` `"foo"`)๋ฅผ ์š”์ฒญํ•˜๋ฉด, HTTP ์ƒํƒœ ์ฝ”๋“œ 200๊ณผ ๋‹ค์Œ JSON ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค:
+
+```JSON
+{
+  "item": "The Foo Wrestlers"
+}
+```
+
+ํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ `http://example.com/items/bar`(์กด์žฌํ•˜์ง€ ์•Š๋Š” `item_id` `"bar"`)๋ฅผ ์š”์ฒญํ•˜๋ฉด, HTTP ์ƒํƒœ ์ฝ”๋“œ 404("not found" ์˜ค๋ฅ˜)์™€ ๋‹ค์Œ JSON ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค:
+
+```JSON
+{
+  "detail": "Item not found"
+}
+```
+
+/// tip | ํŒ
+
+`HTTPException`์„ ๋ฐœ์ƒ์‹œํ‚ฌ ๋•Œ `detail` ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ `str`๋งŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, JSON์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋–ค ๊ฐ’์ด๋“  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+`dict`, `list` ๋“ฑ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋“ค์€ **FastAPI**๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด JSON์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## ์ปค์Šคํ…€ ํ—ค๋” ์ถ”๊ฐ€ํ•˜๊ธฐ { #add-custom-headers }
+
+HTTP ์˜ค๋ฅ˜์— ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์œ ์šฉํ•œ ์ƒํ™ฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ๋ณด์•ˆ ์œ ํ˜•์—์„œ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค.
+
+์•„๋งˆ ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ•„์š”ํ•˜๋‹ค๋ฉด ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
+
+## ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์„ค์น˜ํ•˜๊ธฐ { #install-custom-exception-handlers }
+
+<a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">Starlette์˜ ๋™์ผํ•œ ์˜ˆ์™ธ ์œ ํ‹ธ๋ฆฌํ‹ฐ</a>๋ฅผ ์‚ฌ์šฉํ•ด ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์—ฌ๋Ÿฌ๋ถ„(๋˜๋Š” ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์ด `raise`ํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ์˜ˆ์™ธ `UnicornException`์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ด ์˜ˆ์™ธ๋ฅผ FastAPI์—์„œ ์ „์—ญ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค.
+
+`@app.exception_handler()`๋กœ ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
+
+์—ฌ๊ธฐ์„œ `/unicorns/yolo`๋ฅผ ์š”์ฒญํ•˜๋ฉด, *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๊ฐ€ `UnicornException`์„ `raise`ํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `unicorn_exception_handler`๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ HTTP ์ƒํƒœ ์ฝ”๋“œ `418`๊ณผ ๋‹ค์Œ JSON ๋‚ด์šฉ์„ ๊ฐ€์ง„ ๊น”๋”ํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:
+
+```JSON
+{"message": "Oops! yolo did something. There goes a rainbow..."}
+```
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+`from starlette.requests import Request`์™€ `from starlette.responses import JSONResponse`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด `starlette.responses`๋ฅผ `fastapi.responses`๋กœ๋„ ๋™์ผํ•˜๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์‘๋‹ต์€ Starlette์—์„œ ์ง์ ‘ ์˜ต๋‹ˆ๋‹ค. `Request`๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
+
+///
+
+## ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-default-exception-handlers }
+
+**FastAPI**์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ํ•ธ๋“ค๋Ÿฌ๋“ค์€ `HTTPException`์„ `raise`ํ–ˆ์„ ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ์š”์ฒญ์— ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ๊ธฐ๋ณธ JSON ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋“ค์„ ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ฒƒ์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์š”์ฒญ ๊ฒ€์ฆ ์˜ˆ์™ธ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-request-validation-exceptions }
+
+์š”์ฒญ์— ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜๋ฉด, **FastAPI**๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ `RequestValidationError`๋ฅผ `raise`ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ์ด์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋ ค๋ฉด `RequestValidationError`๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , `@app.exception_handler(RequestValidationError)`๋กœ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ฐ์ฝ”๋ ˆ์ดํŠธํ•ด ์‚ฌ์šฉํ•˜์„ธ์š”.
+
+์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋Š” `Request`์™€ ์˜ˆ์™ธ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
+
+์ด์ œ `/items/foo`๋กœ ์ด๋™ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ JSON ์˜ค๋ฅ˜ ๋Œ€์‹ :
+
+```JSON
+{
+    "detail": [
+        {
+            "loc": [
+                "path",
+                "item_id"
+            ],
+            "msg": "value is not a valid integer",
+            "type": "type_error.integer"
+        }
+    ]
+}
+```
+
+๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ…์ŠคํŠธ ๋ฒ„์ „์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:
+
+```
+Validation errors:
+Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
+```
+
+### `HTTPException` ์˜ค๋ฅ˜ ํ•ธ๋“ค๋Ÿฌ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๊ธฐ { #override-the-httpexception-error-handler }
+
+๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ `HTTPException` ํ•ธ๋“ค๋Ÿฌ๋„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Ÿฐ ์˜ค๋ฅ˜๋“ค์— ๋Œ€ํ•ด JSON ๋Œ€์‹  ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
+
+/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+`from starlette.responses import PlainTextResponse`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด `starlette.responses`๋ฅผ `fastapi.responses`๋กœ๋„ ๋™์ผํ•˜๊ฒŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์‘๋‹ต์€ Starlette์—์„œ ์ง์ ‘ ์˜ต๋‹ˆ๋‹ค.
+
+///
+
+/// warning | ๊ฒฝ๊ณ 
+
+`RequestValidationError`์—๋Š” ๊ฒ€์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ์ค„ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์–ด, ์›ํ•œ๋‹ค๋ฉด ๊ด€๋ จ ์ •๋ณด์™€ ํ•จ๊ป˜ ๋กœ๊ทธ์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์œ ๋…ํ•˜์„ธ์š”.
+
+ํ•˜์ง€๋งŒ ์ด๋Š” ๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด ๊ทธ ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์ผ๋ถ€ ์ •๋ณด๋ฅผ ๋ˆ„์„คํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ์˜ ์ฝ”๋“œ๋Š” ๊ฐ ์˜ค๋ฅ˜๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์ถ”์ถœํ•ด ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
+
+///
+
+### `RequestValidationError`์˜ body ์‚ฌ์šฉํ•˜๊ธฐ { #use-the-requestvalidationerror-body }
+
+`RequestValidationError`์—๋Š” ์œ ํšจํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๋ฐ›์€ `body`๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
+
+์•ฑ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋™์•ˆ body๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ธฐ๊ณ  ๋””๋ฒ„๊ทธํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋“ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
+
+์ด์ œ ๋‹ค์Œ์ฒ˜๋Ÿผ ์œ ํšจํ•˜์ง€ ์•Š์€ item์„ ๋ณด๋‚ด๋ณด์„ธ์š”:
+
+```JSON
+{
+  "title": "towel",
+  "size": "XL"
+}
+```
+
+๋ฐ›์€ body๋ฅผ ํฌํ•จํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๋Š” ์‘๋‹ต์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:
+
+```JSON hl_lines="12-15"
+{
+  "detail": [
+    {
+      "loc": [
+        "body",
+        "size"
+      ],
+      "msg": "value is not a valid integer",
+      "type": "type_error.integer"
+    }
+  ],
+  "body": {
+    "title": "towel",
+    "size": "XL"
+  }
+}
+```
+
+#### FastAPI์˜ `HTTPException` vs Starlette์˜ `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception }
+
+**FastAPI**์—๋Š” ์ž์ฒด `HTTPException`์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  **FastAPI**์˜ `HTTPException` ์˜ค๋ฅ˜ ํด๋ž˜์Šค๋Š” Starlette์˜ `HTTPException` ์˜ค๋ฅ˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค.
+
+์œ ์ผํ•œ ์ฐจ์ด๋Š” **FastAPI**์˜ `HTTPException`์€ `detail` ํ•„๋“œ์— JSON์œผ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋“  ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด, Starlette์˜ `HTTPException`์€ ๋ฌธ์ž์—ด๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์ฝ”๋“œ์—์„œ๋Š” ํ‰์†Œ์ฒ˜๋Ÿผ **FastAPI**์˜ `HTTPException`์„ ๊ณ„์† `raise`ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ๋Š” Starlette์˜ `HTTPException`์— ๋Œ€ํ•ด ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Starlette ๋‚ด๋ถ€ ์ฝ”๋“œ์˜ ์–ด๋–ค ๋ถ€๋ถ„, ๋˜๋Š” Starlette ํ™•์žฅ/ํ”Œ๋Ÿฌ๊ทธ์ธ์ด Starlette `HTTPException`์„ `raise`ํ•˜๋”๋ผ๋„, ์—ฌ๋Ÿฌ๋ถ„์˜ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ด๋ฅผ ์žก์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋™์ผํ•œ ์ฝ”๋“œ์—์„œ ๋‘ `HTTPException`์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก, Starlette์˜ ์˜ˆ์™ธ๋ฅผ `StarletteHTTPException`์œผ๋กœ ์ด๋ฆ„์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค:
+
+```Python
+from starlette.exceptions import HTTPException as StarletteHTTPException
+```
+
+### **FastAPI**์˜ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ { #reuse-fastapis-exception-handlers }
+
+์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ **FastAPI**์˜ ๋™์ผํ•œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, `fastapi.exception_handlers`์—์„œ ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ ธ์™€ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
+
+์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค์šฐ ํ‘œํ˜„๋ ฅ ์žˆ๋Š” ๋ฉ”์‹œ์ง€๋กœ ์˜ค๋ฅ˜๋ฅผ ์ถœ๋ ฅ๋งŒ ํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์š”์ง€๋Š” ์ดํ•ดํ•˜์…จ์„ ๊ฒ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๋ฅผ ์‚ฌ์šฉํ•œ ๋’ค ๊ธฐ๋ณธ ์˜ˆ์™ธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/tutorial/security/first-steps.md b/docs/ko/docs/tutorial/security/first-steps.md
new file mode 100644 (file)
index 0000000..4c9181b
--- /dev/null
@@ -0,0 +1,203 @@
+# ๋ณด์•ˆ - ์ฒซ ๋‹จ๊ณ„ { #security-first-steps }
+
+์–ด๋–ค ๋„๋ฉ”์ธ์— **backend** API๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์— **frontend**๊ฐ€ ์žˆ๊ฑฐ๋‚˜, ๊ฐ™์€ ๋„๋ฉ”์ธ์˜ ๋‹ค๋ฅธ ๊ฒฝ๋กœ์— ์žˆ๊ฑฐ๋‚˜(๋˜๋Š” ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+๊ทธ๋ฆฌ๊ณ  frontend๊ฐ€ **username**๊ณผ **password**๋ฅผ ์‚ฌ์šฉํ•ด backend์— ์ธ์ฆํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค.
+
+**FastAPI**์™€ ํ•จ๊ป˜ **OAuth2**๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ํ•„์š”ํ•œ ์ž‘์€ ์ •๋ณด ์กฐ๊ฐ๋“ค์„ ์ฐพ๊ธฐ ์œ„ํ•ด ๊ธธ๊ณ  ๊ธด ์ „์ฒด ์ŠคํŽ™์„ ์ฝ๋А๋ผ ์‹œ๊ฐ„์„ ์“ฐ์ง€ ์•Š๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด **FastAPI**๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋„๊ตฌ๋“ค์„ ์‚ฌ์šฉํ•ด ๋ด…์‹œ๋‹ค.
+
+## ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ { #how-it-looks }
+
+๋จผ์ € ์ฝ”๋“œ๋ฅผ ๊ทธ๋ƒฅ ์‚ฌ์šฉํ•ด์„œ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋ณด๊ณ , ๊ทธ๋‹ค์Œ์— ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์ดํ•ดํ•˜๋Ÿฌ ๋‹ค์‹œ ๋Œ์•„์˜ค๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## `main.py` ๋งŒ๋“ค๊ธฐ { #create-main-py }
+
+์˜ˆ์ œ๋ฅผ ํŒŒ์ผ `main.py`์— ๋ณต์‚ฌํ•˜์„ธ์š”:
+
+{* ../../docs_src/security/tutorial001_an_py39.py *}
+
+## ์‹คํ–‰ํ•˜๊ธฐ { #run-it }
+
+/// info | ์ •๋ณด
+
+<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> ํŒจํ‚ค์ง€๋Š” `pip install "fastapi[standard]"` ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ฉด **FastAPI**์™€ ํ•จ๊ป˜ ์ž๋™์œผ๋กœ ์„ค์น˜๋ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ `pip install fastapi` ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๋ฉด `python-multipart` ํŒจํ‚ค์ง€๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
+
+์ˆ˜๋™์œผ๋กœ ์„ค์น˜ํ•˜๋ ค๋ฉด, [๊ฐ€์ƒ ํ™˜๊ฒฝ](../../virtual-environments.md){.internal-link target=_blank}์„ ๋งŒ๋“ค๊ณ  ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ, ์•„๋ž˜๋กœ ์„ค์น˜ํ•˜์„ธ์š”:
+
+```console
+$ pip install python-multipart
+```
+
+์ด๋Š” **OAuth2**๊ฐ€ `username`๊ณผ `password`๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด "form data"๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+///
+
+๋‹ค์Œ์œผ๋กœ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”:
+
+<div class="termy">
+
+```console
+$ fastapi dev main.py
+
+<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+</div>
+
+## ํ™•์ธํ•˜๊ธฐ { #check-it }
+
+๋Œ€ํ™”ํ˜• ๋ฌธ์„œ๋กœ ์ด๋™ํ•˜์„ธ์š”: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
+
+๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ ํ™”๋ฉด์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/security/image01.png">
+
+/// check | Authorize ๋ฒ„ํŠผ!
+
+๋ฐ˜์ง์ด๋Š” ์ƒˆ "Authorize" ๋ฒ„ํŠผ์ด ์ด๋ฏธ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*์—๋Š” ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ์— ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์€ ์ž๋ฌผ์‡ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ํด๋ฆญํ•˜๋ฉด `username`๊ณผ `password`(๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์„ ํƒ์  ํ•„๋“œ๋“ค)๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์€ ์ธ์ฆ ํผ์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/security/image02.png">
+
+/// note | ์ฐธ๊ณ 
+
+ํผ์— ๋ฌด์—‡์„ ์ž…๋ ฅํ•˜๋“  ์•„์ง์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ณง ์—ฌ๊ธฐ๊นŒ์ง€ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+///
+
+๋ฌผ๋ก  ์ด๊ฒƒ์€ ์ตœ์ข… ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ frontend๋Š” ์•„๋‹ˆ์ง€๋งŒ, ๋ชจ๋“  API๋ฅผ ๋Œ€ํ™”ํ˜•์œผ๋กœ ๋ฌธ์„œํ™”ํ•˜๋Š” ํ›Œ๋ฅญํ•œ ์ž๋™ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.
+
+frontend ํŒ€(๊ทธ๊ฒŒ ๋ณธ์ธ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค)์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์„œ๋“œํŒŒํ‹ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์‹œ์Šคํ…œ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋™์ผํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋””๋ฒ„๊ทธํ•˜๊ณ , ํ™•์ธํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋ณธ์ธ์ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+## `password` ํ”Œ๋กœ์šฐ { #the-password-flow }
+
+์ด์ œ ์กฐ๊ธˆ ๋Œ์•„๊ฐ€์„œ ์ด๊ฒƒ๋“ค์ด ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•ด ๋ด…์‹œ๋‹ค.
+
+`password` "flow"๋Š” ๋ณด์•ˆ๊ณผ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด OAuth2์—์„œ ์ •์˜ํ•œ ์—ฌ๋Ÿฌ ๋ฐฉ์‹("flows") ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
+
+OAuth2๋Š” backend ๋˜๋Š” API๊ฐ€ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๋Š” ์„œ๋ฒ„์™€ ๋…๋ฆฝ์ ์ผ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ์—๋Š” ๊ฐ™์€ **FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด API์™€ ์ธ์ฆ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ, ๋‹จ์ˆœํ™”๋œ ๊ด€์ ์—์„œ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๋ฉด:
+
+* ์‚ฌ์šฉ์ž๊ฐ€ frontend์—์„œ `username`๊ณผ `password`๋ฅผ ์ž…๋ ฅํ•˜๊ณ  `Enter`๋ฅผ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.
+* frontend(์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋จ)๋Š” ํ•ด๋‹น `username`๊ณผ `password`๋ฅผ ์šฐ๋ฆฌ API์˜ ํŠน์ • URL๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค(`tokenUrl="token"`๋กœ ์„ ์–ธ๋จ).
+* API๋Š” `username`๊ณผ `password`๋ฅผ ํ™•์ธํ•˜๊ณ  "token"์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค(์•„์ง ์•„๋ฌด๊ฒƒ๋„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค).
+    * "token"์€ ๋‚˜์ค‘์— ์ด ์‚ฌ์šฉ์ž๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋–ค ๋‚ด์šฉ์ด ๋‹ด๊ธด ๋ฌธ์ž์—ด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.
+    * ๋ณดํ†ต token์€ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ๋งŒ๋ฃŒ๋˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
+        * ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๋Š” ๋‚˜์ค‘์— ์–ด๋А ์‹œ์ ์—” ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+        * ๊ทธ๋ฆฌ๊ณ  token์ด ๋„๋‚œ๋‹นํ•˜๋”๋ผ๋„ ์œ„ํ—˜์ด ๋” ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์˜๊ตฌ์ ์œผ๋กœ ํ•ญ์ƒ ๋™์ž‘ํ•˜๋Š” ํ‚ค์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
+* frontend๋Š” ๊ทธ token์„ ์ž„์‹œ๋กœ ์–ด๋”˜๊ฐ€์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
+* ์‚ฌ์šฉ์ž๊ฐ€ frontend์—์„œ ํด๋ฆญํ•ด์„œ frontend ์›น ์•ฑ์˜ ๋‹ค๋ฅธ ์„น์…˜์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
+* frontend๋Š” API์—์„œ ๋” ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.
+    * ํ•˜์ง€๋งŒ ๊ทธ ํŠน์ • endpoint์—๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
+    * ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ API์— ์ธ์ฆํ•˜๊ธฐ ์œ„ํ•ด `Authorization` ํ—ค๋”๋ฅผ, ๊ฐ’์€ `Bearer `์— token์„ ๋”ํ•œ ํ˜•ํƒœ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
+    * token์— `foobar`๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค๋ฉด `Authorization` ํ—ค๋”์˜ ๋‚ด์šฉ์€ `Bearer foobar`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
+
+## **FastAPI**์˜ `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer }
+
+**FastAPI**๋Š” ์ด๋Ÿฐ ๋ณด์•ˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด, ์„œ๋กœ ๋‹ค๋ฅธ ์ถ”์ƒํ™” ์ˆ˜์ค€์—์„œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ์˜ˆ์ œ์—์„œ๋Š” **OAuth2**์˜ **Password** ํ”Œ๋กœ์šฐ์™€ **Bearer** token์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด `OAuth2PasswordBearer` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+"bearer" token๋งŒ์ด ์œ ์ผํ•œ ์„ ํƒ์ง€๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์„ ํƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ OAuth2 ์ „๋ฌธ๊ฐ€๋กœ์„œ ์™œ ๋‹ค๋ฅธ ์˜ต์…˜์ด ๋” ์ ํ•ฉํ•œ์ง€ ์ •ํ™•ํžˆ ์•„๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋„ ๊ฐ€์žฅ ์ ํ•ฉํ•  ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค.
+
+๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด์„œ๋„ **FastAPI**๋Š” ์ด๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+`OAuth2PasswordBearer` ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ `tokenUrl` ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ํด๋ผ์ด์–ธํŠธ(์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” frontend)๊ฐ€ token์„ ๋ฐ›๊ธฐ ์œ„ํ•ด `username`๊ณผ `password`๋ฅผ ๋ณด๋‚ผ URL์ด ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
+
+/// tip | ํŒ
+
+์—ฌ๊ธฐ์„œ `tokenUrl="token"`์€ ์•„์ง ๋งŒ๋“ค์ง€ ์•Š์€ ์ƒ๋Œ€ URL `token`์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์ƒ๋Œ€ URL์ด๋ฏ€๋กœ `./token`๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
+
+์ƒ๋Œ€ 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} ๊ฐ™์€ ๊ณ ๊ธ‰ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ณ„์† ๋™์ž‘ํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ทธ endpoint / *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ*๋ฅผ ๋งŒ๋“ค์ง€๋Š” ์•Š์ง€๋งŒ, URL `/token`์ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ token์„ ์–ป๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ด์•ผ ํ•  URL์ด๋ผ๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋Š” OpenAPI์— ์‚ฌ์šฉ๋˜๊ณ , ์ด์–ด์„œ ๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ ์‹œ์Šคํ…œ์—์„œ๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
+
+๊ณง ์‹ค์ œ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+/// info | ์ •๋ณด
+
+์—„๊ฒฉํ•œ "Pythonista"๋ผ๋ฉด `token_url` ๋Œ€์‹  `tokenUrl` ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„ ์Šคํƒ€์ผ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋Š” OpenAPI ์ŠคํŽ™์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ๋งž์ถ˜ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๋ณด์•ˆ ์Šคํ‚ด์— ๋Œ€ํ•ด ๋” ์กฐ์‚ฌํ•ด์•ผ ํ•  ๋•Œ, ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ ๋„ฃ์–ด ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+`oauth2_scheme` ๋ณ€์ˆ˜๋Š” `OAuth2PasswordBearer`์˜ ์ธ์Šคํ„ด์Šค์ด์ง€๋งŒ, "callable"์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
+
+๋‹ค์Œ์ฒ˜๋Ÿผ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+```Python
+oauth2_scheme(some, parameters)
+```
+
+๋”ฐ๋ผ์„œ `Depends`์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+### ์‚ฌ์šฉํ•˜๊ธฐ { #use-it }
+
+์ด์ œ `Depends`๋กœ `oauth2_scheme`๋ฅผ ์˜์กด์„ฑ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
+
+์ด ์˜์กด์„ฑ์€ `str`์„ ์ œ๊ณตํ•˜๊ณ , ๊ทธ ๊ฐ’์€ *๊ฒฝ๋กœ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜*์˜ ํŒŒ๋ผ๋ฏธํ„ฐ `token`์— ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.
+
+**FastAPI**๋Š” ์ด ์˜์กด์„ฑ์„ ์‚ฌ์šฉํ•ด OpenAPI ์Šคํ‚ค๋งˆ(๋ฐ ์ž๋™ API ๋ฌธ์„œ)์— "security scheme"๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
+
+/// info | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
+
+**FastAPI**๋Š” (์˜์กด์„ฑ์— ์„ ์–ธ๋œ) `OAuth2PasswordBearer` ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด OpenAPI์—์„œ ๋ณด์•ˆ ์Šคํ‚ด์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” `OAuth2PasswordBearer`๊ฐ€ `fastapi.security.oauth2.OAuth2`๋ฅผ ์ƒ์†ํ•˜๊ณ , ์ด๊ฒƒ์ด ๋‹ค์‹œ `fastapi.security.base.SecurityBase`๋ฅผ ์ƒ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
+
+OpenAPI(๋ฐ ์ž๋™ API ๋ฌธ์„œ)์™€ ํ†ตํ•ฉ๋˜๋Š” ๋ชจ๋“  ๋ณด์•ˆ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” `SecurityBase`๋ฅผ ์ƒ์†ํ•˜๋ฉฐ, ๊ทธ๋ž˜์„œ **FastAPI**๊ฐ€ ์ด๋ฅผ OpenAPI์— ์–ด๋–ป๊ฒŒ ํ†ตํ•ฉํ• ์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ { #what-it-does }
+
+์š”์ฒญ์—์„œ `Authorization` ํ—ค๋”๋ฅผ ์ฐพ์•„, ๊ฐ’์ด `Bearer `์— ์–ด๋–ค token์ด ๋ถ™์€ ํ˜•ํƒœ์ธ์ง€ ํ™•์ธํ•œ ๋’ค, ๊ทธ token์„ `str`๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
+
+`Authorization` ํ—ค๋”๊ฐ€ ์—†๊ฑฐ๋‚˜, ๊ฐ’์— `Bearer ` token์ด ์—†๋‹ค๋ฉด, ๊ณง๋ฐ”๋กœ 401 ์ƒํƒœ ์ฝ”๋“œ ์˜ค๋ฅ˜(`UNAUTHORIZED`)๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
+
+์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด token์ด ์กด์žฌํ•˜๋Š”์ง€ ์ง์ ‘ ํ™•์ธํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์—ˆ๋‹ค๋ฉด ๊ทธ token์—๋Š” `str`์ด ๋“ค์–ด ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์—์„œ ์ด๋ฏธ ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+
+<img src="/img/tutorial/security/image03.png">
+
+์•„์ง token์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜์ง„ ์•Š์ง€๋งŒ, ์ด๊ฒƒ๋งŒ์œผ๋กœ๋„ ์‹œ์ž‘์€ ๋œ ์…ˆ์ž…๋‹ˆ๋‹ค.
+
+## ์š”์•ฝ { #recap }
+
+์ฆ‰, ์ถ”๊ฐ€๋กœ 3~4์ค„๋งŒ์œผ๋กœ๋„ ์ด๋ฏธ ์›์‹œ์ ์ธ ํ˜•ํƒœ์˜ ๋ณด์•ˆ์„ ๊ฐ–์ถ”๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
diff --git a/docs/ko/docs/tutorial/security/index.md b/docs/ko/docs/tutorial/security/index.md
new file mode 100644 (file)
index 0000000..2320b06
--- /dev/null
@@ -0,0 +1,106 @@
+# ๋ณด์•ˆ { #security }
+
+๋ณด์•ˆ, ์ธ์ฆ(authentication), ์ธ๊ฐ€(authorization)๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค.
+
+๊ทธ๋ฆฌ๊ณ  ๋ณดํ†ต ๋ณต์žกํ•˜๊ณ  "์–ด๋ ค์šด" ์ฃผ์ œ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
+
+๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ์‹œ์Šคํ…œ์—์„œ ๋ณด์•ˆ๊ณผ ์ธ์ฆ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ๋„ ํฐ ๋…ธ๋ ฅ๊ณผ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๋งŽ์€ ๊ฒฝ์šฐ ์ž‘์„ฑ๋œ ์ „์ฒด ์ฝ”๋“œ์˜ 50% ์ด์ƒ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
+
+**FastAPI**๋Š” ๋ชจ๋“  ๋ณด์•ˆ ๋ช…์„ธ๋ฅผ ์ „๋ถ€ ๊ณต๋ถ€ํ•˜๊ณ  ๋ฐฐ์šธ ํ•„์š” ์—†์ด, ํ‘œ์ค€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ **๋ณด์•ˆ(Security)** ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+ํ•˜์ง€๋งŒ ๋จผ์ €, ๋ช‡ ๊ฐ€์ง€ ์ž‘์€ ๊ฐœ๋…์„ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
+
+## ๊ธ‰ํ•˜์‹ ๊ฐ€์š”? { #in-a-hurry }
+
+์ด ์šฉ์–ด๋“ค์— ๊ด€์‹ฌ์ด ์—†๊ณ  ์‚ฌ์šฉ์ž๋ช…๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ์‚ฌ์šฉํ•œ ๋ณด์•ˆ์„ *์ง€๊ธˆ ๋‹น์žฅ* ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค๋ฉด, ๋‹ค์Œ ์žฅ๋“ค๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”.
+
+## OAuth2 { #oauth2 }
+
+OAuth2๋Š” ์ธ์ฆ๊ณผ ์ธ๊ฐ€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•˜๋Š” ๋ช…์„ธ์ž…๋‹ˆ๋‹ค.
+
+์ƒ๋‹นํžˆ ๋ฐฉ๋Œ€ํ•œ ๋ช…์„ธ์ด๋ฉฐ ์—ฌ๋Ÿฌ ๋ณต์žกํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
+
+"์ œ3์ž"๋ฅผ ์‚ฌ์šฉํ•ด ์ธ์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
+
+๋ฐ”๋กœ `"Facebook, Google, X (Twitter), GitHub๋กœ ๋กœ๊ทธ์ธ"` ๊ฐ™์€ ์‹œ์Šคํ…œ๋“ค์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
+
+### OAuth 1 { #oauth-1 }
+
+OAuth 1๋„ ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋Š” OAuth2์™€ ๋งค์šฐ ๋‹ค๋ฅด๊ณ  ํ†ต์‹ ์„ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€ ์ง์ ‘ ๋ช…์„ธ์— ํฌํ•จํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋ณต์žกํ–ˆ์Šต๋‹ˆ๋‹ค.
+
+์š”์ฆ˜์—๋Š” ๊ทธ๋‹ค์ง€ ์ธ๊ธฐ ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
+
+OAuth2๋Š” ํ†ต์‹ ์„ ์–ด๋–ป๊ฒŒ ์•”ํ˜ธํ™”ํ• ์ง€๋Š” ๋ช…์„ธํ•˜์ง€ ์•Š๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด HTTPS๋กœ ์ œ๊ณต๋  ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.
+
+/// tip | ํŒ
+
+**๋ฐฐํฌ**์— ๋Œ€ํ•œ ์„น์…˜์—์„œ Traefik๊ณผ Let's Encrypt๋ฅผ ์‚ฌ์šฉํ•ด ๋ฌด๋ฃŒ๋กœ HTTPS๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+///
+
+## OpenID Connect { #openid-connect }
+
+OpenID Connect๋Š” **OAuth2**๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋˜ ๋‹ค๋ฅธ ๋ช…์„ธ์ž…๋‹ˆ๋‹ค.
+
+OAuth2์—์„œ ๋น„๊ต์  ๋ชจํ˜ธํ•œ ๋ถ€๋ถ„์„ ์ผ๋ถ€ ๊ตฌ์ฒดํ™”ํ•˜์—ฌ ์ƒํ˜ธ ์šด์šฉ์„ฑ์„ ๋†’์ด๋ ค๋Š” ํ™•์žฅ์ž…๋‹ˆ๋‹ค.
+
+์˜ˆ๋ฅผ ๋“ค์–ด, Google ๋กœ๊ทธ์ธ์€ OpenID Connect๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(๋‚ด๋ถ€์ ์œผ๋กœ๋Š” OAuth2๋ฅผ ์‚ฌ์šฉ).
+
+ํ•˜์ง€๋งŒ Facebook ๋กœ๊ทธ์ธ์€ OpenID Connect๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž์ฒด์ ์ธ ๋ณ€ํ˜•์˜ OAuth2๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
+
+### OpenID("OpenID Connect"๊ฐ€ ์•„๋‹˜) { #openid-not-openid-connect }
+
+"OpenID"๋ผ๋Š” ๋ช…์„ธ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” **OpenID Connect**์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ, OAuth2๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
+
+๋”ฐ๋ผ์„œ ์™„์ „ํžˆ ๋ณ„๋„์˜ ์ถ”๊ฐ€ ์‹œ์Šคํ…œ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
+
+์š”์ฆ˜์—๋Š” ๊ทธ๋‹ค์ง€ ์ธ๊ธฐ ์žˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
+
+## OpenAPI { #openapi }
+
+OpenAPI(์ด์ „์—๋Š” Swagger๋กœ ์•Œ๋ ค์ง)๋Š” API๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ๊ณต๊ฐœ ๋ช…์„ธ์ž…๋‹ˆ๋‹ค(ํ˜„์žฌ Linux Foundation์˜ ์ผ๋ถ€).
+
+**FastAPI**๋Š” **OpenAPI**๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
+
+์ด ๋•๋ถ„์— ์—ฌ๋Ÿฌ ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์ธํ„ฐํŽ˜์ด์Šค, ์ฝ”๋“œ ์ƒ์„ฑ ๋“ฑ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+OpenAPI์—๋Š” ์—ฌ๋Ÿฌ ๋ณด์•ˆ "scheme"์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
+
+์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฌํ•œ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ์„ ํฌํ•จํ•ด, ํ‘œ์ค€ ๊ธฐ๋ฐ˜ ๋„๊ตฌ๋“ค์„ ๋ชจ๋‘ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+
+OpenAPI๋Š” ๋‹ค์Œ ๋ณด์•ˆ scheme๋“ค์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค:
+
+* `apiKey`: ๋‹ค์Œ์—์„œ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์šฉ ํ‚ค:
+    * ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ
+    * ํ—ค๋”
+    * ์ฟ ํ‚ค
+* `http`: ํ‘œ์ค€ HTTP ์ธ์ฆ ์‹œ์Šคํ…œ, ์˜ˆ:
+    * `bearer`: `Authorization` ํ—ค๋”์— `Bearer ` + ํ† ํฐ ๊ฐ’์„ ๋„ฃ๋Š” ๋ฐฉ์‹. OAuth2์—์„œ ์œ ๋ž˜ํ–ˆ์Šต๋‹ˆ๋‹ค.
+    * HTTP Basic ์ธ์ฆ
+    * HTTP Digest ๋“ฑ
+* `oauth2`: ๋ณด์•ˆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“  OAuth2 ๋ฐฉ์‹(์ด๋ฅผ "flow"๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค).
+    * ์ด flow๋“ค ์ค‘ ์—ฌ๋Ÿฌ ๊ฐœ๋Š” OAuth 2.0 ์ธ์ฆ ์ œ๊ณต์ž(์˜ˆ: Google, Facebook, X (Twitter), GitHub ๋“ฑ)๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค:
+        * `implicit`
+        * `clientCredentials`
+        * `authorizationCode`
+    * ํ•˜์ง€๋งŒ ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์™„๋ฒฝํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ • "flow"๋„ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค:
+        * `password`: ๋‹ค์Œ ์žฅ๋“ค์—์„œ ์ด์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
+* `openIdConnect`: OAuth2 ์ธ์ฆ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ํƒ์ƒ‰(discover)ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
+    * ์ด ์ž๋™ ํƒ์ƒ‰์€ OpenID Connect ๋ช…์„ธ์—์„œ ์ •์˜๋ฉ๋‹ˆ๋‹ค.
+
+
+/// tip | ํŒ
+
+Google, Facebook, X (Twitter), GitHub ๋“ฑ ๋‹ค๋ฅธ ์ธ์ฆ/์ธ๊ฐ€ ์ œ๊ณต์ž๋ฅผ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋น„๊ต์  ์‰ฝ์Šต๋‹ˆ๋‹ค.
+
+๊ฐ€์žฅ ๋ณต์žกํ•œ ๋ฌธ์ œ๋Š” ๊ทธ๋Ÿฐ ์ธ์ฆ/์ธ๊ฐ€ ์ œ๊ณต์ž ์ž์ฒด๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, **FastAPI**๋Š” ์–ด๋ ค์šด ์ž‘์—…์„ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด ์ฃผ๋ฉด์„œ ์ด๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
+
+///
+
+## **FastAPI** ์œ ํ‹ธ๋ฆฌํ‹ฐ { #fastapi-utilities }
+
+FastAPI๋Š” `fastapi.security` ๋ชจ๋“ˆ์—์„œ ๊ฐ ๋ณด์•ˆ scheme์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
+
+๋‹ค์Œ ์žฅ๋“ค์—์„œ๋Š” **FastAPI**๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด API์— ๋ณด์•ˆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
+
+๋˜ํ•œ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ ์‹œ์Šคํ…œ์— ์–ด๋–ป๊ฒŒ ์ž๋™์œผ๋กœ ํ†ตํ•ฉ๋˜๋Š”์ง€๋„ ํ™•์ธํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.