📚 FDE · 세션 · 데이터 · 서버 · 배포 (수정중) · L04

배포가 바꾸는 것 (수정중)

작성일자 2026-06-28  ·  수정일자 2026-08-06  ·  강의차수 L04  ·  예상소요 30분

목표 이 강의가 끝나면 학습자가 "배포(release)"가 서버에서 구체적으로 무엇을(코드·실행 프로세스·DB 구조·정적 파일·라이브러리) 어떻게 바꾸는지, 그리고 왜 재시작이 꼭 필요하고 왜 마이그레이션이 조심스러운지를 설명할 수 있다.

서버 한 대 안 에서 서버 안 부품(Apache·gunicorn·Django·PostgreSQL)을 봤습니다. 이 강의는 그 부품들 위에서 "배포한다"는 한마디가 실제로 일으키는 변화를 하나씩 엽니다. 배포 절차를 외우기 전에 "그 절차가 왜 그 순서인지"를 이해하는 시간입니다.


1. 배포가 맞추는 다섯 가지

흔히 "배포했어 / prod 에 올렸어"라고 한 마디로 말하지만, 서버에서 실제로 일어나는 건 다섯 가지를 새 버전에 맞추는 작업입니다.

# 무엇을 어떻게 (명령) 서버 안의 어느 부품
① 코드(디스크) git checkout <태그> / git pull Django 코드
② 실행 프로세스 systemctl restart <proj>-prod.service gunicorn
③ DB 구조 migrate PostgreSQL
④ 정적 파일 collectstatic Apache 가 주는 /static/
⑤ 라이브러리 pip install -r requirements.txt (필요할 때만)

이 다섯이 서로 어긋나면 사고가 납니다. 그래서 배포 절차는 이 다섯을 올바른 순서로 맞추는 것입니다. 먼저 큰 그림입니다.

무엇이 바뀌나명령효과 (배포 전 → 후)① 코드(디스크)git checkout v1.4v1.3 → v1.4② gunicorn(메모리)systemctl restartv1.3 → v1.4안 하면 옛 코드 그대로!③ DB 구조(스키마)migrate구(舊) → 신(新)되돌리기 어려움·가장 조심④ 정적 파일collectstatic옛 CSS → 새 CSS⑤ 라이브러리pip install (필요시)옛 → 새 버전데이터(사용자·회의록 등)는 그대로 유지

그림: 배포 = ① 코드(git checkout) ② gunicorn 재시작 ③ DB migrate ④ collectstatic ⑤ pip 를 새 버전에 맞추는 일. 재시작 안 하면 옛 코드 유지, migrate 는 되돌리기 어려움. 데이터·도메인·세션은 그대로 유지.


2. ① 코드 교체

가장 먼저, 서버 디스크(/home/ubuntu/<proj>/src)의 코드 파일을 새 버전으로 바꿉니다. git checkout <태그> 나 git pull 이 하는 일이 이것입니다. GitHub 에 올라간 새 코드를 서버로 당겨와 파일을 교체합니다.

하지만 여기서 가장 흔한 오해가 나옵니다. 👇


3. ② 프로세스 재시작

핵심: gunicorn 은 시작할 때 코드를 메모리에 한 번 읽어 들고, 그 뒤로는 메모리에 든 코드로 계속 일합니다. 그래서 디스크 파일만 새로 바꿔도, 돌고 있는 gunicorn 은 여전히 옛 코드를 실행합니다.

새 코드를 실제로 반영하려면 gunicorn 을 재시작해야 합니다.

sudo systemctl restart popax-prod.service

이 순간 gunicorn 워커들이 새로 떠서 디스크의 새 코드를 다시 읽어 들입니다. 그제서야 사용자가 새 버전을 보게 됩니다.

  • 그래서 "분명히 배포(코드 교체)했는데 안 바뀌었어요"의 90%는 재시작을 안 했거나, 재시작이 실패한 경우입니다.
  • 백그라운드 작업(celery·huey, 예: popax-prod-huey.service)이 있으면 그것도 재시작해야 그쪽 코드가 새로 반영됩니다.
  • 정적 파일(④)만 바꾼 배포라면 gunicorn 재시작이 굳이 필요 없을 수도 있습니다. 무엇이 바뀌었느냐에 따라 무엇을 재시작할지 정해집니다.

4. ③ DB 구조 정렬 (migrate)

코드(Django 모델)가 바뀌면서 데이터베이스의 구조(표·컬럼) 자체를 바꿔야 할 때가 있습니다. 예를 들어 "회의록에 '작성일' 항목을 새로 추가"하면 DB 표에 새 컬럼이 필요합니다. 이 구조 변경을 적용하는 게 마이그레이션입니다.

<PROJ>_PRODUCTION=True python manage.py migrate --noinput

왜 가장 조심스러운가:

  • 실서버 데이터 위에서 구조를 바꿉니다. popax_prod 에는 진짜 사용자 데이터가 들어 있습니다. 구조를 잘못 바꾸면 데이터가 깨지거나 손실될 수 있습니다.
  • 되돌리기가 어렵습니다. 코드는 옛 태그로 checkout 하면 곧장 롤백되지만, 마이그레이션은 한 번 적용되면 자동으로 깔끔히 되돌려지지 않습니다(특히 컬럼 삭제·데이터 변환).
  • 그래서 마이그레이션은 절대 자동·무인으로 돌리지 않습니다. 배포 절차에서 migrate 는 사람이 목록을 확인하고 백업·영향을 점검한 뒤 직접 실행하는 단계로 둡니다(휴먼 게이트).

기억할 것: 코드 교체는 쉽게 되돌릴 수 있지만, DB 마이그레이션은 그렇지 않습니다. 그래서 배포에서 가장 신중해야 하는 단계입니다.


5. ④ 정적 파일 · ⑤ 라이브러리

④ collectstatic: CSS·JS·이미지를 바꿨다면, 서버 한 대 안 에서 본 Apache 가 주는 폴더(popax_static_cdn/static/)에 새 파일을 모아 둬야 합니다.

<PROJ>_PRODUCTION=True python manage.py collectstatic --noinput

이걸 빠뜨리면 코드는 새 버전인데 화면 스타일(CSS)만 옛날 것으로 보이는 어긋남이 생깁니다.

⑤ pip install: requirements.txt 가 바뀌었을 때(새 라이브러리 추가 등)만 합니다. 안 바뀌었으면 건너뜁니다.

pip install -r requirements.txt     # requirements 바뀐 경우에만

6. 안 바뀌는 것

무엇이 안 바뀌는지를 아는 것도 똑같이 중요합니다.

  • 데이터(행): 사용자·회의록 같은 내용물은 그대로입니다. 배포는 "코드·구조"를 바꾸지, "쌓인 데이터"를 지우지 않습니다(서버 한 대 안 의 "코드와 데이터 분리"). 단, ③ 마이그레이션이 데이터를 변환하도록 짜였다면 그건 의도된 변경입니다.
  • 도메인·IP: meetings.popupstudio.ai 와 52.79.132.206 은 배포와 무관하게 그대로입니다(요청이 서버에 닿는 경로).
  • 로그인 세션: 대개 유지됩니다(세션은 DB·쿠키에 있고 코드 교체와 분리).

그래서 보통 사용자는 잠깐의 재시작(수 초) 외에는 배포를 눈치채지 못합니다.


마무리

  • 핵심 정리: "배포"는 ① 코드(git checkout) ② 프로세스 재시작(systemctl restart, 안 하면 gunicorn 이 옛 코드 유지!) ③ DB 구조(migrate, 가장 조심, 되돌리기 어려움) ④ 정적 파일(collectstatic) ⑤ 라이브러리(pip, 필요시)를 새 버전에 맞추는 일입니다. 데이터·도메인·세션은 그대로 남습니다. 다섯이 어긋나면 사고가 나므로 순서가 중요합니다.
  • 주의 사항: ① 재시작 빠뜨림: "배포했는데 안 바뀜"의 최대 원인으로, 코드 파일만 바꾸고 gunicorn 을 안 재운 경우입니다. ② collectstatic 빠뜨림: 코드는 새 버전인데 CSS 만 옛날입니다. ③ migrate 를 가볍게 봄: 실데이터 위 구조 변경이라 백업·영향 확인 없이 돌리면 위험합니다. ④ 마이그레이션이 필요한데 코드만 배포: 새 코드가 없는 컬럼을 찾아 에러가 납니다(코드와 DB 구조는 짝으로 맞춰야 합니다).
  • 다음 시간: 여기까지 시스템이 어떻게 구성되고 도는지 봤습니다. 이제 이 위에서 Claude Code 로 실제로 개발하는 법(스킬·에이전트·훅)을 살펴봅니다.
  • 자습 권장: 최근 배포 하나를 떠올려(또는 git log 로 골라) "이 변경은 ①~⑤ 중 무엇을 건드렸을까?"를 분류해 봅니다. 모델을 바꿨으면 ③ migrate 필요, CSS 만 고쳤으면 ④ 만, 이런 식입니다. 그리고 prod 박스에서 journalctl -u <proj>-prod.service -n 30 으로 마지막 재시작(②)이 언제였는지 확인해 봅니다.
이 강의를 학습하셨나요?