itge · demo| 블로그 — 개발자 기술블로그 (다크) ← 그 외 목록
⌘K 로 검색
devlog · 최신 글

고쳐 가며 남긴 기록

개발 책상
Node.js성능트러블슈팅

메모리가 새는 줄 알았는데
GC 설정이었다

운영 서버 메모리가 4일에 걸쳐 계단식으로 오르는 걸 잡은 기록입니다. 힙 스냅샷을 세 번 뜨고 나서야 원인이 코드가 아니라는 걸 알았습니다.

2026.04.14 · 11분 읽기 · 조회 2,840
Article view

본문 화면

기술 글은 코드 블록과 목차가 절반입니다. 스킨을 고를 때 이 두 개가 제일 중요합니다.

메모리가 새는 줄 알았는데 GC 설정이었다

2026.04.14 · 11분 읽기 · Node.js 20.11

운영 서버 메모리가 배포 직후 380MB에서 시작해 4일 뒤 1.6GB까지 올라갔습니다. 재시작하면 다시 380MB로 떨어졌고요. 전형적인 누수처럼 보였습니다.

1. 힙 스냅샷부터

--heapsnapshot-signal 을 붙여 두고 하루 간격으로 세 번 떴습니다. 스냅샷 사이 Retained Size 를 비교하면 뭐가 안 없어지는지 바로 보입니다.

server.sh
# 시그널로 힙 스냅샷을 뜬다. 재시작 없이 뜰 수 있다
node --heapsnapshot-signal=SIGUSR2 \
     --max-old-space-size=1024 \
     dist/main.js

# 필요할 때 시그널만 보내면 된다
kill -SIGUSR2 $(pgrep -f dist/main.js)

그런데 세 스냅샷의 Retained Size 합계가 거의 그대로였습니다. 객체는 안 늘고 있는데 프로세스 RSS만 올라간 겁니다.

2. 그럼 뭐가 늘어난 건가

  • process.memoryUsage()heapUsed 는 평평
  • rss 만 계속 상승
  • external 도 소폭 상승 — 버퍼 쪽 의심
metrics.ts
setInterval(() => {
  const m = process.memoryUsage()
  logger.info({
    rss: mb(m.rss),
    heapUsed: mb(m.heapUsed),
    external: mb(m.external),
  }, 'mem')
}, 30_000)
여기서 한 시간 날렸습니다

RSS 가 오른다고 전부 누수는 아닙니다. heapUsed 가 평평한데 rss 만 오르면 GC 가 메모리를 OS 에 안 돌려주고 있는 것일 수 있습니다. 컨테이너 메모리 한도가 넉넉하면 V8 은 굳이 반환하지 않습니다.

3. 원인

컨테이너 메모리 한도는 2GB인데 --max-old-space-size 를 안 줬습니다. V8 이 한도를 넉넉하다고 보고 힙을 계속 키운 겁니다. 누수가 아니라 설정 문제였습니다.

한도를 컨테이너의 75%인 1536 으로 고정하고 재배포했더니 RSS 가 4일 내내 620MB 언저리에서 평평해졌습니다.

Archive

글 목록

날짜·제목·읽는 시간만 있습니다. 목록에 요약을 길게 넣으면 스크롤이 안 됩니다.

Thumbnails

썸네일 템플릿 8종

스킨보다 이게 매일 쓰입니다. 제목만 갈아 끼우면 되게 만들어 드립니다 — 글을 쓸 때마다 디자인을 고민하면 결국 안 쓰게 됩니다.

01TROUBLESHOOTING 메모리가 새는 줄 알았는데
GC 설정이었다
02REACT useEffect 를 줄이니
렌더가 1/3이 됐다
03DATABASE 인덱스를 걸었는데
더 느려졌을까
04DEVOPS CI 를 12분에서
3분으로
05SNIPPET $ node --max-old-
space-size=1536
06POSTMORTEM 장애 회고 ·
4시간 12분
07RETRO 타입을 너무
좁게 잡아서 생긴 일
08SERIES 모노레포 이관기
1 / 5

여덟 종을 만들어 드리고, 글 성격에 따라 골라 쓰시면 됩니다. 티스토리·벨로그·깃허브 페이지 어디든 같은 틀로 씁니다.