FastAPI & Docker ๋ฌด์ค๋จ ๋ฐฐํฌ(Zero-Downtime) ํ๊ฒฝ ๊ตฌ์ถ๊ธฐ: Nginx ๋ฆฌ๋ฒ์ค ํ๋ก์๋ก 502 Bad Gateway ์๋ฒฝ ํด๊ฒฐ๊ธฐ
์น์ฌ์ดํธ๋ฅผ ์ด์ํ๋ค ๋ณด๋ฉด ํ๋ฃจ์๋ ๋ช ๋ฒ์ฉ ์ฝ๋๋ฅผ ์์ ํด์ผ ํ๋ ์ผ์ด ์๊น๋๋ค. ์์ํ ์คํ ์์ ๋ถํฐ ์๋ก์ด ๋ฉ๋ด ์ถ๊ฐ, ๊ฒ์์์ง ์ต์ ํ(SEO)๋ฅผ ์ํ ๋ฉํ ํ๊ทธ ํ๋๊น์ง ๋ค์ํฉ๋๋ค. ๊ธฐ์กด์๋ ์ฝ๋๋ฅผ ์์ ํ๊ณ ๋๋ฉด ๋ฐ๋์ docker-compose restart ๋ช
๋ น์ด๋ฅผ ์ณ์ ์๋ฒ๋ฅผ ๊ป๋ค ์ผ์ผ ํ์ต๋๋ค.
๋ฌธ์ ๋ ์ด '๊ป๋ค ์ผ๋' 10์ด ๋จ์งํ ์๊ฐ์
๋๋ค. ์ด ์ฐฐ๋์ ์๊ฐ์ ๊ฒ์๊ธ์ ์ฝ๊ณ ์๊ฑฐ๋ ๋๊ธ์ ์์ฑํ๋ ์ ์ ๋ค์ ๋์ฐํ 502 Bad Gateway ํ์ ์๋ฌ ํ๋ฉด์ ๋ง์ฃผํ๊ฒ ๋ฉ๋๋ค. ๊ตฌ๊ธ ์ ๋์ผ์ค ์ฌ์ฌ ๋ก๋ด(Mediapartners-Google) ์ญ์ ํํ ์ด ํ์ด๋ฐ์ ์ ์ํ๊ฒ ๋๋ฉด "์ฌ์ดํธ๊ฐ ๋ค์ด๋์๊ฑฐ๋ ์ฌ์ฉํ ์ ์์"์ด๋ผ๋ ์น๋ช
์ ์ธ ํ์ ์ ๋ด๋ฆฌ๊ณ ๋ง๋๋ค.
์ ์ ๋ค์ ๋ถํธ์ ๋ง๊ธฐ ์ํด ํญ์ ์๋ฒฝ 3์๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ์๋ฒ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๊ณ ๋จํ ์ผ์์ ๋ฒ์ด๋๊ณ ์, Nginx์ Docker๋ฅผ ํ์ฉํ ์๋ฒฝํ ๋ฌด์ค๋จ ๋ฐฐํฌ(Zero-Downtime Deployment) ์์คํ ์ ๊ตฌ์ถํ ๊ณผ์ ์ ๊ณต์ ํฉ๋๋ค.
1. ์ 502 Bad Gateway๊ฐ ๋ฐ์ํ ๊น? (Downtime์ ์ดํด)
Nginx๋ ์ฌ์ฉ์์ ์์ฒญ์ ๊ฐ์ฅ ๋จผ์ ๋ฐ์ ๋ท๋จ์ ํ์ด์ฌ(FastAPI) ์๋ฒ๋ก ์ ๋ฌํด ์ฃผ๋ 'ํ๊ด๋ฌธ(Reverse Proxy)' ์ญํ ์ ํฉ๋๋ค. ๊ธฐ์กด์ ๋ฐฐํฌ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์งํ๋์์ต๋๋ค.
๊ฐ๋ฐ์๊ฐ ์ ๋ฐ์ดํธ ๋ช ๋ น์ ๋ด๋ฆผ.
๊ธฐ์กด FastAPI ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ๋จ. (์ด๋๋ถํฐ ํ๊ด๋ฌธ์ ๋ค์ด์จ ์ ์ ๋ค์ ๊ธธ์ ์๊ณ 502 ์๋ฌ๋ฅผ ๋ฐ์)
์๋ก์ด ์ฝ๋๊ฐ ์ ์ฉ๋ FastAPI ์ปจํ ์ด๋๊ฐ ์์ฑ๋จ.
Uvicorn ์๋ฒ๊ฐ ๊ฐ๋๋๊ณ DB์ ์ฐ๊ฒฐ๋ ๋๊น์ง ์ฝ 5์ด ๋๊ธฐ.
์๋ฒ ์ค๋น ์๋ฃ. ์ ์ ์๋น์ค ์ฌ๊ฐ.
2๋ฒ๊ณผ 5๋ฒ ์ฌ์ด์ ์๊ฐ์ด ๋ฐ๋ก '๋ค์ดํ์(Downtime)'์ ๋๋ค. ์ด๋ฅผ ์์ ๊ธฐ ์ํ ํต์ฌ ์์ด๋์ด๋ ์์ฃผ ๋จ์ํฉ๋๋ค. "์๋ก์ด ์๋ฒ(Green)๊ฐ ์์ ํ ์ผ์ ธ์ ํธ๋ํฝ์ ๋ฐ์ ์ค๋น๊ฐ ๋๋ ๊ฒ์ ํ์ธํ ๋ค์, ๊ธฐ์กด ์๋ฒ(Blue)๋ฅผ ๋๋ฉด ๋์ง ์์๊น?"
2. ํด๊ฒฐ์ฑ 1๋จ๊ณ: Nginx Upstream ๋ก๋ ๋ฐธ๋ฐ์ฑ
๋จผ์ Nginx๊ฐ ํ๋์ ๊ณ ์ ๋ ํฌํธ(์: 8000)๋ง ๋ฐ๋ผ๋ณด๋ ๊ฒ์, ๋ ๊ฐ์ ํฌํธ(์: 8001, 8002)๋ฅผ ์ ์ฐํ๊ฒ ๋ฐ๋ผ๋ณผ ์ ์๋๋ก ์ค์ ์ ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด nginx.conf ํ์ผ์ upstream ๋ธ๋ก์ ๊ตฌ์ฑํฉ๋๋ค.

์ด์ Nginx๋ 8001๋ฒ๊ณผ 8002๋ฒ ํฌํธ ์ค ์ด์์๋ ๊ณณ์ผ๋ก ํธ๋ํฝ์ ๋๋ํ๊ฒ ๋ถ๋ฐฐ(Load Balancing)ํ ์ ์๋ ๋ฅ๋ ฅ์ ๊ฐ์ถ๊ฒ ๋์์ต๋๋ค.
3. ํด๊ฒฐ์ฑ 2๋จ๊ณ: ๋์ ์ค์์นญ ๋ฐฐํฌ ์คํฌ๋ฆฝํธ(deploy.sh) ์์ฑ
ํ๋ก ํธ์๋ ์ต์ ํ(๋น ๋ฅธ ๋ก๋ฉ)์ ๊น๋ํ ๋์์ธ(Clean design)์ ์ ์งํ๋ ค๋ฉด ๋ฐฑ์๋์ ๊ต์ฒด ๊ณผ์ ์ด ๋ฌผ ํ๋ฅด๋ฏ ์์ฐ์ค๋ฌ์์ผ ํฉ๋๋ค. ์ ๋ Docker์ docker-compose up -d --scale ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๊ต๋ ๊ทผ๋ฌด๋ฅผ ์๋ ์๋ํ ์ ์คํฌ๋ฆฝํธ(deploy.sh)๋ฅผ ์์ฑํ์ต๋๋ค.
์คํฌ๋ฆฝํธ์ ํต์ฌ ๋ ผ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํ์ฌ 8001 ํฌํธ๊ฐ ์คํ ์ค์ธ์ง ํ์ธํฉ๋๋ค.
8001์ด ์คํ ์ค์ด๋ผ๋ฉด, ์ ์ฝ๋๋ฅผ ์ ํ ์ปจํ ์ด๋๋ฅผ 8002 ํฌํธ์ ๋์๋๋ค.
8002 ํฌํธ์
curl๋ช ๋ น์ด๋ฅผ ๋ ๋ ค200 OK์๋ต์ด ์ฌ ๋๊น์ง(Uvicorn์ด ์์ ํ ์ผ์ง ๋๊น์ง) 1์ด๋ง๋ค ๋ฐ๋ณตํด์ ํฌ์ค ์ฒดํฌ(Health Check)๋ฅผ ํฉ๋๋ค.์ ์๋ฒ๊ฐ ์๋ฒฝํ ์ผ์ง ๊ฒ์ด ํ์ธ๋๋ฉด, Nginx์๊ฒ
sudo systemctl reload nginx๋ช ๋ น์ ๋ด๋ ค ํ๊ด๋ฌธ์ ๋ฐฉํฅ์ 8002๋ฒ์ผ๋ก ๋๋ฆฝ๋๋ค.๋ง์ง๋ง์ผ๋ก ๊ตฌ๋ฒ์ ์ด ๋์ด๋ฒ๋ฆฐ 8001 ํฌํธ์ ์ปจํ ์ด๋๋ฅผ ์์ ํ๊ฒ ์ข ๋ฃ(
stop๋ฐrm)์ํต๋๋ค.
์ด ๋ฐฉ์์ ์ ์ฉํ ํ, ๋ฐฐํฌ ๋์ค ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ดํธ ์๋ก๊ณ ์นจ(F5)์ ์ฐํํด ๋ณด์์ต๋๋ค. ๊ฒฐ๊ณผ๋ ๊ฒฝ์ด๋ก์ ์ต๋๋ค. ํ๋ฉด์ด ๋ฉ์ถ๊ฑฐ๋ 502 ์๋ฌ๊ฐ ๋จ๋ ํ์์ด ๋จ ํ ๋ฒ๋ ๋ฐ์ํ์ง ์์์ผ๋ฉฐ, ์ ์ ์ ์ฅ์์๋ ์๋ฒ๊ฐ ์ธ์ ์ ๋ฐ์ดํธ๋์๋์ง์กฐ์ฐจ ๋์น์ฑ ์ ์์ ๋งํผ ๋ถ๋๋ฝ๊ฒ ์๋ก์ด ์ฝ๋๊ฐ ์ ์ฉ๋์์ต๋๋ค.
๋งบ์ผ๋ฉฐ: ์๋ฒ์ ์์ ์ฑ์ด ๊ณง '๊ฐ์น ์๋ ์น์ฌ์ดํธ'์ ์ฆ๋ช ์ด๋ค
๊ตฌ๊ธ ์ ๋์ผ์ค 2026 ์ฒดํฌ๋ฆฌ์คํธ๋ "๋น ๋ฅธ ๋ก๋ฉ(Fast loading)"๊ณผ "์ฌ์ดํธ์ ๊ธฐ์ ์ ์์ฑ๋(Apply only after site looks complete)"๋ฅผ ๋งค์ฐ ๊น๊นํ๊ฒ ์๊ตฌํฉ๋๋ค. ๋จ์ํ ๊ธ(Text)๋ง 1,500์๋ฅผ ์ฑ์ ๋ค๊ณ ํด์ ๊ณ ํ์ง ์ฌ์ดํธ๊ฐ ๋๋ ๊ฒ์ด ์๋๋๋ค.
์๋ฒ์ ๋ค์ดํ์์ ๊ฒ์์์ง ๋ด์๊ฒ๋ ์น๋ช ์ ์ธ ๊ฐ์ ์์์ ๋๋ค. ๋ด์ด ์ฌ์ดํธ์ ๋ด์ฉ์ ์์งํ๋ฌ ์๋๋ฐ 502 ์๋ฌ๋ฅผ ๋ฑ์ด๋ธ๋ค๋ฉด, ๊ตฌ๊ธ์ ํด๋น ์ฌ์ดํธ๋ฅผ '์ ๋ขฐํ ์ ์๋ ๋งค์ฒด'๋ก ๋ถ๋ฅํ์ฌ ์์ธ(Indexing)์ ๋๋ฝ์ํค๊ฑฐ๋ ์ ๋์ผ์ค ์ฌ์ฌ๋ฅผ ๊ฑฐ์ ํด ๋ฒ๋ฆฝ๋๋ค.
์ด๋ฒ ๋ฌด์ค๋จ ๋ฐฐํฌ(Zero-Downtime) ํ๊ฒฝ ๊ตฌ์ถ์ ํตํด, ์ ๋ ์๊ฐ๊ณผ ์ฅ์์ ๊ตฌ์ ๋ฐ์ง ์๊ณ ์ธ์ ๋ ๋ฒ๊ทธ๋ฅผ ์์ ํ๊ณ ์์ง์ ์ฝํ ์ธ ๋ฅผ ์ ๋ฐ์ดํธํ ์ ์๋ ์์ ๋ฅผ ์ป์์ต๋๋ค. 1์ธ ๊ฐ๋ฐ์๋ก์ ํธ๋ํฝ์ ๋ค๋ฃจ๋ ๊ธฐ์ ์ ํํํจ(E-E-A-T)์ ์ฆ๋ช ํด ๋์ผ๋, ๊ตฌ๊ธ ์ฌ์ฌ๊ด ์ญ์ ์ด ์น์ฌ์ดํธ์ ์ง๊ฐ๋ฅผ ์์๋ด ์ค ๊ฒ์ด๋ผ ํ์ ํฉ๋๋ค.
์์ฃผ ๋ฌป๋ ์ง๋ฌธ (FAQ)
Q1. Nginx reload์ Nginx restart์ ์ฐจ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
A. ์๋ฒฝํ ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ํด์๋ ๋ฐ๋์ reload๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. restart๋ Nginx ํ๋ก์ธ์ค ์์ฒด๋ฅผ ๊ฐ์ ๋ก ์ฃฝ์๋ค๊ฐ ๋ค์ ์ด๋ฆฌ๊ธฐ ๋๋ฌธ์ ๊ทธ ์๊ฐ ์ ์ ์ค์ด๋ ์ ์ ๋ค์ ์ฐ๊ฒฐ์ด ํญ ๋์ด์ง๋๋ค. ๋ฐ๋ฉด reload๋ ํ์ฌ ๋ค์ด์ ์๋ ์ ์ ๋ค์ ์ฐ๊ฒฐ์ ๋๊น์ง ์ ์งํ ์ฑ, ์๋ก์ด ์ฐ๊ฒฐ๋ถํฐ๋ง ์ ์ค์ ํ์ผ(๋ฐ๋ ํฌํธ)๋ก ๋ถ๋๋ฝ๊ฒ ๋๊ฒจ์ฃผ๋ฏ๋ก ์ ์ ๊ฒฝํ(UX) ํผ์์ด ์ ํ ๋ฐ์ํ์ง ์์ต๋๋ค.
Q2. Docker๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ผ๋ฐ์ ์ธ ์๋ฒ ํ๊ฒฝ์์๋ ๋ฌด์ค๋จ ๋ฐฐํฌ๊ฐ ๊ฐ๋ฅํ๊ฐ์?
A. ๋ค, ๊ฐ๋ฅํฉ๋๋ค. ํ์ด์ฌ ํ๋ก์ธ์ค ๊ด๋ฆฌ์์ธ PM2, Gunicorn, ๋๋ Supervisor ๋ฑ์ ํ์ฉํ๋ฉด ๋ฉ๋๋ค. Gunicorn์ ๊ฒฝ์ฐ kill -HUP <PID> ๋ช
๋ น์ด๋ฅผ ํตํด ๋ง์คํฐ ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ด์ง ์๊ณ ์์ปค(Worker) ํ๋ก์ธ์ค๋ง ์ ์ฝ๋๋ก ๊ต์ฒดํ๋ ๊ทธ๋ ์ด์คํ ๋ฆฌ๋ก๋(Graceful Reload) ๊ธฐ๋ฅ์ ์ง์ํ๋ฏ๋ก, Docker ์์ด๋ ๋ฌด์ค๋จ ๋ฐฐํฌ์ ๋์ผํ ํจ๊ณผ๋ฅผ ๋ผ ์ ์์ต๋๋ค.
Q3. ๋ฐฐํฌ ์ค ๋ฐ์ดํฐ๋ฒ ์ด์ค(DB) ํ ์ด๋ธ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ๋ง์ด๊ทธ๋ ์ด์ (Migration)์ด ์์ ๋๋ ์ด๋ป๊ฒ ํ๋์?
A. ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ๊ฐ์ฅ ๊น๋ค๋ก์ด ๋ถ๋ถ์ ๋๋ค. ๋ฌด์ค๋จ ๋ฐฐํฌ ์ํฉ์์๋ ๊ตฌ๋ฒ์ (Blue)๊ณผ ์ ๋ฒ์ (Green) ์๋ฒ๊ฐ ์์ฃผ ์งง์ ์๊ฐ ๋์ ๋์์ ์ด์์๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ์ ๋ฒ์ ์ด DB ์ปฌ๋ผ ์ด๋ฆ์ ๋ฐ๊ฟ๋ฒ๋ฆฌ๋ฉด, ์์ง ์ผ์ ธ ์๋ ๊ตฌ๋ฒ์ ์๋ฒ์์ ์๋ฌ๊ฐ ํญ์ฃผํ๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ DB ๋ง์ด๊ทธ๋ ์ด์ ์ ํญ์ 'ํ์ ํธํ์ฑ'์ ์งํค๋๋ก ๋ ๋จ๊ณ๋ก ์ชผ๊ฐ์ด ์์ ํด์ผ ํฉ๋๋ค. (1๋จ๊ณ: ์ ์ปฌ๋ผ ์ถ๊ฐ ํ ๋ฐฐํฌ -> 2๋จ๊ณ: ์ฑ ์ฝ๋์์ ๊ตฌ ์ปฌ๋ผ ์ฌ์ฉ์ ์์ ํ ์์ค ํ ๊ตฌ ์ปฌ๋ผ ์ญ์ ๋ฐฐํฌ).
๐ฌ ๋๊ธ 0๊ฐ