Node.js RPS 급락의 원인: GC Stop-the-World 현상과 힙 메모리 최적화 전략

🤖 AI 추천

고성능 Node.js 애플리케이션을 운영 중이며 주기적인 성능 저하 현상을 겪고 있는 백엔드 개발자 및 DevOps 엔지니어에게 이 글을 추천합니다. 특히 V8 GC 동작 방식과 힙 메모리 설정의 중요성을 이해하고 싶은 개발자에게 유용합니다.

🔖 주요 키워드

Node.js RPS 급락의 원인: GC Stop-the-World 현상과 힙 메모리 최적화 전략

핵심 기술

본 콘텐츠는 Node.js 애플리케이션에서 발생하는 주기적인 RPS(Requests Per Second) 급락 현상의 근본 원인이 V8 엔진의 가비지 컬렉션(GC) 중 발생하는 'Stop-the-World' 동작과 힙 메모리 부족에 있음을 분석합니다. 해결 방안으로 힙 메모리 한도 확대를 제안하며, 그 효과와 한계를 탐구합니다.

기술적 세부사항

  • 현상: 고성능 인프라(c6in.xlarge) 도입 후에도 부하 테스트 시 약 30초마다 RPS가 5,000 이상에서 0에 가깝게 급락하고 요청 실패가 발생하는 문제.
  • 원인 분석:
    • CPU, 네트워크 자원은 충분했으나 애플리케이션 내부 문제 의심.
    • 주기적인 멈춤 현상이 Node.js(V8 엔진)의 'Stop-the-World' GC 패턴과 유사.
    • 높은 RPS로 인한 객체 축적으로 힙(Heap) 메모리 포화.
    • V8 엔진이 힙 한도 도달 시 GC 수행을 위해 모든 애플리케이션 스레드 일시 중단.
    • 이로 인한 응답 지연(수백 ms)으로 NLB 타임아웃 발생 및 요청 실패.
    • GC 완료 후 작업 재개로 RPS 일시적 회복.
  • Node.js 기본 힙 한도: c6in.xlarge (RAM 8GB) 인스턴스에서 Node.js 18.x 버전 기준 약 1.4GB.
  • 가설 검증: 약 5,000 RPS 부하에서 1.4GB 힙이 30초 만에 포화되는 것을 확인.
  • 해결법 1: 힙 메모리 확장
    • pm2 start app.js --node-args="--max-old-space-size=4096" 명령어로 힙 한도를 4GB로 증설.
    • 결과: 안정 구간 최대 RPS 6,000 이상으로 향상.
    • 한계: '주기적인 멈춤' 현상은 여전히 동일하게 발생. 메모리 증설 배율만큼 멈춤 간격이 늘어나지 않음.
  • 추가 분석 필요: GC가 유일한 원인이 아닐 가능성 제시, 후속 해결법 예고.

개발 임팩트

  • Node.js 애플리케이션의 성능 병목 현상 진단 및 해결 능력 향상.
  • GC의 동작 방식과 힙 메모리 설정이 애플리케이션 성능에 미치는 영향 이해.
  • 대규모 트래픽 처리 시 발생할 수 있는 잠재적 문제점 예방 및 대응 전략 수립.

커뮤니티 반응

  • (원문 언급 없음)

📚 관련 자료