본문 바로가기
Backend2026년 7월 15일4분 읽기

우아한 종료(graceful shutdown) — 배포할 때 요청 끊기지 않게

YS
김영삼
조회 170
우아한 종료(graceful shutdown) — 배포할 때 요청 끊기지 않게

핵심 요약

배포·스케일 조정으로 서버 프로세스를 종료할 때, 그냥 죽이면 처리 중이던 요청이 중간에 끊겨 사용자가 에러를 본다. 우아한 종료는 종료 신호(SIGTERM)를 받으면 ① 새 요청은 거부하고 ② 진행 중인 요청은 끝까지 처리한 뒤 ③ 정리하고 종료하는 것이다.

1. 왜 필요한가

쿠버네티스·PM2·systemd 등은 종료 시 프로세스에 먼저 SIGTERM을 보내 "정리할 시간"을 준다. 이 신호를 무시하면 잠시 후 SIGKILL로 강제 종료되어 진행 중 작업이 날아간다. SIGTERM을 받아 마무리 로직을 넣는 게 핵심이다.

2. 기본 구현 (Node.js 예)

const server = app.listen(3000)

function shutdown() {
  console.log('SIGTERM 수신, 종료 시작')
  // 1) 새 연결 거부 + 진행 중 요청은 마무리
  server.close(async () => {
    // 2) DB·큐 등 자원 정리
    await db.close()
    console.log('정상 종료')
    process.exit(0)
  })
  // 3) 너무 오래 걸리면 강제 종료(무한 대기 방지)
  setTimeout(() => process.exit(1), 10000).unref()
}

process.on('SIGTERM', shutdown)
process.on('SIGINT', shutdown)  // Ctrl+C

3. 놓치기 쉬운 것

  • 헬스체크 연동 — 종료 시작 시 헬스체크를 먼저 실패로 바꿔, 로드밸런서가 새 트래픽을 안 보내게 한다(그 다음 기존 요청 마무리).
  • keep-alive 연결 — 유휴 연결이 server.close를 막을 수 있다. 타임아웃으로 강제 종료 안전망을 둔다.
  • 백그라운드 작업 — 처리 중인 큐 작업·크론도 안전하게 멈추거나 완료를 기다린다.

4. 쿠버네티스에서

  • SIGTERM 후 terminationGracePeriodSeconds(기본 30초) 동안 정리 시간을 준다 — 마무리 로직이 이보다 오래 걸리면 잘린다.
  • preStop 훅으로 잠깐 대기해, 엔드포인트에서 파드가 빠지는 시간을 확보하는 패턴도 흔하다.

자주 묻는 질문

SIGTERM과 SIGKILL 차이가 뭔가요?

SIGTERM은 "정리하고 종료해달라"는 정중한 요청이라 앱이 가로채 마무리 작업을 할 수 있습니다. SIGKILL은 즉시 강제 종료라 가로챌 수 없습니다. 오케스트레이터는 보통 SIGTERM을 먼저 보내고, 유예 시간 안에 안 죽으면 SIGKILL을 보냅니다.

종료 처리가 유예 시간보다 오래 걸리면요?

강제 종료(SIGKILL)되어 진행 중 작업이 잘립니다. 그래서 마무리 로직에 자체 타임아웃을 두고, 오래 걸리는 작업은 트랜잭션·멱등 처리로 중단돼도 안전하게 설계해야 합니다. 유예 시간도 실제 소요에 맞게 늘리세요.

헬스체크를 먼저 실패시키는 이유는요?

로드밸런서가 이 서버를 "정상"으로 아는 동안엔 새 요청을 계속 보냅니다. 종료를 시작하면 헬스체크를 먼저 실패로 바꿔 신규 트래픽을 끊고, 이미 들어온 요청만 마무리하면 끊김 없는 배포가 됩니다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록