DevLog

엔지니어링 블로그를 한 곳에서 탐색하고, 최근 발행 흐름을 빠르게 파악할 수 있는 서비스 입니다.

Quick Links

  • Latest Feed
  • Engineering Directory

Support

  • 소개
  • 개인정보처리방침

Contribute

  • 원하는 블로그 추가 (준비 중)
  • Feedback

© 2026 DevLog Inc. All rights reserved.

본 사이트는 공개 RSS 피드를 통해 콘텐츠를 수집하며, 모든 콘텐츠의 저작권은 원저작자에게 있습니다.

Back to Feed
Read Original

Contents

Continue Reading

  • More from 쏘카
  • Related reads#Node.js
#Backend

Node.js 컨테이너, 왜 깔끔하게 안 죽을까? (feat. Graceful shutdown)

Node.js 컨테이너, 왜 깔끔하게 안 죽을까? (feat. Graceful shutdown)
01

Summary

Node.js 컨테이너가 좀처럼 죽지 않는다면? PID 1과 이벤트 루프의 비밀

Kubernetes 환경에서 완벽한 Graceful Shutdown을 구현하기 위한 dumb-init 활용법과 타임아웃 전략

이 아티클은 Node.js 기반 배치 컨슈머가 컨테이너 환경에서 왜 정상적으로 종료되지 않는지 심층 분석합니다. Linux 커널의 PID 1 보호 메커니즘부터 Node.js 이벤트 루프의 특성까지 다루며, 실무적인 해결책으로 인프라와 애플리케이션 설정을 동기화하는 구체적인 방법을 제시합니다.

  • 01Linux PID 1의 특별한 시그널 보호 원칙과 이를 해결하기 위한 dumb-init의 필요성
  • 02NestJS 셧다운 훅 내 Promise.race를 활용한 애플리케이션 레벨 타임아웃 구현 패턴
  • 03이벤트 루프가 완전히 비워지기 전까지 프로세스가 종료되지 않는 Node.js 동작 원리 설명
  • 04애플리케이션 타임아웃과 K8s Grace Period 간의 유기적인 설정 정합성 강조
  • 05데이터 정합성 유지를 위해 AbortController 기반 강제 종료 대신 인프라 정책을 선택한 의사결정 과정

+RECOMMENDATION

Kubernetes에서 Node.js 마이크로서비스나 배치 앱을 운영하는 엔지니어에게 필독을 권하며, 특히 배포 시 작업 유실이 우려되는 상황에서 즉시 적용 가능한 가이드입니다.

The Problem

Kubernetes 환경에서 Node.js 컨테이너가 SIGTERM 시그널을 무시하거나, 종료 훅 실행 후에도 이벤트 루프에 남은 비동기 작업 때문에 프로세스가 즉시 종료되지 않아 배치 작업의 정합성이 깨지는 문제 발생.

The Solution

dumb-init을 도입하여 PID 1의 시그널 전파 및 좀비 프로세스 정리 문제를 해결하고, NestJS 셧다운 훅에 Promise.race 기반 타임아웃을 적용한 뒤 K8s의 terminationGracePeriodSeconds를 앱 타임아웃보다 길게 설정함.

The Result

종료 시그널이 모든 프로세스에 안정적으로 전달됨을 확인하였으며, 타임아웃 제어를 통해 프로세스 종료 시점을 예측 가능하게 관리하여 배치 작업 유실 리스크를 최소화함.

Trade-off

비동기 작업을 강제 중단하는 AbortController 방식은 코드 복잡도 증가와 외부 라이브러리의 트랜잭션 처리 불안정성 등 데이터 정합성 리스크가 있어 도입 대상에서 제외함.

03

Key Concepts

Concept · 01

PID 1 (Init Process)

리눅스 시스템 부팅 시 가장 먼저 실행되는 프로세스로, 다른 모든 프로세스의 부모 역할을 하며 시그널 전파 및 좀비 프로세스 회수를 담당함.

  • 커널은 PID 1이 명시적으로 핸들링하지 않는 시그널을 무시하도록 설계됨
  • dumb-init을 사용해 Node.js 프로세스 대신 시그널을 올바르게 중계하는 구조 구축
Concept · 02

Node.js Event Loop Exit Logic

Node.js는 실행 스택이 비어 있어도 이벤트 루프에 활성화된 타이머, I/O 핸들, 또는 콜백이 남아 있다면 프로세스를 종료하지 않음.

  • 종료 훅 함수가 반환되더라도 백그라운드의 비동기 작업이 남았다면 프로세스가 유지됨을 지적
  • 프로세스 종료를 위해서는 이벤트 루프 자체를 비우거나 강제 종료 시그널이 필요함
Concept · 03

terminationGracePeriodSeconds

Kubernetes가 Pod에 SIGTERM을 보낸 후 애플리케이션이 스스로 종료될 때까지 기다려주는 유예 시간 설정.

  • 애플리케이션 내부의 타임아웃 설정보다 길게 설정하여 안전한 정리를 보장
  • 설정된 시간이 지나면 K8s가 SIGKILL을 보내 컨테이너를 강제 종료함
Continue reading · same source

쏘카More from 쏘카

View all posts from 쏘카
  • S3 + CloudFront 기반 SPA 배포에서 캐시와 fallback 전략 설계하기

    CloudFrontS3SPA
    2주 전
  • 쏘카 디자인 시스템 2.0 개발기 2편: 기술로 굴리기(웹)

    Design SystemReactComponent Architecture
    4개월 전
  • 쏘카 디자인 시스템 2.0 개발기 1편: 시스템으로 굴리기(웹)

    Design SystemFigmaFigma Plugin
    4개월 전
  • 쏘카프레임 - 블루투스 모듈

    BluetoothBLEMobile Architecture
    6개월 전
  • 쏘카프레임 - 앱 프레임워크와 개발자 경험

    Socar Frame개발자 경험Android
    6개월 전

Related reads#Node.js

Explore #Node.js
NAVER D2·JavaScript

FE News 26년 4월 소식을 전해드립니다!

#Node.js3개월 전
당근

서버를 위한 Redux: Node.js 이벤트 소싱 라이브러리 개발기

#Node.js5개월 전
토스·AI

개발자는 AI에게 대체될 것인가

#Node.js5개월 전

Source

쏘카
쏘카
Engineering Blog

Published · January 19, 2026

Topics

Node.jsKubernetesDockerGraceful ShutdownEvent Loopdumb-initNestJS