← 전체 글로 돌아가기

서버 운영

Node.js 빌드가 서버에서 죽는다면 메모리부터 확인한다

로컬에서 잘 되던 npm run build가 서버에서 갑자기 죽으면 십중팔구 메모리 문제다. OOM killer 로그와 swap 설정을 먼저 확인한다.

VPS에서 Next.js나 TypeScript 프로젝트를 빌드하다 보면 프로세스가 갑자기 죽는 일이 생긴다. 에러 메시지도 없이 빌드가 중간에 멈추거나, Killed라는 한 단어만 남기고 종료된다.

OOM killer 흔적 확인

프로세스가 메모리 부족으로 강제 종료됐는지 커널 로그에서 확인한다.

sudo dmesg | grep -i 'oom\|killed'
# [1234567.890] Out of memory: Kill process 12345 (node) score 900 or sacrifice child
# [1234568.123] Killed process 12345 (node) total-vm:2048000kB, anon-rss:1024000kB

oom이나 Kill process node가 보이면 OOM killer가 빌드 프로세스를 강제 종료한 것이다.

현재 메모리와 swap 상태 확인

free -h
#               total   used   free   shared  buff/cache  available
# Mem:           1.9G   1.7G    50M     20M       200M       100M
# Swap:            0B     0B     0B

Swap이 0이고 가용 메모리가 100MB 이하면 Node.js 빌드처럼 메모리를 많이 쓰는 작업이 죽을 수 있다.

swap 파일 추가

디스크에 여유가 있다면 swap 파일을 만들어 임시로 늘릴 수 있다.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 재부팅 후에도 유지하려면 /etc/fstab에 추가
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

2GB swap을 추가한 뒤 다시 빌드하면 대부분 해결된다.

Node.js 메모리 한도 직접 설정

Node.js는 기본적으로 힙 메모리를 시스템 RAM의 일정 비율로 제한한다. --max-old-space-size 옵션으로 명시적으로 설정할 수 있다.

# package.json scripts에 추가
"build": "NODE_OPTIONS='--max-old-space-size=1024' next build"

값은 MB 단위다. RAM이 2GB라면 1024~1536 정도로 설정하면 된다. 너무 크게 잡으면 다른 프로세스와 충돌하니 여유를 두는 편이 낫다.

빌드 전후 메모리 모니터링

# 빌드가 진행되는 동안 다른 창에서
watch -n 2 'free -h && echo "---" && ps aux --sort=-%mem | head -5'

메모리 사용량이 피크를 찍는 시점을 보면 빌드 어느 단계에서 문제가 생기는지 파악할 수 있다. Next.js는 타입 체크와 번들링 단계에서 메모리 사용량이 급격히 오른다. RAM이 작은 서버에서 빌드하는 것보다 CI에서 빌드해서 아티팩트를 배포하는 방식이 더 안정적이다.