Go 언어에서 Graceful Shutdown을 구현하는 실용적 패턴

5 hours ago 1

  • 우아한 종료(graceful shutdown) 는 애플리케이션이 종료 신호를 받은 뒤 새 요청을 막고, 현재 요청을 마치고, 리소스를 정리하는 절차로 구성
  • Go에서는 os/signal 패키지를 사용해 SIGINT, SIGTERM 같은 종료 신호를 직접 처리할 수 있으며, signal.NotifyContext를 이용해 context 기반 종료 제어도 가능함
  • HTTP 서버 종료 시에는 Server.Shutdown() 호출 전 readiness probe 실패를 통해 트래픽을 차단하고, 몇 초 대기한 뒤 shutdown을 수행하는 것이 안정적임
  • 모든 핸들러는 context 종료 신호를 감지하고 종료 가능해야 하며, BaseContext 또는 middleware를 통해 이를 통합적으로 처리할 수 있음
  • 종료 신호 수신 후 데이터베이스, 메시지 브로커, 캐시 등 외부 리소스는 의도적으로 정리해야 하며, defer로 등록하면 종료 순서 관리가 쉬움

Graceful Shutdown이란?

  • 우아한 종료는 애플리케이션이 종료될 때 새로운 요청 차단, 진행 중 요청 완료 대기, 리소스 정리를 거치는 프로세스임
  • 이 글은 주로 HTTP 서버와 컨테이너 환경을 다루지만, 모든 애플리케이션에 적용 가능한 개념

1. 종료 신호 처리

  • Unix 계열 시스템에서는 SIGTERM, SIGINT, SIGHUP 등이 종료 신호로 사용됨
  • Go 런타임은 SIGTERM, SIGINT 수신 시 기본적으로 애플리케이션을 종료하지만, os/signal.Notify로 직접 처리 가능함
  • 버퍼링된 채널(용량 1) 을 사용하면 초기화 중 신호 유실 방지 가능
  • Go 1.16 이후에는 signal.NotifyContext를 사용해 context 기반 신호 제어가 간편해짐

2. 종료 시간 인식

  • Kubernetes에서는 기본적으로 30초의 종료 유예 기간이 주어짐 (terminationGracePeriodSeconds)
  • 안전하게 종료하려면 20% 여유를 두고 25초 이내에 종료 작업을 완료하는 것이 바람직함

3. 새 요청 받기 중단

  • http.Server.Shutdown()은 새 연결을 차단하고 기존 요청이 완료될 때까지 대기
  • Kubernetes 환경에서는 readiness probe를 먼저 실패하게 만들어 트래픽 유입을 차단한 뒤 약간 대기 후 shutdown 수행
  • readiness 핸들러에서는 전역 변수로 종료 상태를 판단하여 HTTP 503 반환하도록 구성 가능함

4. 요청 처리 마무리

  • 종료를 위한 context에 적절한 timeout 설정 필요 (context.WithTimeout)
  • shutdown context가 만료되면 남은 연결은 강제 종료
  • 모든 핸들러는 context.Context를 활용해 종료 신호를 감지하고 중단 가능하도록 설계해야 함
  • 이를 위해 middleware나 BaseContext를 통해 모든 요청에 종료 context를 주입할 수 있음

5. 리소스 정리

  • 종료 신호를 받았다고 바로 리소스를 닫으면 처리 중인 핸들러에 문제 발생 가능
  • shutdown이 완료된 뒤에 데이터베이스 연결, 메시지 브로커, 캐시 등을 정리해야 함
  • Go의 defer를 활용하면 초기화 역순으로 종료 루틴 실행 가능하여 의존성 관리가 쉬움
  • 메모리, 파일 디스크립터 등 OS가 자동으로 정리하는 리소스 외에도 데이터 flush, 트랜잭션 rollback 등 명시적 종료가 필요한 리소스 존재

전체 예제 요약

  • signal.NotifyContext로 종료 신호 수신
  • /healthz readiness 엔드포인트 구현
  • BaseContext로 모든 요청에 종료 context 주입
  • readiness 5초 대기 후 shutdown 수행
  • server.Shutdown 호출 실패 시 강제 종료 fallback 포함

참고 문헌 및 관련 리소스

Read Entire Article