Browse Source

๐ŸŒ Add Korean translation for `docs/ko/docs/advanced/async-test.md` (#12918)

pull/13055/head
viva-douner 4 months ago
committed by GitHub
parent
commit
f7ba75e3f7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 108
      docs/ko/docs/advanced/async-tests.md

108
docs/ko/docs/advanced/async-tests.md

@ -0,0 +1,108 @@
# ๋น„๋™๊ธฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ
์ด์ „ ์žฅ์—์„œ `TestClient` ๋ฅผ ์ด์šฉํ•ด **FastAPI** ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์šฐ์…จ์„ํ…๋ฐ์š”.
์ง€๊ธˆ๊นŒ์ง€๋Š” `async` ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ์—†์ด ๋™๊ธฐ ํ•จ์ˆ˜์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฒ•๋งŒ ์ตํ˜”์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋น„๋™๊ธฐ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.
FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฑ์—”๋“œ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋กํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋น„๋™๊ธฐ๋กœ ์ž‘์„ฑํ•˜๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.
## pytest.mark.anyio
์•ž์—์„œ ์ž‘์„ฑํ•œ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜์—์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.
AnyIO๋Š” ํŠน์ • ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๋ฅผ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ ํ•  ์ˆ˜ ์žˆ๋Š” ๊น”๋”ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
## HTTPX
**FastAPI** ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด `async def` ๋Œ€์‹  `def` ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์—ฌ์ „ํžˆ `๋น„๋™๊ธฐ` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค.
`TestClient`๋Š” pytest ํ‘œ์ค€์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ผ๋ฐ˜์ ์ธ `def` ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚ด๋ถ€์—์„œ ๋งˆ์ˆ ์„ ๋ถ€๋ฆฝ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋งˆ์ˆ ์€ ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋” ์ด์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๋ฉด, ๋” ์ด์ƒ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ `TestClient`๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
`TestClient`๋Š” <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋‹คํ–‰ํžˆ ์ด๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ API๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
## ์˜ˆ์‹œ
๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด [๋” ํฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค๊ธฐ](../ko/tutorial/bigger-applications.md){.internal-link target=_blank} ์™€ [ํ…Œ์ŠคํŠธ](../ko/tutorial/testing.md){.internal-link target=_blank}:์—์„œ ๋‹ค๋ฃฌ ํŒŒ์ผ ๊ตฌ์กฐ์™€ ๋น„์Šทํ•œ ํ˜•ํƒœ๋ฅผ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค:
```
.
โ”œโ”€โ”€ app
โ”‚ย ย  โ”œโ”€โ”€ __init__.py
โ”‚ย ย  โ”œโ”€โ”€ main.py
โ”‚ย ย  โ””โ”€โ”€ test_main.py
```
`main.py`๋Š” ์•„๋ž˜์™€ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค:
{* ../../docs_src/async_tests/main.py *}
`test_main.py` ํŒŒ์ผ์€ `main.py`์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ์„ ํ…๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/async_tests/test_main.py *}
## ์‹คํ–‰ํ•˜๊ธฐ
์•„๋ž˜์˜ ๋ช…๋ น์–ด๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:
<div class="termy">
```console
$ pytest
---> 100%
```
</div>
## ์ž์„ธํžˆ ๋ณด๊ธฐ
`@pytest.mark.anyio` ๋งˆ์ปค๋Š” pytest์—๊ฒŒ ์ด ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•จ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค:
{* ../../docs_src/async_tests/test_main.py hl[7] *}
/// tip | ํŒ
ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ์ด์ œ `TestClient`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์ฒ˜๋Ÿผ ๋‹จ์ˆœํžˆ `def`๊ฐ€ ์•„๋‹ˆ๋ผ `async def`๋กœ ์ž‘์„ฑ๋œ ์ ์— ์ฃผ๋ชฉํ•ด์ฃผ์„ธ์š”.
///
๊ทธ ๋‹ค์Œ์— `AsyncClient` ๋กœ ์•ฑ์„ ๋งŒ๋“ค๊ณ  ๋น„๋™๊ธฐ ์š”์ฒญ์„ `await` ํ‚ค์›Œ๋“œ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
์œ„์˜ ์ฝ”๋“œ๋Š”:
```Python
response = client.get('/')
```
`TestClient` ์— ์š”์ฒญ์„ ๋ณด๋‚ด๋˜ ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
/// tip | ํŒ
์ƒˆ๋กœ์šด `AsyncClient`๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ async/await๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. ์ด ์š”์ฒญ์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
///
/// warning | ๊ฒฝ๊ณ 
๋งŒ์•ฝ์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด Lifespan ์ด๋ฒคํŠธ์— ์˜์กด์„ฑ์„ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด `AsyncClient` ๊ฐ€ ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
`AsyncClient` ๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰์‹œ์ผฐ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด
`LifespanManager` from <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.ํ™•์ธํ•ด์ฃผ์„ธ์š”.
///
## ๊ทธ ์™ธ์˜ ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ
ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ์ด์ œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์ด๋ฏ€๋กœ, FastAPI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ ์™ธ์—๋„ ๋‹ค๋ฅธ `async` ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  `await` ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
/// tip | ํŒ
ํ…Œ์ŠคํŠธ์— ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ํ†ตํ•ฉํ•  ๋•Œ (์˜ˆ: <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB์˜ MotorClient</a>๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ) `RuntimeError: Task attached to a different loop` ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ํ•„์š”ํ•œ ๊ฐ์ฒด๋Š” ๋ฐ˜๋“œ์‹œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ๋‚ด์—์„œ๋งŒ ์ธ์Šคํ„ด์Šคํ™”ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•˜์„ธ์š”!
์˜ˆ๋ฅผ ๋“ค์–ด `@app.on_event("startup")` ์ฝœ๋ฐฑ ๋‚ด์—์„œ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
///
Loadingโ€ฆ
Cancel
Save