Browse Source

๐ŸŒ Add Korean translation for `docs/ko/docs/advanced/custom-response.md` (#13265)

pull/13378/head
11kkw 2 months ago
committed by GitHub
parent
commit
030012bf4c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 313
      docs/ko/docs/advanced/custom-response.md

313
docs/ko/docs/advanced/custom-response.md

@ -0,0 +1,313 @@
# ์‚ฌ์šฉ์ž ์ •์˜ ์‘๋‹ต - HTML, Stream, ํŒŒ์ผ, ๊ธฐํƒ€
๊ธฐ๋ณธ์ ์œผ๋กœ, **FastAPI** ์‘๋‹ต์„ `JSONResponse`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ์žฌ์ •์˜ ํ•˜๋ ค๋ฉด [์‘๋‹ต์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๊ธฐ](response-directly.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ `Response`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ `Response` (๋˜๋Š” `JSONResponse`์™€ ๊ฐ™์€ ํ•˜์œ„ ํด๋ž˜์Šค)๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ๋ฐ์ดํ„ฐ๊ฐ€ ์ž๋™์œผ๋กœ ๋ณ€ํ™˜๋˜์ง€ ์•Š์œผ๋ฉฐ (์‹ฌ์ง€์–ด `response_model`์„ ์„ ์–ธํ–ˆ๋”๋ผ๋„), ๋ฌธ์„œํ™”๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒ์„ฑ๋œ OpenAPI์˜ ์ผ๋ถ€๋กœ HTTP ํ—ค๋” `Content-Type`์— ํŠน์ • "๋ฏธ๋””์–ด ํƒ€์ž…"์„ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ).
ํ•˜์ง€๋งŒ *๊ฒฝ๋กœ ์ž‘์—… ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” `Response`(์˜ˆ: ๋ชจ๋“  `Response` ํ•˜์œ„ ํด๋ž˜์Šค)๋ฅผ ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
*๊ฒฝ๋กœ ์ž‘์—… ํ•จ์ˆ˜*์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‚ด์šฉ์€ ํ•ด๋‹น `Response`์•ˆ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ ๊ทธ `Response`๊ฐ€ `JSONResponse`์™€ `UJSONResponse`์˜ ๊ฒฝ์šฐ ์ฒ˜๋Ÿผ JSON ๋ฏธ๋””์–ด ํƒ€์ž…(`application/json`)์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, *๊ฒฝ๋กœ ์ž‘์—… ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ ์„ ์–ธํ•œ Pydantic์˜ `response_model`์„ ์‚ฌ์šฉํ•ด ์ž๋™์œผ๋กœ ๋ณ€ํ™˜(๋ฐ ํ•„ํ„ฐ๋ง) ๋ฉ๋‹ˆ๋‹ค.
/// note | ์ฐธ๊ณ 
๋ฏธ๋””์–ด ํƒ€์ž…์ด ์—†๋Š” ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, FastAPI๋Š” ์‘๋‹ต์— ๋‚ด์šฉ์ด ์—†์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋ฏ€๋กœ ์ƒ์„ฑ๋œ OpenAPI ๋ฌธ์„œ์—์„œ ์‘๋‹ต ํ˜•์‹์„ ๋ฌธ์„œํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
///
## `ORJSONResponse` ์‚ฌ์šฉํ•˜๊ธฐ
์˜ˆ๋ฅผ ๋“ค์–ด, ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">orjson</a>์„ ์„ค์น˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์‘๋‹ต์„ `ORJSONResponse`๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” `Response` ํด๋ž˜์Šค(ํ•˜์œ„ ํด๋ž˜์Šค)๋ฅผ ์ž„ํฌํŠธํ•œ ํ›„, **๊ฒฝ๋กœ ์ž‘์—… ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์—์„œ ์„ ์–ธํ•˜์„ธ์š”.
๋Œ€๊ทœ๋ชจ ์‘๋‹ต์˜ ๊ฒฝ์šฐ, ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค `Response`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋น ๋ฆ…๋‹ˆ๋‹ค.
์ด์œ ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ, FastAPI๊ฐ€ ๋‚ด๋ถ€์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์„ ๊ฒ€์‚ฌํ•˜๊ณ  JSON์œผ๋กœ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ์—์„œ ์„ค๋ช…๋œ [JSON ํ˜ธํ™˜ ๊ฐ€๋Šฅ ์ธ์ฝ”๋”](../tutorial/encoder.md){.internal-link target=_blank}๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ๊ณผ ๊ฐ™์€ **์ž„์˜์˜ ๊ฐ์ฒด**๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‚ด์šฉ์ด **JSON์œผ๋กœ ์ง๋ ฌํ™” ๊ฐ€๋Šฅ**ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ๋‚ด์šฉ์„ ์‘๋‹ต ํด๋ž˜์Šค์— ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, FastAPI๊ฐ€ ๋ฐ˜ํ™˜ ๋‚ด์šฉ์„ `jsonable_encoder`๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•œ ๋’ค ์‘๋‹ต ํด๋ž˜์Šค์— ์ „๋‹ฌํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *}
/// info | ์ •๋ณด
`response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์‘๋‹ต์˜ "๋ฏธ๋””์–ด ํƒ€์ž…"์„ ์ •์˜ํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ, HTTP ํ—ค๋” `Content-Type`์€ `application/json`์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ด๋Š” OpenAPI์— ๊ทธ๋Œ€๋กœ ๋ฌธ์„œํ™”๋ฉ๋‹ˆ๋‹ค.
///
/// tip | ํŒ
`ORJSONResponse`๋Š” FastAPI์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  Starlette์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
///
## HTML ์‘๋‹ต
**FastAPI**์—์„œ HTML ์‘๋‹ต์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด `HTMLResponse`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
* `HTMLResponse`๋ฅผ ์ž„ํฌํŠธ ํ•ฉ๋‹ˆ๋‹ค.
* *๊ฒฝ๋กœ ์ž‘์—… ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ*์˜ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ `HTMLResponse`๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *}
/// info | ์ •๋ณด
`response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์‘๋‹ต์˜ "๋ฏธ๋””์–ด ํƒ€์ž…"์„ ์ •์˜ํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ, HTTP ํ—ค๋” `Content-Type`์€ `text/html`๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ด๋Š” OpenAPI์— ๊ทธ๋Œ€๋กœ ๋ฌธ์„œํ™” ๋ฉ๋‹ˆ๋‹ค.
///
### `Response` ๋ฐ˜ํ™˜ํ•˜๊ธฐ
[์‘๋‹ต์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๊ธฐ](response-directly.md){.internal-link target=_blank}์—์„œ ๋ณธ ๊ฒƒ ์ฒ˜๋Ÿผ, *๊ฒฝ๋กœ ์ž‘์—…*์—์„œ ์‘๋‹ต์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์žฌ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์œ„์˜ ์˜ˆ์ œ์™€ ๋™์ผํ•˜๊ฒŒ `HTMLResponse`๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
/// warning | ๊ฒฝ๊ณ 
*๊ฒฝ๋กœ ์ž‘์—… ํ•จ์ˆ˜*์—์„œ ์ง์ ‘ ๋ฐ˜ํ™˜๋œ `Response`๋Š” OpenAPI์— ๋ฌธ์„œํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ๋ฅผ๋“ค์–ด, `Content-Type`์ด ๋ฌธ์„œํ™”๋˜์ง€ ์•Š์Œ) ์ž๋™ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์—์„œ๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
///
/// info | ์ •๋ณด
๋ฌผ๋ก  ์‹ค์ œ `Content-Type` ํ—ค๋”, ์ƒํƒœ ์ฝ”๋“œ ๋“ฑ์€ ๋ฐ˜ํ™˜๋œ `Response` ๊ฐ์ฒด์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
///
### OpenAPI์— ๋ฌธ์„œํ™”ํ•˜๊ณ  `Response` ์žฌ์ •์˜ ํ•˜๊ธฐ
ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‘๋‹ต์„ ์žฌ์ •์˜ํ•˜๋ฉด์„œ ๋™์‹œ์— OpenAPI์—์„œ "๋ฏธ๋””์–ด ํƒ€์ž…"์„ ๋ฌธ์„œํ™”ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, `response_class` ๋งค๊ฒŒ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ `Response` ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ `response_class`๋Š” OpenAPI *๊ฒฝ๋กœ ์ž‘์—…*์„ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋ฐ๋งŒ ์‚ฌ์šฉ๋˜๊ณ , ์‹ค์ œ๋กœ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ๋ฐ˜ํ™˜ํ•œ `Response`๊ฐ€ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
### `HTMLResponse`์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๊ธฐ
์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *}
์ด ์˜ˆ์ œ์—์„œ, `generate_html_response()` ํ•จ์ˆ˜๋Š” HTML์„ `str`๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ์ด๋ฏธ `Response`๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
`generate_html_response()`๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•จ์œผ๋กœ์จ, ๊ธฐ๋ณธ์ ์ธ **FastAPI** ๊ธฐ๋ณธ ๋™์ž‘์„ ์žฌ์ •์˜ ํ•˜๋Š” `Response`๋ฅผ ์ด๋ฏธ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ `response_class`์— `HTMLResponse`๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, FastAPI๋Š” ์ด๋ฅผ OpenAPI ๋ฐ ๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์—์„œ `text/html`๋กœ HTML์„ ๋ฌธ์„œํ™” ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<img src="/img/tutorial/custom-response/image01.png">
## ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‘๋‹ต๋“ค
๋‹ค์Œ์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡๊ฐ€์ง€ ์‘๋‹ต๋“ค ์ž…๋‹ˆ๋‹ค.
`Response`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ์–ด๋–ค ๊ฒƒ๋„ ๋ฐ˜ํ™˜ ํ• ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ง์ ‘ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
/// note | ๊ธฐ์ˆ  ์„ธ๋ถ€์‚ฌํ•ญ
`from starlette.responses import HTMLResponse`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
**FastAPI**๋Š” ๊ฐœ๋ฐœ์ž์ธ ์—ฌ๋Ÿฌ๋ถ„์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด `starlette.responses`๋ฅผ `fastapi.responses`๋กœ ์ œ๊ณต ํ•˜์ง€๋งŒ, ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์‘๋‹ต์€ Starlette์—์„œ ์ง์ ‘ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
///
### `Response`
๊ธฐ๋ณธ `Response` ํด๋ž˜์Šค๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ์‘๋‹ต ํด๋ž˜์Šค์˜ ๋ถ€๋ชจ ํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.
์ด ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
* `content` - `str` ๋˜๋Š” `bytes`.
* `status_code` - HTTP ์ƒํƒœ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” `int`.
* `headers` - ๋ฌธ์ž์—ด๋กœ ์ด๋ฃจ์–ด์ง„ `dict`.
* `media_type` - ๋ฏธ๋””์–ด ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” `str` ์˜ˆ: `"text/html"`.
FastAPI (์‹ค์ œ๋กœ๋Š” Starlette)๊ฐ€ ์ž๋™์œผ๋กœ `Content-Length` ํ—ค๋”๋ฅผ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค. ๋˜ํ•œ `media_type`์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ `Content-Type` ํ—ค๋”๋ฅผ ํฌํ•จํ•˜๋ฉฐ, ํ…์ŠคํŠธ ํƒ€์ž…์˜ ๊ฒฝ์šฐ ๋ฌธ์ž ์ง‘ํ•ฉ์„ ์ถ”๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
### `HTMLResponse`
ํ…์ŠคํŠธ ๋˜๋Š” ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•„ HTML ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
### `PlainTextResponse`
ํ…์ŠคํŠธ ๋˜๋Š” ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•„ ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
### `JSONResponse`
๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ `application/json`์œผ๋กœ ์ธ์ฝ”๋”ฉ๋œ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
์ด๋Š” ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด **FastAPI**์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์‘๋‹ต ํ˜•์‹์ž…๋‹ˆ๋‹ค.
### `ORJSONResponse`
<a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น ๋ฅธ JSON ์‘๋‹ต์„ ์ œ๊ณตํ•˜๋Š” ๋Œ€์•ˆ์ž…๋‹ˆ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
/// info | ์ •๋ณด
์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด `orjson`์„ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: `pip install orjson`.
///
### `UJSONResponse`
<a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>์„ ์‚ฌ์šฉํ•œ ๋˜ ๋‹ค๋ฅธ JSON ์‘๋‹ต ํ˜•์‹์ž…๋‹ˆ๋‹ค.
/// info | ์ •๋ณด
์ด ์‘๋‹ต์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด `ujson`์„ ์„ค์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: 'pip install ujson`.
///
/// warning | ๊ฒฝ๊ณ 
`ujson` ์€ ์ผ๋ถ€ ์˜ˆ์™ธ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์žˆ์–ด Python ๋‚ด์žฅ ๊ตฌํ˜„๋ณด๋‹ค ๋œ ์—„๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
///
{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
/// tip | ํŒ
`ORJSONResponse`๊ฐ€ ๋” ๋น ๋ฅธ ๋Œ€์•ˆ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
///
### `RedirectResponse`
HTTP ๋ฆฌ๋””๋ ‰์…˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ ์ฝ”๋“œ๋Š” 307(์ž„์‹œ ๋ฆฌ๋””๋ ‰์…˜)์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
`RedirectResponse`๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
---
๋˜๋Š” `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *}
์ด ๊ฒฝ์šฐ, *๊ฒฝ๋กœ ์ž‘์—…* ํ•จ์ˆ˜์—์„œ URL์„ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ, ์‚ฌ์šฉ๋˜๋Š” `status_code`๋Š” `RedirectResponse`์˜ ๊ธฐ๋ณธ๊ฐ’์ธ `307` ์ž…๋‹ˆ๋‹ค.
---
`status_code` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
### `StreamingResponse`
๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ๋˜๋Š” ์ผ๋ฐ˜ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ/์ดํ„ฐ๋ ˆ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์‘๋‹ต ๋ณธ๋ฌธ์„ ์ŠคํŠธ๋ฆฌ๋ฐ ํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
#### ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ `StreamingResponse`
ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด(์˜ˆ: `open()`์œผ๋กœ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด)๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜๋ณต(iterate)ํ•˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋ฐฉ์‹์œผ๋กœ, ํŒŒ์ผ ์ „์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋จผ์ € ์ฝ์–ด๋“ค์ผ ํ•„์š” ์—†์ด, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ `StreamingResponse`์— ์ „๋‹ฌํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋ฐฉ์‹์€ ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€, ๋น„๋””์˜ค ์ฒ˜๋ฆฌ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
1. ์ด๊ฒƒ์ด ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. `yield` ๋ฌธ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ "์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜"์ž…๋‹ˆ๋‹ค.
2. `with` ๋ธ”๋ก์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ๋‹ซํžˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์‘๋‹ต ์ „์†ก์ด ๋๋‚œ ํ›„ ๋‹ซํž™๋‹ˆ๋‹ค.
3. ์ด `yield from`์€ ํ•จ์ˆ˜๊ฐ€ `file_like`๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜๋ณต(iterate)ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ณต๋œ ๊ฐ ๋ถ€๋ถ„์€ ์ด ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜(`iterfile`)์—์„œ ์ƒ์„ฑ๋œ ๊ฒƒ์ฒ˜๋Ÿผ `yield` ๋ฉ๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด "์ƒ์„ฑ(generating)" ์ž‘์—…์„ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€์— ์œ„์ž„ํ•˜๋Š” ์ œ๋„ˆ๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด `with` ๋ธ”๋ก ์•ˆ์—์„œ ํŒŒ์ผ์„ ์—ด ์ˆ˜ ์žˆ์–ด, ์ž‘์—…์ด ์™„๋ฃŒ๋œ ํ›„ ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ๋‹ซํžˆ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
/// tip | ํŒ
์—ฌ๊ธฐ์„œ ํ‘œ์ค€ `open()`์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— `async`์™€ `await`๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฒฝ๋กœ ์ž‘์—…์€ ์ผ๋ฐ˜ `def`๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
///
### `FileResponse`
ํŒŒ์ผ์„ ๋น„๋™๊ธฐ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜์—ฌ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
๋‹ค๋ฅธ ์‘๋‹ต ์œ ํ˜•๊ณผ๋Š” ๋‹ค๋ฅธ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
* `path` - ์ŠคํŠธ๋ฆฌ๋ฐํ•  ํŒŒ์ผ์˜ ๊ฒฝ๋กœ.
* `headers` - ๋”•์…”๋„ˆ๋ฆฌ ํ˜•์‹์˜ ์‚ฌ์šฉ์ž ์ •์˜ ํ—ค๋”.
* `media_type` - ๋ฏธ๋””์–ด ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด. ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํŒŒ์ผ ์ด๋ฆ„์ด๋‚˜ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.
* `filename` - ์„ค์ •๋œ ๊ฒฝ์šฐ ์‘๋‹ต์˜ `Content-Disposition`์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
ํŒŒ์ผ ์‘๋‹ต์—๋Š” ์ ์ ˆํ•œ `Content-Length`, `Last-Modified`, ๋ฐ `ETag` ํ—ค๋”๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
๋˜ํ•œ `response_class` ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *}
์ด ๊ฒฝ์šฐ, ๊ฒฝ๋กœ ์ž‘์—… ํ•จ์ˆ˜์—์„œ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
## ์‚ฌ์šฉ์ž ์ •์˜ ์‘๋‹ต ํด๋ž˜์Šค
`Response`๋ฅผ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉ์ž ์ •์˜ ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ํฌํ•จ๋œ `ORJSONResponse` ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์„ค์ •์œผ๋กœ <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">orjson</a>์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.
๋งŒ์•ฝ ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฐ ํฌ๋งท๋œ JSON์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, `orjson.OPT_INDENT_2` ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
`CustomORJSONResponse`๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ `Response.render(content)` ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋‚ด์šฉ์„ `bytes`๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:
{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
์ด์ œ ๋‹ค์Œ ๋Œ€์‹ :
```json
{"message": "Hello World"}
```
์ด ์‘๋‹ต์€ ์ด๋ ‡๊ฒŒ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค:
```json
{
"message": "Hello World"
}
```
๋ฌผ๋ก  JSON ํฌ๋งทํŒ…๋ณด๋‹ค ๋” ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜‰
## ๊ธฐ๋ณธ ์‘๋‹ต ํด๋ž˜์Šค
**FastAPI** ํด๋ž˜์Šค ๊ฐ์ฒด ๋˜๋Š” `APIRouter`๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ์ •์˜ํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” `default_response_class`์ž…๋‹ˆ๋‹ค.
์•„๋ž˜ ์˜ˆ์ œ์—์„œ **FastAPI**๋Š” ๋ชจ๋“  ๊ฒฝ๋กœ ์ž‘์—…์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ `JSONResponse` ๋Œ€์‹  `ORJSONResponse`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *}
/// tip | ํŒ
์—ฌ์ „ํžˆ ์ด์ „์ฒ˜๋Ÿผ *๊ฒฝ๋กœ ์ž‘์—…*์—์„œ `response_class`๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
///
## ์ถ”๊ฐ€ ๋ฌธ์„œํ™”
OpenAPI์—์„œ `responses`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฏธ๋””์–ด ํƒ€์ž… ๋ฐ ๊ธฐํƒ€ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์„ ์–ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค: [OpenAPI์—์„œ ์ถ”๊ฐ€ ์‘๋‹ต](additional-responses.md){.internal-link target=_blank}.
Loadingโ€ฆ
Cancel
Save