병원 사이트 블루-그린 배포 템플릿
헬스체크를 통과한 새 컨테이너로 Nginx를 넘기는 블루-그린 배포 템플릿을 만들고, 이후 서비스에 맞게 다시 구현한 작업
- Docker 컨테이너를 blue/green 두 벌로 띄우고, 헬스체크를 통과한 쪽으로 Nginx를 넘기는 배포 템플릿을 GitHub Actions로 작성했습니다.
- 동료가 이 템플릿을 병원 사이트 세 곳에 가져가 고쳐 쓰며 운영했고, 제가 퇴사한 뒤에도 이어서 운영하고 있습니다.
- 블로그 서비스에는 더 단순한 블루-그린을, 블로그 CMS에는 병원별 병렬 배포를 따로 만들었습니다.
문제
2025년 11월 전까지 병원 사이트 대부분은 PHP 파일을 서버에 손으로 올려 배포했고, git을 쓰지 않았다. 이후 Next.js·NestJS 사이트를 Docker 컨테이너로 운영하게 되면서, 배포 방식을 한 번 정해 여러 사이트에 쓸 수 있는 템플릿을 만들었다.
해결
배포 템플릿 (2025.11)
GitHub Actions 워크플로 세 개와 서버 스크립트를 한 저장소에 정리했다.
- CI — lint, 테스트, 빌드를 돌리고, main에 들어오면 서비스 이미지를 컨테이너 레지스트리에 올린 뒤 이미지 취약점 스캔을 한다.
- 블루-그린 배포 — 서버에 지금 어느 색이 운영 중인지 기록해 두고, 쉬고 있는 색에 새 이미지를 올린다. backend와 frontend 헬스 엔드포인트가 모두 응답해야 다음 단계로 넘어간다(최대 30회, 2초 간격).
- 트래픽 전환 — Nginx 설정을 백업한 뒤 upstream을 바꾸고, 설정 검사(
nginx -t)에 실패하면 백업으로 되돌린다. - 롤백 — 반대 색이 떠 있고 헬스체크를 통과할 때만 트래픽을 되돌린다. 실행할 때 사유 입력이 필수다.
- 운영 스크립트 — DB 백업·복원, 환경 변수 검사, 상태 확인, SSL 발급, Prometheus·Grafana·Loki 모니터링 구성.
템플릿 저장소 자체에서는 배포가 성공하지 못했다. 동료가 이를 병원 사이트에 가져가 설정을 맞추며 첫 배포를 성공시켰다.
병원 사이트 세 곳에 적용
동료가 템플릿을 병원 사이트 세 곳에 복사해 운영했다. CI가 끝나면 자동으로 배포하고, 슬롯을 자동으로 고르고, 배포를 한 번에 하나씩만 돌리는 개선은 동료가 했다. 제가 운영하면서 한 보안·장애 보완은 운영 보안·장애 대응에 따로 정리했다.
블로그 서비스에 새로 구현 (2026.04)
템플릿보다 단순한 구조로 블루-그린을 다시 만들었다.
- main에 머지하면 소스를 서버로 보내고, GitHub Secrets로 서버의 환경 변수 파일을 만든다.
- 기록된 현재 색을 읽고, 반대 색을 서버에서 빌드해 띄운다.
- API가 60초(5초 × 12회) 안에 응답하지 않으면 새 색을 내리고 멈춘다. 기존 색은 그대로 둔다.
- 응답하면 Nginx 설정을 새 색으로 다시 쓰고, 이전 색을 내리고, 현재 색을 기록한다.
Let's Encrypt 인증서 초기 발급 스크립트도 같이 작성했다. 도입 당일 배포 스크립트를 세 번 고쳐 배포를 성공시켰다.
블로그 CMS 배포 (2026.06)
블로그 CMS는 블루-그린이 아니라 병원별 병렬 배포로 만들었다. 병원 목록을 받아 병원마다 따로 배포하되, 같은 병원은 한 번에 하나씩만 돈다. 서버에서 Nginx 설정을 바꾸고 검사에 통과해야 reload하며, 배포 뒤 공개 API가 200을 돌려주는지 확인한다. 새 서버 초기 셋업, 여러 서버 일괄 셋업, DB·업로드 백업 스크립트도 작성했다. 이후 이 서비스의 블루-그린 전환은 동료가 했다.
결과
- 3곳
- 템플릿을 가져다 쓴 병원 사이트
- 3개
- 워크플로 (CI · 블루-그린 배포 · 롤백)
- 60초
- 블로그 서비스 새 컨테이너 헬스체크 상한
- 템플릿에서 출발한 배포 워크플로가 병원 사이트 세 곳에서 돌고 있다. Actions 기록상 성공 실행은 188회, 351회, 153회이며, 동료가 개선한 이후 버전의 기록이다.
- 블로그 서비스는 새 컨테이너가 응답하지 않으면 기존 운영을 건드리지 않고 멈춘다.
- 전환 순간의 다운타임은 측정하지 않았다. 그래서 "무중단"이라고 쓰지 않는다.
- Claude Code로 구현 속도를 높였고, 배포 순서와 실패 처리는 직접 정했다.
계약상 병원 실명, 도메인, 서버 정보는 공개하지 않는다.
이 프로젝트가 궁금하시면 편하게 물어보세요.
연락하기