Go 언어에서 Graceful Shutdown을 구현하는 실용적 패턴
분야
프로그래밍/소프트웨어 개발
대상자
Go 언어를 사용하는 개발자, HTTP 서버 및 컨테이너 환경(예: Kubernetes)에서 안정적인 종료 로직을 구현해야 하는 개발자, 리소스 관리 및 시스템 안정성에 관심 있는 개발자
핵심 요약
- Go에서 우아한 종료는 신호 처리, 컨텍스트 기반 제어, 리소스 정리로 구성* **
os/signal
패키지로SIGINT
,SIGTERM
신호 처리,signal.NotifyContext
로 컨텍스트 기반 종료 제어*- HTTP 서버 종료 시
Server.Shutdown()
전readiness probe
실패로 트래픽 차단, 30초 대기 후 종료* defer
로 리소스 정리,context.Context
를 통해 모든 핸들러에 종료 신호 전파*
섹션별 세부 요약
- 신호 처리 및 컨텍스트 기반 종료 제어
os/signal
패키지로SIGINT
,SIGTERM
신호 직접 처리 가능signal.NotifyContext
를 사용해 컨텍스트 기반 종료 제어 구현 (Go 1.16 이상)- 버퍼링된 채널(용량 1) 사용으로 신호 유실 방지
context.WithTimeout
으로 shutdown context에 타임아웃 설정log.Fatal
대신panic
사용 시defer
내용 실행 가능
- HTTP 서버 및 컨테이너 환경 종료 처리
Server.Shutdown()
호출 전readiness probe
실패로 트래픽 차단- Kubernetes 환경에서
terminationGracePeriodSeconds
(기본 30초) 고려, 25초 이내 종료 readiness
핸들러에서 전역 변수로 종료 상태 판단, HTTP 503 반환/healthz
엔드포인트로 상태 확인, 5초 대기 후 shutdown 수행server.Shutdown
실패 시 강제 종료 fallback 처리
- 리소스 정리 및 시스템 안정성
- 데이터베이스, 메시지 브로커, 캐시 등 외부 리소스 의도적 정리 필요
defer
로 초기화 역순으로 종료 루틴 실행, 의존성 관리 용이- 메모리, 파일 디스크립터 등 OS 자동 정리 리소스 외 명시적 정리 필요 (예: 데이터 flush, 트랜잭션 rollback)
- 로드밸런서 타겟 IP 업데이트 지연 시 트래픽 드레인 확인 필수
- 실무 팁 및 주의 사항
log.Fatal
사용 시defer
실행 중단,panic
으로 대체 권장- Prometheus
/metrics
스크랩 시 마지막 메트릭 누락 가능성 - systemd, nginx는 graceful shutdown 지원, Kubernetes/Docker는 지원 없음
- 동일한 엔드포인트를 liveness/readiness로 사용하는 경우 주의
preStop
훅으로 15초 대기 시간 추가해 HTTP 503 비율 개선
결론
- Go 애플리케이션의 우아한 종료는 신호 처리, 컨텍스트 기반 컨트롤, 리소스 정리로 구성* **
os/signal
,signal.NotifyContext
,context.Context
활용해 종료 신호 전파*- HTTP 서버 종료 시
readiness probe
로 트래픽 차단 후Server.Shutdown()
호출* defer
로 리소스 정리,context.WithTimeout
로 타임아웃 설정*- Kubernetes 환경에서는 25초 이내 종료,
preStop
훅으로 HTTP 503 개선* log.Fatal
대신panic
사용, 메트릭/로그 누락 방지*- 리소스 명시적 정리와 시스템 안정성 고려 필수*