ELIFECYCLE은 npm이 감싼 실패다. 실제 원인은 위 도구 로그와 종료 숫자다. 로컬은 되고 통합 환경만 실패하면 노드 버전, 잠금 파일 설치, 환경변수, 맥과 리눅스 대소문자부터 맞춘다. 개발자, npm, 깃허브 액션, Next.js, Node.js, 데브옵스 기준. 2026년 8월 npm과 깃허브 공식 문서 기준.
ELIFECYCLE은 npm이 감싼 실패입니다. 실제 원인은 그 위에 있는 빌드·테스트 종료 코드입니다. 로컬은 되고 CI만 빨간 줄이면, 노드 버전, 환경변수, npm ci와 npm install 차이부터 보세요.
노트북 노드는 20인데 액션은 18이고, 로컬 환경 파일은 있는데 CI 비밀 값은 빠진 조합을 혼자 워크플로 짜다 보면 자주 만납니다. 겉으로만 같은 빌드 명령입니다.
npm 로그의 Exit status 숫자를 읽고, engines와 캐시를 맞추면 대부분 끝납니다. 근거는 npm scripts와 액션 워크플로 문법에 있습니다.
ELIFECYCLE은 원인 이름이 아니다
스크립트가 0이 아닌 코드로 끝나 npm이 한 줄 덧붙인 것입니다. npm ERR! code ELIFECYCLE 아래 Exit status 1 또는 137이 진짜입니다. 1이면 명령 실패, 137이면 메모리 킬입니다.
로컬에서 npm run build가 초록이면, 같은 package.json 스크립트가 CI에서 다른 환경으로 돌고 있다는 뜻입니다. 스크립트 문자열을 고치기 전에 환경을 맞추세요.
lifecycle이라는 단어 때문에 배포 직전 훅만 의심하기 쉽습니다. 빌드 명령 실패도 같은 코드로 나옵니다. 훅 전용이 아닙니다.
빨간 줄만 보고 스크립트 이름을 지우면, 다음날 같은 실패가 다른 이름으로 돌아옵니다. 로컬에서 초록이었던 이유를 한 줄로 적고, 그 이유에 환경 파일이나 노드 버전이 들어 있으면 그게 CI에 있는지를 먼저 보세요. 한국에서 맥으로 짜고 우분투에서 돌리는 조합이면 파일 이름 대소문자도 같은 빨간 줄을 만듭니다.
먼저 기억할 것 | npm ERR! 블록보다 위, 도구가 찍은 첫 에러 줄을 복사하세요. tsc, next, eslint, jest 중 누가 1을 냈는지가 출발입니다.
같은 npm 스크립트라도 노드 버전과 환경변수가 다르면 CI만 실패한다
로컬은 되고 CI만 실패하는 네 칸
노드 버전, lock 설치, 비밀 값, OS가 갈리는 지점입니다.
칸
로컬
CI에서 빠지기 쉬운 것
노드 버전
nvm/mise로 최신
setup-node 기본값, engines 미검사
설치
npm install
npm ci + 어긋난 lock
환경변수
.env
gitignore, Secrets 미등록
대소문자
맥 디스크
리눅스 파일명
메모리
16GB
작은 러너, 종료 137
한국에서 맥으로 개발하고 우분투 액션을 쓰는 조합이면 네 번째 칸이 특히 많습니다. 불러오기 경로만 달라도 빌드가 실패로 끝납니다. 낮에 초록이어도 통합 환경 로그 첫 에러 줄이 다른 파일을 가리키면, 그 파일을 로컬에서 리눅스처럼 대소문자를 구분해 다시 열어보세요.
메모리 칸은 힙 부족 글입니다. ELIFECYCLE만 보고 스크립트를 지우면 137 원인을 놓칩니다.
로컬과 CI의 노드를 같게
node -v
npx next --version
# 액션
# - uses: actions/setup-node@v4
# with:
# node-version-file: '.nvmrc'
# cache: 'npm'
engines와 npm ci를 로컬에서도 돌리기
CI가 하는 명령을 노트북에서 그대로 치면 재현됩니다. rm -rf node_modules && npm ci && npm run build입니다. install로만 개발하다가 ci를 처음 쓰면 lock이 안 맞아 설치 단계에서 이미 실패합니다.
package.json의 engines.node를 적었으면 액션의 setup-node가 그 버전을 쓰게 하세요. 로컬은 22, CI는 18이면 문법이나 네이티브 애드온이 갈립니다. 버전 고정은 미즈·nvm 글과 맞춥니다.
engine-strict를 켜면 로컬에서도 버전 불일치가 바로 납니다. 끄고 개발하면 CI만 엄격해져 ELIFECYCLE로 보입니다.
CI와 같은 설치로 로컬 재현
rm -rf node_modules
npm ci
npm run build
# engines를 쓰려면
# npm config set engine-strict true
[ ] npm ERR!보다 위 실제 도구 에러를 복사했다
[ ] Exit status가 1인지 137인지 구분했다
[ ] node -v를 로컬과 CI 로그에서 비교했다
[ ] npm ci로 로컬 재현을 했다
[ ] CI에 필요한 환경변수가 Secrets에 있는지 봤다
로컬 install과 CI의 npm ci가 다르면 같은 스크립트가 갈린다
환경변수가 없어서 빌드가 1이 될 때
넥스트는 빌드 때 NEXT_PUBLIC_ 값을 넣습니다. 로컬 .env.local에만 있으면 CI 빌드가 빈 값으로 페이지를 만들거나, 스키마 검증에서 1로 끝납니다. 액션 env 또는 호스트 대시보드에 같은 키를 넣으세요.
비밀 키를 로그에 찍지 마세요. 있는지만 확인하고, 없으면 의도한 실패인지 보세요. 폴더별 환경은 direnv와 자리가 다릅니다. 여기서는 CI 잡에 값이 전달되는지만 봅니다.
피어 충돌로 설치가 막히면 ERESOLVE가 먼저입니다. 설치가 끝난 뒤 스크립트 실패만 ELIFECYCLE입니다.
스크립트를 지우지 말 것 | build를 echo로 바꿔 초록을 만드는 건 배포를 속이는 일입니다. Exit status의 주인을 고치세요.
Exit status를 읽고 다음 글로 넘기기
숫자가 갈리면 글도 갈립니다. 1이면 도구 에러, 137이면 힙, 127이면 명령을 못 찾음입니다. 127은 PATH에 next가 없는 npx 누락입니다. CI에서 npx next build 또는 로컬 바이너리 경로를 쓰세요.
동시성으로 이전 잡이 취소되면 실패처럼 보입니다. 그건 액션 동시성입니다. ELIFECYCLE 블록이 없는 취소 로그와 구분하세요.
제가 쓰는 발행 파이프라인도 로컬 셸 줄임말이 통합 환경에 없어 명령을 못 찾는 숫자로 끝난 적이 있습니다. 워크플로에는 줄임말 없이 풀 명령만 적습니다. 혼자 맥에서 편한 별명을 쓰다가 우분투에서 그대로 옮기면 같은 사고가 납니다.