빠른 흐름
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));종료 흐름
먼저 구분해 둘 기본형은 아래입니다.
- 운영 종료 신호:
SIGTERM - 로컬 중단 신호:
SIGINT - 정리 후 자연 종료:
process.exitCode = 1 - 정말 마지막 즉시 종료:
process.exit(1) - 종료 중복 방지:
if (shuttingDown) return
SIGTERM과 SIGINT
SIGTERM: 운영 환경 종료 요청SIGINT: 보통 Ctrl+C
실전에서는 둘 다 graceful shutdown 경로로 묶는 경우가 많습니다.
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));process.exit()를 바로 치지 않는 이유
서버, DB 연결, 열린 파일, 로그 flush 같은 정리 작업이 남아 있을 수 있기 때문입니다.
즉 종료 카드는 사실상 "정리 순서" 카드입니다.
- 새 요청 받기 중단
- 연결 정리
- 로그/큐 flush
- 마지막에 종료 코드 확정
process.exitCode와 직접 종료
즉시 종료가 아니라 "정리 후 종료 코드만 예약"하고 싶을 때는 process.exitCode가 더 자연스럽습니다.
반면 정말 마지막에 프로세스를 끝낼 타이밍이면 process.exit()를 씁니다.
process.exitCode = 1; // 정리 후 종료
// ...
process.exit(1); // 즉시 종료종료 로직은 한 번만 타게 만든다
SIGTERM과 SIGINT를 둘 다 받거나, 종료 중 예외가 다시 올라오면 shutdown 함수가 중복 실행되기 쉽습니다.
실전에서는 shuttingDown 플래그를 두고 한 번만 정리 흐름에 들어가게 만드는 편이 안전합니다.
'exit' 이벤트는 정리 시작점이 아니라 마지막 동기 훅이다
process.on("exit") 안에서는 비동기 정리를 기대하면 안 됩니다.
서버 닫기, DB flush, 큐 drain 같은 작업은 signal handler나 명시적 shutdown 함수에서 먼저 처리해야 합니다.
언제 직접 종료할까
체크포인트
- 운영 종료는
SIGTERM - 로컬 중단은
SIGINT - 먼저 정리, 나중에 종료
- 종료 코드는 0/비0 의미를 분명히 둔다
- shutdown 함수는 중복 실행되지 않게 막는다
주의할 점
시그널 핸들러 안에서 바로 process.exit(0)을 호출하면 "깔끔하게 종료"가 아니라 "정리 생략 후 즉시 종료"가 될 수 있습니다. 종료 신호를 받았을 때 더 중요한 건 exit 호출 자체보다, 남은 자원과 연결을 어떤 순서로 닫을지입니다.
참고 링크
1 sources