npm ERR! code ELIFECYCLE 해결 — errno 1·134·SIGKILL 원인별 진단 가이드
npm run build를 돌렸는데 터미널이 빨간 글씨로 가득 찼습니다. 맨 아래엔 이런 줄이 보입니다.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `next build`
npm ERR! Exit status 1이 문구를 그대로 검색해서 들어오셨다면, 먼저 한 가지만 기억하세요. ELIFECYCLE은 범인이 아닙니다. 당황하지 말고 한 줄 위를 보세요. 진짜 원인은 항상 그 위에 있습니다.
ELIFECYCLE의 정체: npm은 잘못이 없다
핵심 개념
ELIFECYCLE= "lifecycle script(=package.json의scripts에 정의한 명령)가 0이 아닌 종료 코드로 끝났다"는 신호입니다. npm은 그저 자식 프로세스를 실행하고, 그 프로세스가 실패하자 "내가 돌린 스크립트가 죽었어요"라고 래핑해서 알려주는 역할만 합니다. 즉 진짜 에러 메시지는npm ERR! code ELIFECYCLE바로 위 줄들에 출력되어 있습니다.
실제 로그를 보면 구조가 명확합니다. 아래는 ESLint 실패로 빌드가 죽은 전형적인 출력입니다.
> [email protected] build
> eslint . && next build
/src/components/Header.tsx
12:7 error 'useState' is defined but never used no-unused-vars
✖ 1 problem (1 error, 0 warnings)
npm ERR! code ELIFECYCLE ← 여기는 결과 요약일 뿐
npm ERR! errno 1 ← '실패했다'는 사실만 알려줌윗부분의 'useState' is defined but never used가 진짜 원인입니다. ELIFECYCLE 줄만 복사해서 검색하면 영원히 답을 못 찾습니다. 로그를 위에서 아래로 거슬러 올라가며 첫 번째 빨간 에러를 찾는 게 핵심입니다.
ERESOLVE와 헷갈리지 마세요
pnpm/yarn으로 넘어왔다가 오랜만에 npm을 만진 분들이 자주 혼동하는 지점입니다. 둘은 발생 단계가 다릅니다.
- ELIFECYCLE:
npm install이후 스크립트(build/start/test) 실행 단계에서 발생 - ERESOLVE:
npm install도중 의존성 트리 해결 단계에서 발생 (peer dependency 충돌 등)
ERESOLVE가 떴다면 이 글이 아니라 의존성 충돌 해결(--legacy-peer-deps 등)을 다루는 글을 봐야 합니다. 이 글은 "설치는 됐는데 스크립트가 죽는" 경우를 다룹니다.
errno·signal 5초 분류법
빨간 로그에서 errno 또는 signal 단어를 찾아 아래 표와 대조하면 원인 카테고리가 즉시 좁혀집니다.
| 증상 문구 | 의미 | 대표 원인 | 1차 조치 |
|---|---|---|---|
errno 1 / Exit status 1 | 스크립트 일반 실패 | 린트·타입·테스트·webpack 에러 | 위 로그 확인, 해당 스크립트 단독 실행 |
errno 134 / SIGABRT, signal SIGKILL / Killed | 프로세스 강제 종료(OOM) | 메모리 부족, 힙 초과 | NODE_OPTIONS=--max-old-space-size=4096 |
errno ENOENT | 명령/파일 없음 | 패키지 미설치, 스크립트 오타, node_modules 없음 | npm install, 스크립트명 확인 |
ERESOLVE(참고) | 의존성 해결 실패 | peer dep 충돌 | 이건 ELIFECYCLE 아님 — 별도 처리 |
핵심: 134/Killed는 메모리, 1은 코드 에러, ENOENT는 없는 파일. 이 세 갈래만 기억하면 80%는 끝납니다.
원인별 복붙 해결책 6종
① 실제 스크립트 에러 (errno 1) — 가장 흔함
npm run build는 여러 명령을 묶어 돌리는 경우가 많아 어디서 죽었는지 가립니다. 해당 스크립트만 직접 실행해 원본 에러를 드러내세요.
# 빌드 스크립트 안에 묶인 명령을 따로 실행
npm run lint # 린트 단독 확인
npx tsc --noEmit # 타입 에러만 확인
npm test # 테스트 단독 확인여기서 나온 빨간 메시지가 진짜 원인입니다. 고치면 끝입니다.
② node_modules · lock 파일 손상
설치가 꼬였거나 lock과 실제 트리가 어긋났을 때입니다.
rm -rf node_modules package-lock.json
npm install③ 캐시 손상
위 방법으로도 같은 에러가 반복되면 캐시를 비웁니다.
npm cache clean --force
rm -rf node_modules
npm install
# Windows (PowerShell/CMD)
rd /s /q node_modules
npm cache clean --force
npm install④ 메모리 부족 (errno 134 / SIGKILL)
Killed 또는 JavaScript heap out of memory가 보이면 힙 한계를 올립니다. Node.js 20/22 LTS에서 기본 힙이 시스템 메모리 비례로 조정되긴 했지만, monorepo·대형 webpack 빌드에선 여전히 터집니다.
# 일시적
NODE_OPTIONS=--max-old-space-size=4096 npm run build
# package.json에 박아두기 (cross-env로 OS 호환)
# "build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 next build"CI에서는 환경 변수로 주입하는 편이 깔끔합니다.
env:
NODE_OPTIONS: --max-old-space-size=4096⑤ node 버전 불일치
로컬과 동료/CI의 Node 버전이 다르면 특정 패키지가 빌드 단계에서 죽습니다. 버전을 고정하세요.
# 프로젝트 루트에 .nvmrc 생성
echo "20" > .nvmrc
nvm use// package.json
{
"engines": {
"node": ">=20.0.0 <23.0.0",
"npm": ">=10.0.0"
}
}⑥ 권한 / EACCES
EACCES: permission denied가 보일 때 sudo npm install -g는 지양하세요. 루트 소유 파일이 생겨 더 큰 문제를 부릅니다. 전역 prefix를 사용자 폴더로 옮기는 게 안전합니다.
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
# ~/.zshrc 또는 ~/.bashrc 에 추가
export PATH=~/.npm-global/bin:$PATH로그 읽는 법: 위로 스크롤이 전부다
npm 10/11에서는 실패 시 전체 로그를 파일로 남깁니다. 터미널 출력이 잘렸다면 이 파일을 여세요.
# macOS / Linux
cat ~/.npm/_logs/*.log | tail -n 100
# 더 자세히 다시 실행
npm run build --verbose구버전이라면 프로젝트 폴더의 npm-debug.log를 확인합니다. 어떤 로그를 보든 방법은 같습니다. ELIFECYCLE 줄을 찾고, 거기서 위로 스크롤하며 첫 번째 진짜 에러를 찾으세요.
로컬은 되는데 CI(GitHub Actions)만 실패할 때
가장 약 오르는 상황이죠. 체크리스트는 이렇습니다.
- Node 버전 mismatch:
actions/setup-node의node-version을.nvmrc와 일치시켰는지 확인 npm civsnpm install: CI는 lock을 엄격히 따르는npm ci를 써야 합니다. lock과package.json이 어긋나면 즉시 실패- 러너 메모리 한계: GitHub 기본 러너는 약 7GB. 대형 빌드는 SIGKILL이 뜨므로
NODE_OPTIONS로 힙 조정 CI=true승격: 특히 CRA(Create React App)는CI=true일 때 경고를 에러로 승격시켜 로컬에선 통과하던 빌드가 죽습니다. 경고 자체를 고치는 게 정석입니다
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc' # 로컬과 버전 일치
cache: 'npm'
- run: npm ci # install 아님!실무 한마디
여러 프로젝트를 디버깅하며 느낀 건, ELIFECYCLE로 검색하는 시간의 90%가 낭비라는 점입니다. 신입 때 저도 npm ERR! code ELIFECYCLE을 그대로 구글에 붙여넣고 반나절을 날렸는데, 정작 답은 터미널 세 줄 위 Module not found에 있었습니다. 요즘은 빨간 로그를 보면 무조건 맨 위 에러부터 읽는 습관을 들였고, 트러블슈팅 시간이 체감상 1/5로 줄었습니다. ELIFECYCLE은 "스크립트가 죽었다"는 부고일 뿐, 사인(死因)은 그 위에 적혀 있습니다.
자주 묻는 질문 (FAQ)
Q. ELIFECYCLE과 ERESOLVE는 같은 에러인가요?
A. 아닙니다. ERESOLVE는 npm install 중 의존성 충돌(peer dependency 등)에서, ELIFECYCLE은 설치 이후 build/start/test 스크립트 실행 중에 발생합니다. 발생 단계가 완전히 다릅니다.
Q. errno 1과 134의 차이가 뭔가요?
A. errno 1은 스크립트가 일반적으로 실패한 경우(린트·타입·테스트 에러 등)이고, 134(또는 SIGKILL/Killed)는 메모리 부족으로 프로세스가 강제 종료된 경우입니다. 134가 보이면 NODE_OPTIONS=--max-old-space-size=4096을 먼저 시도하세요.
Q. 로컬에선 빌드가 되는데 GitHub Actions에서만 ELIFECYCLE이 떠요.
A. Node 버전 불일치, npm install 대신 npm ci 사용, 러너 메모리 한계로 인한 SIGKILL, 그리고 CI=true로 경고가 에러로 승격되는 경우(특히 CRA)를 차례로 확인하세요. .nvmrc와 node-version-file을 맞추는 것부터 시작하면 됩니다.
이 글은 AI 에이전트가 1차 초안을 작성한 뒤, 사람 편집자가 사실관계·출처·톤과 맥락을 검토하여 발행했습니다. 오류나 부정확한 내용이 확인되면 24시간 이내에 정정합니다.
댓글
불러오는 중...