Browse Source

๐ŸŒ Add Korean translation for `docs/ko/docs/deployment/docker.md` (#5657)

pull/11011/head
HyeonJeong Yeo 1 year ago
committed by GitHub
parent
commit
6c3d8eb2d9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 698
      docs/ko/docs/deployment/docker.md

698
docs/ko/docs/deployment/docker.md

@ -0,0 +1,698 @@
# ์ปจํ…Œ์ด๋„ˆ์˜ FastAPI - ๋„์ปค
FastAPI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์€ **๋ฆฌ๋ˆ…์Šค ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์ฃผ๋กœ <a href="https://www.docker.com/" class="external-link" target="_blank">**๋„์ปค**</a>๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ•ด๋‹น ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋ช‡๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ฆฌ๋ˆ…์Šค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์—๋Š” **๋ณด์•ˆ**, **๋ฐ˜๋ณต ๊ฐ€๋Šฅ์„ฑ**, **๋‹จ์ˆœํ•จ** ๋“ฑ์˜ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
!!! ํŒ
์‹œ๊ฐ„์— ์ซ“๊ธฐ๊ณ  ์žˆ๊ณ  ์ด๋ฏธ ์ด๋Ÿฐ๊ฒƒ๋“ค์„ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด [`Dockerfile`๐Ÿ‘‡](#build-a-docker-image-for-fastapi)๋กœ ์ ํ”„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<details>
<summary>๋„์ปคํŒŒ์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๐Ÿ‘€</summary>
```Dockerfile
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
# If running behind a proxy like Nginx or Traefik add --proxy-headers
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]
```
</details>
## ์ปจํ…Œ์ด๋„ˆ๋ž€
์ปจํ…Œ์ด๋„ˆ(์ฃผ๋กœ ๋ฆฌ๋ˆ…์Šค ์ปจํ…Œ์ด๋„ˆ)๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์˜์กด์„ฑ๊ณผ ํ•„์š”ํ•œ ํŒŒ์ผ๋“ค์„ ๋ชจ๋‘ ํŒจํ‚ค์ง•ํ•˜๋Š” ๋งค์šฐ **๊ฐ€๋ฒผ์šด** ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ๋Š” ๊ฐ™์€ ์‹œ์Šคํ…œ์— ์žˆ๋Š” ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ(๋‹ค๋ฅธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ์š”์†Œ๋“ค)์™€ ๋…๋ฆฝ์ ์œผ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
๋ฆฌ๋ˆ…์Šค ์ปจํ…Œ์ด๋„ˆ๋Š” ํ˜ธ์ŠคํŠธ(๋จธ์‹ , ๊ฐ€์ƒ ๋จธ์‹ , ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„ ๋“ฑ)์™€ ๊ฐ™์€ ๋ฆฌ๋ˆ…์Šค ์ปค๋„์„ ์‚ฌ์šฉํ•ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ง์€ ๋ฆฌ๋ˆ…์Šค ์ปจํ…Œ์ด๋„ˆ๊ฐ€ (์ „์ฒด ์šด์˜์ฒด์ œ๋ฅผ ๋ชจ๋ฐฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐ€์ƒ ๋จธ์‹ ๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ) ๋งค์šฐ ๊ฐ€๋ณ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด, ์ปจํ…Œ์ด๋„ˆ๋Š” ์ง์ ‘ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ •๋„์˜ **์ ์€ ์ž์›**์„ ์†Œ๋น„ํ•ฉ๋‹ˆ๋‹ค (๊ฐ€์ƒ ๋จธ์‹ ์€ ํ›จ์”ฌ ๋งŽ์€ ์ž์›์„ ์†Œ๋น„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค).
์ปจํ…Œ์ด๋„ˆ๋Š” ๋˜ํ•œ ๊ทธ๋“ค๋งŒ์˜ **๋…๋ฆฝ๋œ** ์‹คํ–‰ ํ”„๋กœ์„ธ์Šค (์ผ๋ฐ˜์ ์œผ๋กœ ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค), ํŒŒ์ผ ์‹œ์Šคํ…œ, ๊ทธ๋ฆฌ๊ณ  ๋„คํŠธ์›Œํฌ๋ฅผ ๊ฐ€์ง€๋ฏ€๋กœ ๋ฐฐํฌ, ๋ณด์•ˆ, ๊ฐœ๋ฐœ ๋ฐ ๊ธฐํƒ€ ๊ณผ์ •์„ ๋‹จ์ˆœํ™” ํ•ฉ๋‹ˆ๋‹ค.
## ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ž€
**์ปจํ…Œ์ด๋„ˆ**๋Š” **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋ฅผ ์‹คํ–‰ํ•œ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ž€ ์ปจํ…Œ์ด๋„ˆ์— ํ•„์š”ํ•œ ๋ชจ๋“  ํŒŒ์ผ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ทธ๋ฆฌ๊ณ  ๋””ํดํŠธ ๋ช…๋ น/ํ”„๋กœ๊ทธ๋žจ์˜ **์ •์ ** ๋ฒ„์ „์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ **์ •์ **์ด๋ž€ ๋ง์€ ์ปจํ…Œ์ด๋„ˆ **์ด๋ฏธ์ง€**๊ฐ€ ์ž‘๋™๋˜๊ฑฐ๋‚˜ ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹จ์ง€ ํŒจํ‚ค์ง€ ํŒŒ์ผ๊ณผ ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ๋ผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
์ €์žฅ๋œ ์ •์  ์ปจํ…์ธ ์ธ **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**์™€ ๋Œ€์กฐ๋˜๊ฒŒ, **์ปจํ…Œ์ด๋„ˆ**๋ž€ ๋ณดํ†ต ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ž‘๋™ ์ธ์Šคํ„ด์Šค๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
**์ปจํ…Œ์ด๋„ˆ**๊ฐ€ (**์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋กœ ๋ถ€ํ„ฐ) ์‹œ์ž‘๋˜๊ณ  ์‹คํ–‰๋˜๋ฉด, ์ปจํ…Œ์ด๋„ˆ๋Š” ํŒŒ์ผ์ด๋‚˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณ€ํ™”๋Š” ์˜ค์ง ์ปจํ…Œ์ด๋„ˆ์—์„œ๋งŒ ์กด์žฌํ•˜๋ฉฐ, ๊ทธ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์—๋Š” ์ง€์†๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (์ฆ‰ ๋””์Šคํฌ์—๋Š” ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋Š” **ํ”„๋กœ๊ทธ๋žจ** ํŒŒ์ผ๊ณผ ์ปจํ…์ธ , ์ฆ‰ `python`๊ณผ ์–ด๋–ค ํŒŒ์ผ `main.py`์— ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  (**์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**์™€ ๋Œ€๋น„ํ•ด์„œ) **์ปจํ…Œ์ด๋„ˆ**๋Š” ์ด๋ฏธ์ง€์˜ ์‹ค์ œ ์‹คํ–‰ ์ธ์Šคํ„ด์Šค๋กœ **ํ”„๋กœ์„ธ์Šค**์— ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ์ปจํ…Œ์ด๋„ˆ๋Š” **ํ”„๋กœ์„ธ์Šค ๋Ÿฌ๋‹**์ด ์žˆ์„ ๋•Œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค (๊ทธ๋ฆฌ๊ณ  ๋ณดํ†ต ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค ์ž…๋‹ˆ๋‹ค). ์ปจํ…Œ์ด๋„ˆ๋Š” ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์œผ๋ฉด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
## ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€
๋„์ปค๋Š” **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**์™€ **์ปจํ…Œ์ด๋„ˆ**๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ์ฃผ์š” ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋˜์–ด์™”์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  <a href="https://hub.docker.com/" class="external-link" target="_blank">๋„์ปค ํ—ˆ๋ธŒ</a>์— ๋‹ค์–‘ํ•œ ๋„๊ตฌ, ํ™˜๊ฒฝ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๊ทธ๋ฆฌ๊ณ  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ **๊ณต์‹ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๊ฐ€ ๊ณต๊ฐœ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณต์‹ <a href="https://hub.docker.com/_/python" class="external-link" target="_blank">ํŒŒ์ด์ฌ ์ด๋ฏธ์ง€</a>๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ๋‹ค๋ฅธ ๋Œ€์ƒ, ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์œ„ํ•œ ์ด๋ฏธ์ง€๋“ค๋„ ์žˆ์Šต๋‹ˆ๋‹ค:
* <a href="https://hub.docker.com/_/postgres" class="external-link" target="_blank">PostgreSQL</a>
* <a href="https://hub.docker.com/_/mysql" class="external-link" target="_blank">MySQL</a>
* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a> ๋“ฑ
๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค์„ **๊ฒฐํ•ฉ**ํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—, **๊ณต์‹ ์ด๋ฏธ์ง€๋“ค**์„ ์‚ฌ์šฉํ•˜๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ์ปจํ…Œ์ด๋„ˆ์™€ ๋„์ปค์— ๋Œ€ํ•ด ๋ฐฐ์šธ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค์–‘ํ•œ ๋„๊ตฌ์™€ ์š”์†Œ๋“ค์— ๋Œ€ํ•œ ์ง€์‹์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์„œ๋กœ ๋‹ค๋ฅธ **๋‹ค์ค‘ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ ์ด๋“ค์„ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ํŒŒ์ด์ฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜, ๋ฆฌ์•กํŠธ ํ”„๋ก ํŠธ์—”๋“œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ์›น ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค์–ด ์ด๋“ค์˜ ๋‚ด๋ถ€ ๋„คํŠธ์›Œํฌ๋กœ ๊ฐ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋“  ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ(๋„์ปค๋‚˜ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค)์€ ์ด๋Ÿฌํ•œ ๋„คํŠธ์›Œํ‚น ํŠน์„ฑ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
## ์ปจํ…Œ์ด๋„ˆ์™€ ํ”„๋กœ์„ธ์Šค
**์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋Š” ๋ณดํ†ต **์ปจํ…Œ์ด๋„ˆ**๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋””ํดํŠธ ์ปค๋งจ๋“œ/ํ”„๋กœ๊ทธ๋žจ๊ณผ ๊ทธ ํ”„๋กœ๊ทธ๋žจ์— ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ปค๋งจ๋“œ ๋ผ์ธ์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•  ๋•Œ ํ•„์š”ํ•œ ๊ฐ’๋“ค๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.
**์ปจํ…Œ์ด๋„ˆ**๊ฐ€ ์‹œ์ž‘๋˜๋ฉด, ํ•ด๋‹น ์ปค๋งจ๋“œ/ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค (๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์ปค๋งจ๋“œ/ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋„๋ก ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
์ปจํ…Œ์ด๋„ˆ๋Š” **๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค**(์ปค๋งจ๋“œ ๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ)์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
์ปจํ…Œ์ด๋„ˆ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ, ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค์˜ ์„œ๋ธŒ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ์— **๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ **์ตœ์†Œํ•œ ํ•˜๋‚˜์˜ ์‹คํ–‰์ค‘์ธ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๊ณ ์„œ๋Š” ์‹คํ–‰์ค‘์ธ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ค‘๋‹จ๋˜๋ฉด, ์ปจํ…Œ์ด๋„ˆ๋„ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.
## FastAPI๋ฅผ ์œ„ํ•œ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œํ•˜๊ธฐ
์ด์ œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค! ๐Ÿš€
**๊ณต์‹ ํŒŒ์ด์ฌ** ์ด๋ฏธ์ง€์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ, FastAPI๋ฅผ ์œ„ํ•œ **๋„์ปค ์ด๋ฏธ์ง€**๋ฅผ **๋งจ ์ฒ˜์Œ๋ถ€ํ„ฐ** ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์ด๊ฒ ์Šต๋‹ˆ๋‹ค.
**๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ**์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด:
* **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค** ๋˜๋Š” ์œ ์‚ฌํ•œ ๋„๊ตฌ ์‚ฌ์šฉํ•˜๊ธฐ
* **๋ผ์ฆˆ๋ฒ ๋ฆฌ ํŒŒ์ด**๋กœ ์‹คํ–‰ํ•˜๊ธฐ
* ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ์‹คํ–‰ํ•  ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค ์‚ฌ์šฉํ•˜๊ธฐ ๋“ฑ
### ์š”๊ตฌ ํŒจํ‚ค์ง€
์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํŠน์ • ํŒŒ์ผ์„ ์œ„ํ•œ **ํŒจํ‚ค์ง€ ์š”๊ตฌ ์กฐ๊ฑด**์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ ์š”๊ตฌ ์กฐ๊ฑด์„ **์„ค์น˜**ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๋ถ„์ด ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ ํŒจํ‚ค์ง€ ์ด๋ฆ„๊ณผ ๋ฒ„์ „์ด ์ค„ ๋ณ„๋กœ ๊ธฐ๋ก๋œ `requirements.txt` ํŒŒ์ผ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋ฒ„์ „์˜ ๋ฒ”์œ„๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” [FastAPI ๋ฒ„์ „๋“ค์— ๋Œ€ํ•˜์—ฌ](./versions.md){.internal-link target=_blank}์— ์“ฐ์—ฌ์ง„ ๊ฒƒ๊ณผ ๊ฐ™์€ ์•„์ด๋””์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, `requirements.txt` ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
```
fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
```
๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ํŒจํ‚ค์ง€ ์ข…์†์„ฑ์€ `pip`๋กœ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:
<div class="termy">
```console
$ pip install -r requirements.txt
---> 100%
Successfully installed fastapi pydantic uvicorn
```
</div>
!!! ์ •๋ณด
ํŒจํ‚ค์ง€ ์ข…์†์„ฑ์„ ์ •์˜ํ•˜๊ณ  ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๊ณผ ๋„๊ตฌ๋Š” ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค.
๋‚˜์ค‘์— ์•„๋ž˜ ์„ธ์…˜์—์„œ Poetry๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ๋ฅผ ๋ณด์ด๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ‘‡
### **FastAPI** ์ฝ”๋“œ ์ƒ์„ฑํ•˜๊ธฐ
* `app` ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
* ๋นˆ ํŒŒ์ผ `__init__.py`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
* ๋‹ค์Œ๊ณผ ๊ฐ™์€ `main.py`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
### ๋„์ปคํŒŒ์ผ
์ด์ œ ๊ฐ™์€ ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ `Dockerfile`์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:
```{ .dockerfile .annotate }
# (1)
FROM python:3.9
# (2)
WORKDIR /code
# (3)
COPY ./requirements.txt /code/requirements.txt
# (4)
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (5)
COPY ./app /code/app
# (6)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
```
1. ๊ณต์‹ ํŒŒ์ด์ฌ ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€์—์„œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
2. ํ˜„์žฌ ์›Œํ‚น ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ `/code`๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์— `requirements.txt` ํŒŒ์ผ๊ณผ `app` ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์œ„์น˜์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
3. ์š”๊ตฌ ์กฐ๊ฑด๊ณผ ํŒŒ์ผ์„ `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
์ฒ˜์Œ์—๋Š” **์˜ค์ง** ์š”๊ตฌ ์กฐ๊ฑด์ด ํ•„์š”ํ•œ ํŒŒ์ผ๋งŒ ๋ณต์‚ฌํ•˜๊ณ , ์ด์™ธ์˜ ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ ๋‘ก๋‹ˆ๋‹ค.
์ด ํŒŒ์ผ์ด **์ž์ฃผ ๋ฐ”๋€Œ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—**, ๋„์ปค๋Š” ํŒŒ์ผ์„ ํƒ์ง€ํ•˜์—ฌ ์ด ๋‹จ๊ณ„์˜ **์บ์‹œ**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ๋„ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
4. ์š”๊ตฌ ์กฐ๊ฑด ํŒŒ์ผ์— ์žˆ๋Š” ํŒจํ‚ค์ง€ ์ข…์†์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
`--no-cache-dir` ์˜ต์…˜์€ `pip`์—๊ฒŒ ๋‹ค์šด๋กœ๋“œํ•œ ํŒจํ‚ค์ง€๋“ค์„ ๋กœ์ปฌ ํ™˜๊ฒฝ์— ์ €์žฅํ•˜์ง€ ์•Š๋„๋ก ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋งˆ์น˜ ๊ฐ™์€ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด ์˜ค์ง `pip`๋งŒ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ, ์ปจํ…Œ์ด๋„ˆ๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ ๊ทธ๋ ‡์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
!!! ๋…ธํŠธ
`--no-cache-dir` ๋Š” ์˜ค์ง `pip`์™€ ๊ด€๋ จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๋„์ปค๋‚˜ ์ปจํ…Œ์ด๋„ˆ์™€๋Š” ๋ฌด๊ด€ํ•ฉ๋‹ˆ๋‹ค.
`--upgrade` ์˜ต์…˜์€ `pip`์—๊ฒŒ ์„ค์น˜๋œ ํŒจํ‚ค์ง€๋“ค์„ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
์ด์ „ ๋‹จ๊ณ„์—์„œ ํŒŒ์ผ์„ ๋ณต์‚ฌํ•œ ๊ฒƒ์ด **๋„์ปค ์บ์‹œ**์— ์˜ํ•ด ํƒ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด ๋‹จ๊ณ„์—์„œ๋„ ๊ฐ€๋Šฅํ•œ ํ•œ **๋„์ปค ์บ์‹œ**๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ด ๋‹จ๊ณ„์—์„œ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด **๋งค๋ฒˆ** ๋ชจ๋“  ์ข…์†์„ฑ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ  ์„ค์น˜ํ•  ํ•„์š”๊ฐ€ ์—†์–ด, ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์ง€์†์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐ์— ๋“œ๋Š” **์‹œ๊ฐ„**์„ ๋งŽ์ด **์ ˆ์•ฝ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
5. `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ์— `./app` ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
**์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š”** ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋„์ปค **์บ์‹œ**๋Š” ์ด ๋‹จ๊ณ„๋‚˜ **์ดํ›„์˜ ๋‹จ๊ณ„์—์„œ** ์ž˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ๋นŒ๋“œ ์‹œ๊ฐ„์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด `Dockerfile`์˜ **๊ฑฐ์˜ ๋ ๋ถ€๋ถ„**์— ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
6. `uvicorn` ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด **์ปค๋งจ๋“œ**๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
`CMD`๋Š” ๋ฌธ์ž์—ด ๋ฆฌ์ŠคํŠธ๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ , ๊ฐ ๋ฌธ์ž์—ด์€ ์ปค๋งจ๋“œ ๋ผ์ธ์˜ ๊ฐ ์ค„์— ์ž…๋ ฅํ•  ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค.
์ด ์ปค๋งจ๋“œ๋Š” **ํ˜„์žฌ ์›Œํ‚น ๋””๋ ‰ํ„ฐ๋ฆฌ**์—์„œ ์‹คํ–‰๋˜๋ฉฐ, ์ด๋Š” ์œ„์—์„œ `WORKDIR /code`๋กœ ์„ค์ •ํ•œ `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ๊ทธ๋žจ์ด `/code`์—์„œ ์‹œ์ž‘ํ•˜๊ณ  ๊ทธ ์†์— `./app` ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋“ค์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์—, **Uvicorn**์€ ์ด๋ฅผ ๋ณด๊ณ  `app`์„ `app.main`์œผ๋กœ๋ถ€ํ„ฐ **๋ถˆ๋Ÿฌ ์˜ฌ** ๊ฒƒ์ž…๋‹ˆ๋‹ค.
!!! ํŒ
๊ฐ ์ฝ”๋“œ ๋ผ์ธ์„ ์ฝ”๋“œ์˜ ์ˆซ์ž ๋ฒ„๋ธ”์„ ํด๋ฆญํ•˜์—ฌ ๋ฆฌ๋ทฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ‘†
์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
```
.
โ”œโ”€โ”€ app
โ”‚ย ย  โ”œโ”€โ”€ __init__.py
โ”‚ โ””โ”€โ”€ main.py
โ”œโ”€โ”€ Dockerfile
โ””โ”€โ”€ requirements.txt
```
#### TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ์˜ ๋ฐฐํ›„
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ Nginx ๋˜๋Š” Traefik๊ณผ ๊ฐ™์€ TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ (๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ) ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, `--proxy-headers` ์˜ต์…˜์„ ๋”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ Uvicorn์—๊ฒŒ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด HTTPS ๋“ฑ์˜ ๋’ค์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ”„๋ก์‹œ์—์„œ ์ „์†ก๋œ ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์•Œ๋ฆฝ๋‹ˆ๋‹ค.
```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
```
#### ๋„์ปค ์บ์‹œ
์ด `Dockerfile`์—๋Š” ์ค‘์š”ํ•œ ํŠธ๋ฆญ์ด ์žˆ๋Š”๋ฐ, ์ฒ˜์Œ์—๋Š” **์˜์กด์„ฑ์ด ์žˆ๋Š” ํŒŒ์ผ๋งŒ** ๋ณต์‚ฌํ•˜๊ณ , ๋‚˜๋จธ์ง€ ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ ๋‘ก๋‹ˆ๋‹ค. ์™œ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์จ์•ผํ•˜๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
```Dockerfile
COPY ./requirements.txt /code/requirements.txt
```
๋„์ปค์™€ ๋‹ค๋ฅธ ๋„๊ตฌ๋“ค์€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ **์ฆ๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋นŒ๋“œ**ํ•ฉ๋‹ˆ๋‹ค. `Dockerfile`์˜ ๋งจ ์œ— ๋ถ€๋ถ„๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด, ๋ ˆ์ด์–ด ์œ„์— ์ƒˆ๋กœ์šด ๋ ˆ์ด์–ด๋ฅผ ๋”ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, `Dockerfile`์˜ ๊ฐ ์ง€์‹œ ์‚ฌํ•ญ์œผ๋กœ ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ ์–ด๋–ค ํŒŒ์ผ์ด๋“  ๋”ํ•ด๊ฐ‘๋‹ˆ๋‹ค.
๋„์ปค ๊ทธ๋ฆฌ๊ณ  ์ด์™€ ์œ ์‚ฌํ•œ ๋„๊ตฌ๋“ค์€ ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์‹œ์— **๋‚ด๋ถ€ ์บ์‹œ**๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ํŒŒ์ผ์ด ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•œ ๋•Œ๋กœ๋ถ€ํ„ฐ ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค๋ฉด, ํŒŒ์ผ์„ ๋‹ค์‹œ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ ˆ์ด์–ด๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋งˆ์ง€๋ง‰์— ์ƒ์„ฑํ–ˆ๋˜ **๊ฐ™์€ ๋ ˆ์ด์–ด๋ฅผ ์žฌ์‚ฌ์šฉ**ํ•ฉ๋‹ˆ๋‹ค.
๋‹จ์ง€ ํŒŒ์ผ ๋ณต์‚ฌ๋ฅผ ์ง€์–‘ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํšจ์œจ์ด ๋งŽ์ด ํ–ฅ์ƒ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ทธ ๋‹จ๊ณ„์—์„œ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, **๋‹ค์Œ ๋‹จ๊ณ„์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์บ์‹œ๋ฅผ ์‚ฌ์šฉ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•˜๋Š” ์ง€์‹œ ์‚ฌํ•ญ์„ ์œ„ํ•œ ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
```Dockerfile
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
```
ํŒจํ‚ค์ง€๋ฅผ ํฌํ•จํ•˜๋Š” ํŒŒ์ผ์€ **์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค**. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ํŒŒ์ผ๋งŒ ๋ณต์‚ฌํ•˜๋ฏ€๋กœ์„œ, ๋„์ปค๋Š” ๊ทธ ๋‹จ๊ณ„์˜ **์บ์‹œ๋ฅผ ์‚ฌ์šฉ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ ๋‹ค์Œ์œผ๋กœ, ๋„์ปค๋Š” **๋‹ค์Œ ๋‹จ๊ณ„์—์„œ** ์˜์กด์„ฑ์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์„ค์น˜ํ•˜๋Š” **์บ์‹œ๋ฅผ ์‚ฌ์šฉ**ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ด ๊ณผ์ •์—์„œ ์šฐ๋ฆฌ๋Š” **๋งŽ์€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝ**ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โœจ ...๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ง€๋ฃจํ•จ๋„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ช๐Ÿ˜†
ํŒจํ‚ค์ง€ ์˜์กด์„ฑ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ  ์„ค์น˜ํ•˜๋Š” ๋ฐ์ด๋Š” **์ˆ˜ ๋ถ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ**, **์บ์‹œ**๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ๋Œ€ **์ˆ˜ ์ดˆ๋งŒ์—** ๋๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐ˜์˜๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๊ณ„์†ํ•ด์„œ ๋นŒ๋“œํ•˜๋ฉด, ์ ˆ์•ฝ๋œ ์‹œ๊ฐ„์€ ์ถ•์ ๋˜์–ด ๋”์šฑ ์ปค์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ `Dockerfile`์˜ ๊ฑฐ์˜ ๋ ๋ถ€๋ถ„์—์„œ, ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด **๊ฐ€์žฅ ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ณ€๊ฒฝ**๋˜๋Š” ๋ถ€๋ถ„์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ์ด ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ๋Š” ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ๋‘ก๋‹ˆ๋‹ค.
```Dockerfile
COPY ./app /code/app
```
### ๋„์ปค ์ด๋ฏธ์ง€ ์ƒ์„ฑํ•˜๊ธฐ
์ด์ œ ๋ชจ๋“  ํŒŒ์ผ์ด ์ œ์ž๋ฆฌ์— ์žˆ์œผ๋‹ˆ, ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค.
* (์—ฌ๋Ÿฌ๋ถ„์˜ `Dockerfile`๊ณผ `app` ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์œ„์น˜ํ•œ) ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
* FastAPI ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค:
<div class="termy">
```console
$ docker build -t myimage .
---> 100%
```
</div>
!!! ํŒ
๋งจ ๋์— ์žˆ๋Š” `.` ์— ์ฃผ๋ชฉํ•ฉ์‹œ๋‹ค. ์ด๋Š” `./`์™€ ๋™๋“ฑํ•˜๋ฉฐ, ๋„์ปค์—๊ฒŒ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜๊ธฐ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ์—๋Š” ํ˜„์žฌ ๋””๋ ‰ํ„ฐ๋ฆฌ(`.`)์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
### ๋„์ปค ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ํ•˜๊ธฐ
* ์—ฌ๋Ÿฌ๋ถ„์˜ ์ด๋ฏธ์ง€์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:
<div class="termy">
```console
$ docker run -d --name mycontainer -p 80:80 myimage
```
</div>
## ์ฒดํฌํ•˜๊ธฐ
์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ URL์—์„œ ์‹คํ–‰ ์‚ฌํ•ญ์„ ์ฒดํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ๋˜๋Š” <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (๋˜๋Š” ๋™์ผํ•˜๊ฒŒ, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์ปค ํ˜ธ์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ์ฒดํฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค).
์•„๋ž˜์™€ ๋น„์Šทํ•œ ๊ฒƒ์„ ๋ณด๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
```JSON
{"item_id": 5, "q": "somequery"}
```
## ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ API ๋ฌธ์„œ
์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ๋˜๋Š” <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a>๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋˜๋Š”, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์ปค ํ˜ธ์ŠคํŠธ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
์—ฌ๋Ÿฌ๋ถ„์€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ API(<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>์—์„œ ์ œ๊ณต๋œ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
## ๋Œ€์•ˆ API ๋ฌธ์„œ
๋˜ํ•œ ์—ฌ๋Ÿฌ๋ถ„์€ <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ๋˜๋Š” <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a>์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋˜๋Š”, ์—ฌ๋Ÿฌ๋ถ„์˜ ๋„์ปค ํ˜ธ์ŠคํŠธ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
์—ฌ๋Ÿฌ๋ถ„์€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ๋Œ€์•ˆ ๋ฌธ์„œ(<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>์—์„œ ์ œ๊ณต๋œ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## ๋‹จ์ผ ํŒŒ์ผ FastAPI๋กœ ๋„์ปค ์ด๋ฏธ์ง€ ์ƒ์„ฑํ•˜๊ธฐ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ FastAPI๊ฐ€ ํ•˜๋‚˜์˜ ํŒŒ์ผ์ด๋ผ๋ฉด, ์˜ˆ๋ฅผ ๋“ค์–ด `./app` ๋””๋ ‰ํ„ฐ๋ฆฌ ์—†์ด `main.py` ํŒŒ์ผ๋งŒ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค๋ฉด, ํŒŒ์ผ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:
```
.
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ main.py
โ””โ”€โ”€ requirements.txt
```
๊ทธ๋Ÿฌ๋ฉด ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ `Dockerfile` ๋‚ด์— ์žˆ๋Š” ํŒŒ์ผ์„ ๋ณต์‚ฌํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ์ € ์ƒ์‘ํ•˜๋Š” ๊ฒฝ๋กœ๋ฅผ ๋ฐ”๊พธ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค:
```{ .dockerfile .annotate hl_lines="10 13" }
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (1)
COPY ./main.py /code/
# (2)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
```
1. `main.py` ํŒŒ์ผ์„ `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๊ณง๋ฐ”๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค(`./app` ๋””๋ ‰ํ„ฐ๋ฆฌ๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
2. Uvicorn์„ ์‹คํ–‰ํ•ด `app` ๊ฐ์ฒด๋ฅผ (`app.main` ๋Œ€์‹ ) `main`์œผ๋กœ ๋ถ€ํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ ๋‹ค์Œ Uvicorn ์ปค๋งจ๋“œ๋ฅผ ์กฐ์ •ํ•ด์„œ FastAPI ๊ฐ์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ `app.main` ๋Œ€์‹ ์— ์ƒˆ๋กœ์šด ๋ชจ๋“ˆ `main`์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
## ๋ฐฐํฌ ๊ฐœ๋…
์ด์ œ ์ปจํ…Œ์ด๋„ˆ์˜ ์ธก๋ฉด์—์„œ [๋ฐฐํฌ ๊ฐœ๋…](./concepts.md){.internal-link target=_blank}์—์„œ ๋‹ค๋ฃจ์—ˆ๋˜ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฐํฌ ๊ฐœ๋…์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์ปจํ…Œ์ด๋„ˆ๋Š” ์ฃผ๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •์„ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๋„๊ตฌ์ด์ง€๋งŒ, **๋ฐฐํฌ ๊ฐœ๋…**์— ๋Œ€ํ•œ ํŠน์ •ํ•œ ์ ‘๊ทผ๋ฒ•์„ ๊ฐ•์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•œ ๋ฐฐํฌ ์ „๋žต์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
**์ข‹์€ ์†Œ์‹**์€ ์„œ๋กœ ๋‹ค๋ฅธ ์ „๋žต๋“ค์„ ํฌ๊ด„ํ•˜๋Š” ๋ฐฐํฌ ๊ฐœ๋…์ด ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๐ŸŽ‰
์ปจํ…Œ์ด๋„ˆ ์ธก๋ฉด์—์„œ **๋ฐฐํฌ ๊ฐœ๋…**์„ ๋ฆฌ๋ทฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:
* HTTPS
* ๊ตฌ๋™ํ•˜๊ธฐ
* ์žฌ์‹œ์ž‘
* ๋ณต์ œ (์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜)
* ๋ฉ”๋ชจ๋ฆฌ
* ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ๋‹จ๊ณ„๋“ค
## HTTPS
๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ FastAPI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ **์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**์—๋งŒ ์ง‘์ค‘ํ•œ๋‹ค๋ฉด (๊ทธ๋ฆฌ๊ณ  ๋‚˜์ค‘์— ์‹คํ–‰๋  **์ปจํ…Œ์ด๋„ˆ**์—), HTTPS๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค๋ฅธ ๋„๊ตฌ์— ์˜ํ•ด **์™ธ๋ถ€์ ์œผ๋กœ** ๋‹ค๋ฃจ์–ด์งˆ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
**HTTPS**์™€ **์ธ์ฆ์„œ**์˜ **์ž๋™** ์ทจ๋“์„ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์˜ˆ๋ฅผ ๋“ค์–ด <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
!!! ํŒ
Traefik์€ ๋„์ปค, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค, ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ํ†ตํ•ฉ๋˜์–ด ์žˆ์–ด ์—ฌ๋Ÿฌ๋ถ„์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํฌํ•จํ•˜๋Š” HTTPS๋ฅผ ์…‹์—…ํ•˜๊ณ  ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
๋Œ€์•ˆ์ ์œผ๋กœ, HTTPS๋Š” ํด๋ผ์šฐ๋“œ ์ œ๊ณต์ž์— ์˜ํ•ด ์„œ๋น„์Šค์˜ ์ผํ™˜์œผ๋กœ ๋‹ค๋ฃจ์–ด์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค (์ด๋•Œ๋„ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—ฌ์ „ํžˆ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค).
## ๊ตฌ๋™๊ณผ ์žฌ์‹œ์ž‘
์—ฌ๋Ÿฌ๋ถ„์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ **์‹œ์ž‘ํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š”** ๋ฐ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋„๊ตฌ๋Š” ๋”ฐ๋กœ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋Š” **๋„์ปค** ์ž์ฒด์ผ ์ˆ˜๋„ ์žˆ๊ณ , **๋„์ปค ์ปดํฌ์ฆˆ**, **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**, **ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค** ๋“ฑ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋Œ€๋ถ€๋ถ„ (๋˜๋Š” ์ „์ฒด) ๊ฒฝ์šฐ์—, ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ตฌ๋™ํ•˜๊ฑฐ๋‚˜ ๊ณ ์žฅ์‹œ์— ์žฌ์‹œ์ž‘ํ•˜๋„๋ก ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„์ปค์—์„œ๋Š”, ์ปค๋งจ๋“œ ๋ผ์ธ ์˜ต์…˜ `--restart` ์ž…๋‹ˆ๋‹ค.
์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ์„œ๋Š”, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋™ํ•˜๊ณ  ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ **์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด** ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ์ด๋Ÿฐ ๊ธฐ๋Šฅ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. โœจ
## ๋ณต์ œ - ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**์™€ ๋จธ์‹  <abbr title="A group of machines that are configured to be connected and work together in some way.">ํด๋Ÿฌ์Šคํ„ฐ</abbr>, ๋„์ปค ์Šค์™ ๋ชจ๋“œ, ๋…ธ๋งˆ๋“œ, ๋˜๋Š” ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๋จธ์‹  ์œ„์— ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์„ ๋‹ค๋ฃจ๊ณ  ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฐ ์ปจํ…Œ์ด๋„ˆ์—์„œ (์›Œ์ปค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” Gunicorn ๊ฐ™์€) **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €** ๋Œ€์‹  **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ **๋ณต์ œ๋ฅผ ๋‹ค๋ฃจ**๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์™€ ๊ฐ™์€ ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ ์ค‘ ์ผ๋ถ€๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ**์„ ์ง€์›ํ•˜๋ฉด์„œ **์ปจํ…Œ์ด๋„ˆ ๋ณต์ œ**๋ฅผ ๋‹ค๋ฃจ๋Š” ํ†ตํ•ฉ๋œ ๋ฐฉ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ **ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ**์—์„œ ๋ง์ด์ฃ .
์ด๋Ÿฐ ๊ฒฝ์šฐ์—, ์—ฌ๋Ÿฌ๋ถ„์€ [์œ„์—์„œ ๋ฌ˜์‚ฌ๋œ ๊ฒƒ](#dockerfile)์ฒ˜๋Ÿผ **์ฒ˜์Œ๋ถ€ํ„ฐ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ** ๋นŒ๋“œํ•ด์„œ, ์˜์กด์„ฑ์„ ์„ค์น˜ํ•˜๊ณ , Uvicorn ์›Œ์ปค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” Gunicorn ๋Œ€์‹  **๋‹จ์ผ Uvicorn ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
### ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ
์ปจํ…Œ์ด๋„ˆ๋กœ ์ž‘์—…ํ•  ๋•Œ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ผ๋ฐ˜์ ์œผ๋กœ **๋ฉ”์ธ ํฌํŠธ์˜ ์ƒํ™ฉ์„ ๊ฐ์ง€ํ•˜๋Š”** ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” **HTTPS**๋ฅผ ๋‹ค๋ฃจ๋Š” **TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ**์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์ผ ์ˆ˜๋„ ์žˆ๊ณ , ์œ ์‚ฌํ•œ ๋‹ค๋ฅธ ๋„๊ตฌ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์š”์†Œ๊ฐ€ ์š”์ฒญ๋“ค์˜ **๋กœ๋“œ**๋ฅผ ์ฝ์–ด๋“ค์ด๊ณ  ๊ฐ ์›Œ์ปค์—๊ฒŒ (๋ฐ”๋ผ๊ฑด๋Œ€) **๊ท ํ˜•์ ์œผ๋กœ** ๋ถ„๋ฐฐํ•œ๋‹ค๋ฉด, ์ด ์š”์†Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๋ผ๊ณ  ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค.
!!! ํŒ
HTTPS๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋œ **TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ** ์š”์†Œ ๋˜ํ•œ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ์ปจํ…Œ์ด๋„ˆ๋กœ ์ž‘์—…ํ•  ๋•Œ, ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์‹œ์Šคํ…œ์€ ์ด๋ฏธ ํ•ด๋‹น **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๋กœ ๋ถ€ํ„ฐ ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์— ํ•ด๋‹นํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ๋กœ **๋„คํŠธ์›Œํฌ ํ†ต์‹ **(์˜ˆ๋ฅผ ๋“ค์–ด, HTTP ์š”์ฒญ)์„ ์ „์†กํ•˜๋Š” ๋‚ด๋ถ€์ ์ธ ๋„๊ตฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค (์—ฌ๊ธฐ์„œ๋„ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋Š” **TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ**์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
### ํ•˜๋‚˜์˜ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ - ๋‹ค์ค‘ ์›Œ์ปค ์ปจํ…Œ์ด๋„ˆ
**์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**๋‚˜ ๋˜๋Š” ๋‹ค๋ฅธ ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์œผ๋กœ ์ž‘์—…ํ•  ๋•Œ, ์‹œ์Šคํ…œ ๋‚ด๋ถ€์˜ ๋„คํŠธ์›Œํ‚น ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ด์šฉํ•จ์œผ๋กœ์จ ๋ฉ”์ธ **ํฌํŠธ**๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์žˆ๋Š” ๋‹จ์ผ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” **์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ**์— ํ†ต์‹ (์š”์ฒญ๋“ค)์„ ์ „์†กํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ๊ฐ๊ฐ์˜ ์ปจํ…Œ์ด๋„ˆ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค**๋งŒ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค (์˜ˆ๋ฅผ ๋“ค์–ด, FastAPI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‹คํ–‰๋˜๋Š” ํ•˜๋‚˜์˜ Uvicorn ํ”„๋กœ์„ธ์Šค์ฒ˜๋Ÿผ). ์ด ์ปจํ…Œ์ด๋„ˆ๋“ค์€ ๋ชจ๋‘ ๊ฐ™์€ ๊ฒƒ์„ ์‹คํ–‰ํ•˜๋Š” ์ ์—์„œ **๋™์ผํ•œ ์ปจํ…Œ์ด๋„ˆ**์ด์ง€๋งŒ, ํ”„๋กœ์„ธ์Šค, ๋ฉ”๋ชจ๋ฆฌ ๋“ฑ์€ ๊ณต์œ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์€ CPU์˜ **์„œ๋กœ ๋‹ค๋ฅธ ์ฝ”์–ด๋“ค** ๋˜๋Š” **์„œ๋กœ ๋‹ค๋ฅธ ๋จธ์‹ ๋“ค**์„ **๋ณ‘๋ ฌํ™”**ํ•˜๋Š” ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๊ฐ€ ์žˆ๋Š” ๋ถ„์‚ฐ ์ปจํ…Œ์ด๋„ˆ ์‹œ์Šคํ…œ์€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์— ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ ๊ฐ๊ฐ์— **์ฐจ๋ก€๋Œ€๋กœ ์š”์ฒญ์„ ๋ถ„์‚ฐ**์‹œํ‚ฌ ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ ์š”์ฒญ์€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์—์„œ ์‹คํ–‰๋˜๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ **๋ณต์ œ๋œ ์ปจํ…Œ์ด๋„ˆ๋“ค** ์ค‘ ํ•˜๋‚˜์— ์˜ํ•ด ๋‹ค๋ฃจ์–ด์งˆ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ**๋Š” ์—ฌ๋Ÿฌ๋ถ„์˜ ํด๋Ÿฌ์Šคํ„ฐ์— ์žˆ๋Š” *๋‹ค๋ฅธ* ์•ฑ์œผ๋กœ ๊ฐ€๋Š” ์š”์ฒญ๋“ค๋„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์œผ๋ฉฐ (์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์œผ๋กœ ๊ฐ€๊ฑฐ๋‚˜ ๋‹ค๋ฅธ URL ๊ฒฝ๋กœ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒฝ์šฐ), ์ด ํ†ต์‹ ๋“ค์„ ํด๋Ÿฌ์Šคํ„ฐ์— ์žˆ๋Š” *๋ฐ”๋กœ ๊ทธ ๋‹ค๋ฅธ* ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ œ๋Œ€๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
### ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๋Š” ์ปจํ…Œ์ด๋„ˆ
์ด ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ๊ฒฝ์šฐ, ์—ฌ๋Ÿฌ๋ถ„์€ ์ด๋ฏธ ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ์—์„œ ๋ณต์ œ๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋ฏ€๋กœ **์ปจํ…Œ์ด๋„ˆ ๋‹น ๋‹จ์ผ (Uvicorn) ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๊ณ ์ž ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์—ฌ๋Ÿฌ๋ถ„์€ Gunicorn ์ด๋‚˜ Uvicorn ์›Œ์ปค, ๋˜๋Š” Uvicorn ์›Œ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Uvicorn ๋งค๋‹ˆ์ €์™€ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €๋ฅผ ๊ฐ€์ง€๊ณ  ์‹ถ์–ดํ•˜์ง€ **์•Š์„** ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ์ปจํ…Œ์ด๋„ˆ ๋‹น **๋‹จ์ผ Uvicorn ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๊ณ  ์‹ถ์–ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค (๊ทธ๋Ÿฌ๋‚˜ ์•„๋งˆ๋„ ๋‹ค์ค‘ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค).
์ด๋ฏธ ์—ฌ๋Ÿฌ๋ถ„์ด ํด๋Ÿฌ์Šคํ„ฐ ์‹œ์Šคํ…œ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, (Uvicorn ์›Œ์ปค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” Gunicorn ์ด๋‚˜ Uvicorn ์ฒ˜๋Ÿผ) ์ปจํ…Œ์ด๋„ˆ ๋‚ด์— ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์€ **๋ถˆํ•„์š”ํ•œ ๋ณต์žก์„ฑ**๋งŒ ๋”ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
### ๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๋Š” ์ปจํ…Œ์ด๋„ˆ์™€ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๋“ค
๋‹น์—ฐํ•œ ๋ง์ด์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์ด ๋‚ด๋ถ€์ ์œผ๋กœ **Uvicorn ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋“ค**๋ฅผ ์‹œ์ž‘ํ•˜๋Š” **Gunicorn ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**๋ฅผ ๊ฐ€์ง€๋Š” ๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์›ํ•˜๋Š” **ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ**๋„ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—, ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ **Gunicorn**์„ ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €๋กœ ํฌํ•จํ•˜๋Š” **๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€**๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €๋Š” ๋‹ค์ค‘ **Uvicorn ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋“ค**์„ ์‹คํ–‰ํ•˜๋ฉฐ, ๋””ํดํŠธ ์„ธํŒ…์œผ๋กœ ํ˜„์žฌ CPU ์ฝ”์–ด์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ž๋™์œผ๋กœ ์›Œ์ปค ๊ฐœ์ˆ˜๋ฅผ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์‚ฌํ•ญ์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜์˜ [Gunicorn๊ณผ ํ•จ๊ป˜ํ•˜๋Š” ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€ - Uvicorn](#official-docker-image-with-gunicorn-uvicorn)์—์„œ ๋” ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•˜๋Š” ๋ช‡๊ฐ€์ง€ ์˜ˆ์‹œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:
#### ๋‹จ์ˆœํ•œ ์•ฑ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด **์ถฉ๋ถ„ํžˆ ๋‹จ์ˆœ**ํ•ด์„œ (์ ์–ด๋„ ์•„์ง์€) ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜๋ฅผ ํŒŒ์ธ-ํŠ  ํ•  ํ•„์š”๊ฐ€ ์—†๊ฑฐ๋‚˜ ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์•„๋‹Œ **๋‹จ์ผ ์„œ๋ฒ„**์—์„œ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์ปจํ…Œ์ด๋„ˆ ๋‚ด์— ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ (๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€์—์„œ) ์ž๋™์œผ๋กœ ์„ค์ •๋˜๋Š” ๋””ํดํŠธ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
#### ๋„์ปค ๊ตฌ์„ฑ
์—ฌ๋Ÿฌ๋ถ„์€ **๋„์ปค ์ปดํฌ์ฆˆ**๋กœ (ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์•„๋‹Œ) **๋‹จ์ผ ์„œ๋ฒ„๋กœ** ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ๊ฒฝ์šฐ์— ๊ณต์œ ๋œ ๋„คํŠธ์›Œํฌ์™€ **๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ**์„ ํฌํ•จํ•˜๋Š” (๋„์ปค ์ปดํฌ์ฆˆ๋กœ) ์ปจํ…Œ์ด๋„ˆ์˜ ๋ณต์ œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์ด ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ **ํ”„๋กœ์„ธ์Šค ๋งค๋‹ˆ์ €**์™€ ํ•จ๊ป˜ ๋‚ด๋ถ€์— **๋ช‡๊ฐœ์˜ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค๋“ค**์„ ์‹œ์ž‘ํ•˜๋Š” **๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ํ•„์š”๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
#### Prometheus์™€ ๋‹ค๋ฅธ ์ด์œ ๋“ค
์—ฌ๋Ÿฌ๋ถ„์€ **๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๋Š” **๋‹ค์ค‘ ์ปจํ…Œ์ด๋„ˆ** ๋Œ€์‹  **๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๋Š” **๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ์ฑ„ํƒํ•˜๋Š” **๋‹ค๋ฅธ ์ด์œ **๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด (์—ฌ๋Ÿฌ๋ถ„์˜ ์žฅ์น˜ ์„ค์ •์— ๋”ฐ๋ผ) Prometheus ์ต์Šคํฌํ„ฐ์™€ ๊ฐ™์ด ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ์— ๋“ค์–ด์˜ค๋Š” **๊ฐ ์š”์ฒญ์— ๋Œ€ํ•ด** ์ ‘๊ทผ๊ถŒํ•œ์„ ๊ฐ€์ง€๋Š” ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ์— ์—ฌ๋Ÿฌ๋ถ„์ด **์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋“ค**์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, Prometheus๊ฐ€ **๋ฉ”ํŠธ๋ฆญ์„ ์ฝ์–ด ๋“ค์ผ ๋•Œ**, ๋””ํดํŠธ๋กœ **๋งค๋ฒˆ ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ**(ํŠน์ • ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ”๋กœ ๊ทธ ์ปจํ…Œ์ด๋„ˆ)๋กœ ๋ถ€ํ„ฐ ์ฝ์–ด๋“ค์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ชจ๋“  ๋ณต์ œ๋œ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•ด **์ถ•์ ๋œ ๋ฉ”ํŠธ๋ฆญ๋“ค**์„ ์ฝ์–ด๋“ค์ด๋Š” ๊ฒƒ๊ณผ ๋Œ€๋น„๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์ด ๊ฒฝ์šฐ์—๋Š” **๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๋Š” **ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ๋‘์–ด์„œ ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋ชจ๋“  ๋‚ด๋ถ€ ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ Prometheus ๋ฉ”ํŠธ๋ฆญ์„ ์ˆ˜์ง‘ํ•˜๋Š” ๋กœ์ปฌ ๋„๊ตฌ(์˜ˆ๋ฅผ ๋“ค์–ด Prometheus ์ต์Šคํฌํ„ฐ ๊ฐ™์€)๋ฅผ ๋‘์–ด์„œ ์ด ๋ฉ”๊ทธ๋ฆญ๋“ค์„ ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ์— ๋‚ด์—์„œ ๊ณต์œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋” ๋‹จ์ˆœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
---
์š”์ ์€, ์ด ์ค‘์˜ **์–ด๋Š๊ฒƒ๋„** ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ๋ฐ˜๋“œ์‹œ ๋”ฐ๋ผ์•ผํ•˜๋Š” **ํ™•์ •๋œ ์‚ฌ์‹ค**์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ์ด ์•„์ด๋””์–ด๋“ค์„ **์—ฌ๋Ÿฌ๋ถ„์˜ ๊ณ ์œ ํ•œ ์ด์šฉ ์‚ฌ๋ก€๋ฅผ ํ‰๊ฐ€**ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•˜๊ณ , ์—ฌ๋Ÿฌ๋ถ„์˜ ์‹œ์Šคํ…œ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์ ‘๊ทผ๋ฒ•์ด ์–ด๋–ค ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•˜๋ฉฐ, ๋‹ค์Œ์˜ ๊ฐœ๋…๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
* ๋ณด์•ˆ - HTTPS
* ๊ตฌ๋™ํ•˜๊ธฐ
* ์žฌ์‹œ์ž‘
* ๋ณต์ œ (์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜)
* ๋ฉ”๋ชจ๋ฆฌ
* ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ๋‹จ๊ณ„๋“ค
## ๋ฉ”๋ชจ๋ฆฌ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด **์ปจํ…Œ์ด๋„ˆ ๋‹น ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฐ ์ปจํ…Œ์ด๋„ˆ(๋ณต์ œ๋œ ๊ฒฝ์šฐ์—๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ๋“ค)์— ๋Œ€ํ•ด ์ž˜ ์ •์˜๋˜๊ณ , ์•ˆ์ •์ ์ด๋ฉฐ, ์ œํ•œ๋œ ์šฉ๋Ÿ‰์˜ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„๋Ÿ‰์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด ์—ฌ๋Ÿฌ๋ถ„์˜ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ(์˜ˆ๋ฅผ ๋“ค์–ด **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**) ์„ค์ •์—์„œ ์•ž์„œ ์ •์˜๋œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ๊ณผ ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ **๊ฐ€์šฉ ๋จธ์‹ **์ด ํ•„์š”๋กœํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ์™€ ํด๋Ÿฌ์Šคํ„ฐ์— ์žˆ๋Š” ๊ฐ€์šฉ ๋จธ์‹ ๋“ค์„ ์—ผ๋‘์— ๋‘๊ณ  **์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋ณต์ œ**ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด **๋‹จ์ˆœ**ํ•˜๋‹ค๋ฉด, ์ด๊ฒƒ์€ **๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„** ๊ฒƒ์ด๊ณ , ๊ณ ์ •๋œ ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ์„ ๊ตฌ์ฒดํ™”ํ•  ํ•„์š”๋„ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด (์˜ˆ๋ฅผ ๋“ค์–ด **๋จธ์‹  ๋Ÿฌ๋‹** ๋ชจ๋ธ๊ฐ™์ด) **๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ์š”ํ•œ๋‹ค๋ฉด**, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์–‘์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  **๊ฐ ๋จธ์‹ ์—์„œ** ์‚ฌ์šฉํ•˜๋Š” **์ปจํ…Œ์ด๋„ˆ์˜ ์ˆ˜**๋ฅผ ์กฐ์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (๊ทธ๋ฆฌ๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ๋ถ„์˜ ํด๋Ÿฌ์Šคํ„ฐ์— ๋จธ์‹ ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด **์ปจํ…Œ์ด๋„ˆ ๋‹น ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค**๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด (์˜ˆ๋ฅผ ๋“ค์–ด ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€ ์ฒ˜๋Ÿผ), ์—ฌ๋Ÿฌ๋ถ„์€ ์‹œ์ž‘๋œ ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜๊ฐ€ ๊ฐ€์šฉํ•œ ๊ฒƒ ๋ณด๋‹ค **๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์†Œ๋น„**ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
## ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ๋‹จ๊ณ„๋“ค๊ณผ ์ปจํ…Œ์ด๋„ˆ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ์ปจํ…Œ์ด๋„ˆ(์˜ˆ๋ฅผ ๋“ค์–ด ๋„์ปค, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
### ๋‹ค์ค‘ ์ปจํ…Œ์ด๋„ˆ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด **์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ์•„๋งˆ๋„ ๊ฐ๊ฐ์˜ ์ปจํ…Œ์ด๋„ˆ๋Š” **ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค**๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด, **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค** ํด๋Ÿฌ์Šคํ„ฐ์—์„œ). ๊ทธ๋Ÿฌ๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ ๋ณต์ œ๋œ ์›Œ์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ **์ด์ „์—**, ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ์— ์žˆ๋Š” **์ด์ „์˜ ๋‹จ๊ณ„๋“ค์„** ์ˆ˜ํ–‰ํ•˜๋Š” ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๋Š” **๋ณ„๋„์˜ ์ปจํ…Œ์ด๋„ˆ๋“ค**์„ ๊ฐ€์ง€๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
!!! ์ •๋ณด
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์•„๋งˆ๋„ ์ด๋Š” <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ด์šฉ ์‚ฌ๋ก€์—์„œ ์ด์ „ ๋‹จ๊ณ„๋“ค์„ **๋ณ‘๋ ฌ์ ์œผ๋กœ ์—ฌ๋Ÿฌ๋ฒˆ** ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด (์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ด์ „์„ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ค€๋น„๋˜์—ˆ๋Š”์ง€ ํ™•์ธ๋งŒ ํ•˜๋Š” ๊ฒฝ์šฐ), ๋ฉ”์ธ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ด ๋‹จ๊ณ„๋“ค์„ ๊ฐ ์ปจํ…Œ์ด๋„ˆ์— ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
### ๋‹จ์ผ ์ปจํ…Œ์ด๋„ˆ
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์…‹์—…์ด **๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค**(๋˜๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค)๋ฅผ ์‹œ์ž‘ํ•˜๋Š” **ํ•˜๋‚˜์˜ ์ปจํ…Œ์ด๋„ˆ**๋ฅผ ๊ฐ€์ง€๋Š” ๋‹จ์ˆœํ•œ ์…‹์—…์ด๋ผ๋ฉด, ์‚ฌ์ „ ๋‹จ๊ณ„๋“ค์„ ์•ฑ์„ ํฌํ•จํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ง์ „์— ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€๋Š” ์ด๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
## Gunicorn๊ณผ ํ•จ๊ป˜ํ•˜๋Š” ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€ - Uvicorn
์•ž ์ฑ•ํ„ฐ์—์„œ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…๋œ ๊ฒƒ ์ฒ˜๋Ÿผ, Uvicorn ์›Œ์ปค์™€ ๊ฐ™์ด ์‹คํ–‰๋˜๋Š” Gunicorn์„ ํฌํ•จํ•˜๋Š” ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: [์„œ๋ฒ„ ์›Œ์ปค - Uvicorn๊ณผ ํ•จ๊ป˜ํ•˜๋Š” Gunicorn](./server-workers.md){.internal-link target=_blank}.
์ด ์ด๋ฏธ์ง€๋Š” ์ฃผ๋กœ ์œ„์—์„œ ์„ค๋ช…๋œ ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค: [๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๋Š” ์ปจํ…Œ์ด๋„ˆ์™€ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๋“ค](#containers-with-multiple-processes-and-special-cases).
* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
!!! ๊ฒฝ๊ณ 
์—ฌ๋Ÿฌ๋ถ„์ด ์ด ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ๋˜๋Š” ๋‹ค๋ฅธ ์œ ์‚ฌํ•œ ์ด๋ฏธ์ง€๋ฅผ ํ•„์š”๋กœ ํ•˜์ง€ **์•Š์„** ๋†’์€ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฉฐ, [์œ„์—์„œ ์„ค๋ช…๋œ ๊ฒƒ์ฒ˜๋Ÿผ: FastAPI๋ฅผ ์œ„ํ•œ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œํ•˜๊ธฐ](#build-a-docker-image-for-fastapi) ์ฒ˜์Œ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฏธ์ง€๋Š” ๊ฐ€๋Šฅํ•œ CPU ์ฝ”์–ด์— ๊ธฐ๋ฐ˜ํ•œ **๋ช‡๊ฐœ์˜ ์›Œ์ปค ํ”„๋กœ์„ธ์Šค**๋ฅผ ์„ค์ •ํ•˜๋Š” **์ž๋™-ํŠœ๋‹** ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฏธ์ง€๋Š” **๋ฏผ๊ฐํ•œ ๋””ํดํŠธ** ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์—ฌ์ „ํžˆ **ํ™˜๊ฒฝ ๋ณ€์ˆ˜** ๋˜๋Š” ์„ค์ • ํŒŒ์ผ์„ ํ†ตํ•ด ์„ค์ •๊ฐ’์„ ์ˆ˜์ •ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#pre_start_path" class="external-link" target="_blank">**์‹œ์ž‘ํ•˜๊ธฐ ์ „ ์‚ฌ์ „ ๋‹จ๊ณ„**</a>๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
!!! ํŒ
๋ชจ๋“  ์„ค์ •๊ณผ ์˜ต์…˜์„ ๋ณด๋ ค๋ฉด, ๋„์ปค ์ด๋ฏธ์ง€ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
### ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€์— ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜
์ด ์ด๋ฏธ์ง€์— ์žˆ๋Š” **ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜**๋Š” ๊ฐ€์šฉํ•œ CPU **์ฝ”์–ด๋“ค**๋กœ ๋ถ€ํ„ฐ **์ž๋™์œผ๋กœ ๊ณ„์‚ฐ**๋ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ์ด๋ฏธ์ง€๊ฐ€ CPU๋กœ๋ถ€ํ„ฐ **์ตœ๋Œ€ํ•œ์˜ ์„ฑ๋Šฅ**์„ **์ฅ์–ด์งœ๋‚ธ๋‹ค**๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์—ฌ๋Ÿฌ๋ถ„์€ ์ด ์„ค์ • ๊ฐ’์„ **ํ™˜๊ฒฝ ๋ณ€์ˆ˜**๋‚˜ ๊ธฐํƒ€ ๋ฐฉ๋ฒ•๋“ค๋กœ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ํ”„๋กœ์„ธ์Šค์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” CPU์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋˜ํ•œ **์†Œ์š”๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ์˜ ํฌ๊ธฐ** ๋˜ํ•œ ์ด์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์š”๊ตฌํ•˜๊ณ  (์˜ˆ๋ฅผ ๋“ค์–ด ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์ฒ˜๋Ÿผ), ์—ฌ๋Ÿฌ๋ถ„์˜ ์„œ๋ฒ„๊ฐ€ CPU ์ฝ”์–ด ์ˆ˜๋Š” ๋งŽ์ง€๋งŒ **์ ์€ ๋ฉ”๋ชจ๋ฆฌ**๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ ์ปจํ…Œ์ด๋„ˆ๋Š” ๊ฐ€์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ณด๋‹ค ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฒฐ๊ตญ ํผํฌ๋จผ์Šค๋ฅผ ํฌ๊ฒŒ ๋–จ์–ด๋œจ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์‹ฌ์ง€์–ด ๊ณ ์žฅ์ด ๋‚  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). ๐Ÿšจ
### `Dockerfile` ์ƒ์„ฑํ•˜๊ธฐ
์ด ์ด๋ฏธ์ง€์— ๊ธฐ๋ฐ˜ํ•ด `Dockerfile`์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app
```
### ๋” ํฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด [๋‹ค์ค‘ ํŒŒ์ผ์„ ๊ฐ€์ง€๋Š” ๋” ํฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜](../tutorial/bigger-applications.md){.internal-link target=_blank}์„ ์ƒ์„ฑํ•˜๋Š” ์„น์…˜์„ ๋”ฐ๋ž๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์˜ `Dockerfile`์€ ๋Œ€์‹  ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
```Dockerfile hl_lines="7"
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app/app
```
### ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ
์—ฌ๋Ÿฌ๋ถ„๋“ค์ด **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**(๋˜๋Š” ์œ ์‚ฌํ•œ ๋‹ค๋ฅธ ๋„๊ตฌ) ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ์—์„œ ๋‹ค์ค‘ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ด์šฉํ•ด ์ด๋ฏธ **์‚ฌ๋ณธ**์„ ์„ค์ •ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๊ณต์‹ ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€(๋˜๋Š” ์œ ์‚ฌํ•œ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ **์•Š๋Š”** ๊ฒƒ ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์— ์—ฌ๋Ÿฌ๋ถ„์€ ๋‹ค์Œ์— ์„ค๋ช…๋œ ๊ฒƒ ์ฒ˜๋Ÿผ **์ฒ˜์Œ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๊ฒƒ**์ด ๋” ๋‚ซ์Šต๋‹ˆ๋‹ค: [FastAPI๋ฅผ ์œ„ํ•œ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œํ•˜๊ธฐ](#build-a-docker-image-for-fastapi).
์ด ์ด๋ฏธ์ง€๋Š” ์œ„์˜ [๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๋Š” ์ปจํ…Œ์ด๋„ˆ์™€ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๋“ค](#containers-with-multiple-processes-and-special-cases)์—์„œ ์„ค๋ช…๋œ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด์„œ๋งŒ ์ฃผ๋กœ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด **์ถฉ๋ถ„ํžˆ ๋‹จ์ˆœ**ํ•ด์„œ CPU์— ๊ธฐ๋ฐ˜ํ•œ ๋””ํดํŠธ ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ž˜ ์ž‘๋™ํ•œ๋‹ค๋ฉด, ํด๋Ÿฌ์Šคํ„ฐ ๋ ˆ๋ฒจ์—์„œ ์ˆ˜๋™์œผ๋กœ ์‚ฌ๋ณธ์„ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์„ ๊ฒƒ์ด๊ณ , ์—ฌ๋Ÿฌ๋ถ„์˜ ์•ฑ์—์„œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜์ง€๋„ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜๋Š” ๋งŒ์•ฝ์— ์—ฌ๋Ÿฌ๋ถ„์ด **๋„์ปค ์ปดํฌ์ฆˆ**๋กœ ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜, ๋‹จ์ผ ์„œ๋ฒ„์—์„œ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
## ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ๋ฐฐํฌํ•˜๊ธฐ
์ปจํ…Œ์ด๋„ˆ (๋„์ปค) ์ด๋ฏธ์ง€๋ฅผ ์™„์„ฑํ•œ ๋’ค์— ์ด๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด:
* ๋‹จ์ผ ์„œ๋ฒ„์—์„œ **๋„์ปค ์ปดํฌ์ฆˆ**๋กœ ๋ฐฐํฌํ•˜๊ธฐ
* **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค** ํด๋Ÿฌ์Šคํ„ฐ๋กœ ๋ฐฐํฌํ•˜๊ธฐ
* ๋„์ปค ์Šค์™ ๋ชจ๋“œ ํด๋Ÿฌ์Šคํ„ฐ๋กœ ๋ฐฐํฌํ•˜๊ธฐ
* ๋…ธ๋งˆ๋“œ ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ๋กœ ๋ฐฐํฌํ•˜๊ธฐ
* ์—ฌ๋Ÿฌ๋ถ„์˜ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋ฐฐํฌํ•ด์ฃผ๋Š” ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค๋กœ ๋ฐฐํฌํ•˜๊ธฐ
## Poetry์˜ ๋„์ปค ์ด๋ฏธ์ง€
๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ํ”„๋กœ์ ํŠธ ์˜์กด์„ฑ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด <a href="https://python-poetry.org/" class="external-link" target="_blank">Poetry</a>๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๋„์ปค์˜ ๋ฉ€ํ‹ฐ-์Šคํ…Œ์ด์ง€ ๋นŒ๋”ฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
```{ .dockerfile .annotate }
# (1)
FROM python:3.9 as requirements-stage
# (2)
WORKDIR /tmp
# (3)
RUN pip install poetry
# (4)
COPY ./pyproject.toml ./poetry.lock* /tmp/
# (5)
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
# (6)
FROM python:3.9
# (7)
WORKDIR /code
# (8)
COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt
# (9)
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
# (10)
COPY ./app /code/app
# (11)
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
```
1. ์ฒซ ์Šคํ…Œ์ด์ง€๋กœ, `requirements-stage`๋ผ๊ณ  ์ด๋ฆ„ ๋ถ™์˜€์Šต๋‹ˆ๋‹ค.
2. `/tmp`๋ฅผ ํ˜„์žฌ์˜ ์›Œํ‚น ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
์ด ์œ„์น˜์— ์šฐ๋ฆฌ๋Š” `requirements.txt` ํŒŒ์ผ์„ ์ƒ์„ฑํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
3. ์ด ๋„์ปค ์Šคํ…Œ์ด์ง€์—์„œ Poetry๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
4. ํŒŒ์ผ `pyproject.toml`์™€ `poetry.lock`๋ฅผ `/tmp` ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
`./poetry.lock*` (`*`๋กœ ๋๋‚˜๋Š”) ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํŒŒ์ผ์ด ์•„์ง ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋”๋ผ๋„ ๊ณ ์žฅ๋‚˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
5. `requirements.txt` ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
6. ์ด๊ฒƒ์ด ๋งˆ์ง€๋ง‰ ์Šคํ…Œ์ด์ง€๋กœ, ์—ฌ๊ธฐ์— ์œ„์น˜ํ•œ ๋ชจ๋“  ๊ฒƒ์ด ๋งˆ์ง€๋ง‰ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์— ํฌํ•จ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
7. ํ˜„์žฌ์˜ ์›Œํ‚น ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ `/code`๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
8. ํŒŒ์ผ `requirements.txt`๋ฅผ `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
์ด ํŒŒ์ผ์€ ์˜ค์ง ์ด์ „์˜ ๋„์ปค ์Šคํ…Œ์ด์ง€์—๋งŒ ์กด์žฌํ•˜๋ฉฐ, ๋•Œ๋ฌธ์— ๋ณต์‚ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ `--from-requirements-stage` ์˜ต์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
9. ์ƒ์„ฑ๋œ `requirements.txt` ํŒŒ์ผ์— ํŒจํ‚ค์ง€ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
10. `app` ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ `/code` ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
11. `uvicorn` ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ, `app.main`์—์„œ ๋ถˆ๋Ÿฌ์˜จ `app` ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
!!! ํŒ
๋ฒ„๋ธ” ์ˆซ์ž๋ฅผ ํด๋ฆญํ•ด ๊ฐ ์ค„์ด ํ•˜๋Š” ์ผ์„ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
**๋„์ปค ์Šคํ…Œ์ด์ง€**๋ž€ `Dockefile`์˜ ์ผ๋ถ€๋กœ์„œ ๋‚˜์ค‘์— ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ์ผ๋“ค์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ **์ผ์‹œ์ ์ธ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€**๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
์ฒซ ์Šคํ…Œ์ด์ง€๋Š” ์˜ค์ง **Poetry๋ฅผ ์„ค์น˜**ํ•˜๊ณ  Poetry์˜ `pyproject.toml` ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ํ”„๋กœ์ ํŠธ ์˜์กด์„ฑ์„ ์œ„ํ•œ **`requirements.txt`๋ฅผ ์ƒ์„ฑ**ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
์ด `requirements.txt` ํŒŒ์ผ์€ **๋‹ค์Œ ์Šคํ…Œ์ด์ง€**์—์„œ `pip`๋กœ ์‚ฌ์šฉ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์—๋Š” **์˜ค์ง ๋งˆ์ง€๋ง‰ ์Šคํ…Œ์ด์ง€๋งŒ** ๋ณด์กด๋ฉ๋‹ˆ๋‹ค. ์ด์ „ ์Šคํ…Œ์ด์ง€(๋“ค)์€ ๋ฒ„๋ ค์ง‘๋‹ˆ๋‹ค.
Poetry๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ **๋„์ปค ๋ฉ€ํ‹ฐ-์Šคํ…Œ์ด์ง€ ๋นŒ๋“œ**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€๋ฐ, ์—ฌ๋Ÿฌ๋ถ„๋“ค์˜ ํ”„๋กœ์ ํŠธ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์ง€๋ง‰ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์— **์˜ค์ง** `requirements.txt` ํŒŒ์ผ๋งŒ ํ•„์š”ํ•˜์ง€, Poetry์™€ ๊ทธ ์˜์กด์„ฑ์€ ์žˆ์„ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
์ด ๋‹ค์Œ (๋˜ํ•œ ๋งˆ์ง€๋ง‰) ์Šคํ…Œ์ด์ง€์—์„œ ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์ด์ „์— ์„ค๋ช…๋œ ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
### TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ์˜ ๋ฐฐํ›„ - Poetry
์ด์ „์— ์–ธ๊ธ‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด, ๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ Nginx ๋˜๋Š” Traefik๊ณผ ๊ฐ™์€ TLS ์ข…๋ฃŒ ํ”„๋ก์‹œ (๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ) ๋’ค์—์„œ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์ปค๋งจ๋“œ์— `--proxy-headers` ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:
```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
```
## ์š”์•ฝ
์ปจํ…Œ์ด๋„ˆ ์‹œ์Šคํ…œ(์˜ˆ๋ฅผ ๋“ค์–ด **๋„์ปค**๋‚˜ **์ฟ ๋ฒ„๋„คํ‹ฐ์Šค**)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  **๋ฐฐํฌ ๊ฐœ๋…**์„ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์€ ๊ฝค ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค:
* HTTPS
* ๊ตฌ๋™ํ•˜๊ธฐ
* ์žฌ์‹œ์ž‘
* ๋ณต์ œ (์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค ๊ฐœ์ˆ˜)
* ๋ฉ”๋ชจ๋ฆฌ
* ์‹œ์ž‘ํ•˜๊ธฐ ์ „ ๋‹จ๊ณ„๋“ค
๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์€ ์–ด๋–ค ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ณต์‹ ํŒŒ์ด์ฌ ๋„์ปค ์ด๋ฏธ์ง€์— ๊ธฐ๋ฐ˜ํ•ด **์ฒ˜์Œ๋ถ€ํ„ฐ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œ**ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
`Dockerfile`์— ์žˆ๋Š” ์ง€์‹œ ์‚ฌํ•ญ์„ **์ˆœ์„œ๋Œ€๋กœ** ๋‹ค๋ฃจ๊ณ  **๋„์ปค ์บ์‹œ**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์€ **๋นŒ๋“œ ์‹œ๊ฐ„์„ ์ตœ์†Œํ™”**ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋กœ์จ ์ƒ์‚ฐ์„ฑ์„ ์ตœ๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๊ทธ๋ฆฌ๊ณ  ์ง€๋ฃจํ•จ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์ฃ ) ๐Ÿ˜Ž
ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์—๋Š”, FastAPI๋ฅผ ์œ„ํ•œ ๊ณต์‹ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค“
Loadingโ€ฆ
Cancel
Save