문제 정의
Docker Compose에서 컨테이너가 Up이라고 해서 서비스가 준비된 것은 아닙니다. 프로세스는 떠 있지만 데이터베이스 연결이 끝나지 않았거나, 마이그레이션이 실패했거나, 프론트엔드가 잘못된 API URL로 빌드된 상태일 수 있습니다.
이 차이를 구분하지 못하면 배포 스크립트는 성공했다고 말하지만 사용자는 502나 빈 화면을 보게 됩니다.
상황과 배경
Compose 기반 배포는 단순하고 재현성이 좋습니다. 하지만 서비스가 여러 개인 경우 시작 순서와 준비 상태가 어긋나기 쉽습니다. 특히 백엔드가 DB에 연결되기 전 프록시가 트래픽을 보내면 짧은 장애가 반복됩니다.
빌드와 재시작 범위가 헷갈린다면 먼저 Docker build와 restart의 차이를 정리해 두는 것이 좋습니다. healthcheck는 그 다음 단계의 운영 기준입니다.
healthcheck와 readiness를 나누는 이유
- healthcheck: 프로세스가 살아 있고 기본 엔드포인트가 응답하는지 확인합니다.
- readiness: DB, 캐시, 마이그레이션, 외부 의존성처럼 실제 요청 처리에 필요한 조건을 확인합니다.
- smoke test: 사용자가 여는 공개 URL이 프록시와 브라우저 기준으로 정상인지 확인합니다.
실제 적용 방법
백엔드에는 가벼운 /health와 더 엄격한 /health/ready를 분리합니다. /health는 프로세스 생존 확인에 쓰고, /health/ready는 DB 연결과 핵심 의존성을 확인합니다. 프론트엔드는 단순 HTML 응답뿐 아니라 초기 HTML에 주요 텍스트가 들어 있는지도 확인해야 합니다.
배포 후 공개 경로 점검은 smoke test 체크리스트와 함께 묶으면 좋습니다. 컨테이너 내부 기준과 사용자 URL 기준을 모두 통과해야 실제 배포 완료입니다.
운영 체크리스트
- 컨테이너 healthcheck는 너무 무겁지 않게 유지합니다.
- readiness는 DB 연결 실패를 명확히 실패로 반환합니다.
- 배포 스크립트는 readiness 통과 전 성공 메시지를 내지 않습니다.
- 프록시 502는 backend readiness, upstream 주소, 포트 매핑 순서로 확인합니다.
- 실패 로그에는 어떤 체크가 실패했는지 이름을 남깁니다.
결론
healthcheck는 컨테이너 생존 신호이고 readiness는 사용자 요청 준비 신호입니다. 이 둘을 분리하면 배포 실패를 더 빨리 드러낼 수 있고, 운영 런북도 훨씬 실행 가능한 문서가 됩니다.