본문 바로가기
Q&A2026년 7월 1일1분 읽기

Next.js 16 빌드가 CI에서 JavaScript heap out of memory로 죽습니다

n
nextjs_dohyun
조회 1216댓글 3

로컬(맥북 32GB)에서는 next build가 잘 되는데, GitHub Actions에서만 이렇게 죽습니다.

FATAL ERROR: Reached heap limit Allocation failed
- JavaScript heap out of memory

페이지가 200개 정도 되는 앱입니다. NODE_OPTIONS=--max-old-space-size를 4096으로 올려도 여전히 죽어요. 러너를 더 큰 걸로 바꿔야만 하나요?

댓글 3

김김영삼4개월 전

러너를 키우는 건 마지막 수단이고, 먼저 두 가지를 봐야 합니다. 로컬 32GB에서 되던 게 CI(보통 7GB)에서 죽는 건 빌드 피크 메모리가 그 사이 어딘가라는 뜻이에요.

1. Turbopack 빌드 캐시 켜기 (16.3+)

16.3의 Turbopack 영구 캐시가 바로 이 문제를 겨냥해 나왔습니다. Vercel 사례에서 빌드 메모리가 21.5GB → 2GB로 줄었어요.

# next.config.js
module.exports = {
experimental: { turbopackFileSystemCacheForBuild: true }
}
# 빌드
next build --turbopack
2. max-old-space-size를 러너 실메모리에 맞게

4096은 애매합니다. 러너가 7GB면 그보다 살짝 낮게:

# GitHub Actions step env
NODE_OPTIONS: --max-old-space-size=6144

단, 물리 메모리보다 크게 잡으면 OOM Killer가 프로세스를 죽여서 오히려 더 빨리 터집니다. 러너 스펙을 먼저 확인하세요.

3. 소스맵·병렬성 조정
  • 프로덕션 소스맵이 켜져 있으면 메모리를 크게 먹습니다. 꼭 필요할 때만.
  • 빌드 워커 병렬 수를 줄이면 피크 메모리가 낮아집니다(느려지는 대신).

보통 1번(Turbopack 캐시) + 2번(정확한 힙 사이즈)만 해도 큰 러너 없이 통과합니다.

nnextjs_dohyun(guest)4개월 전
Turbopack 캐시 켜니까 빌드는 통과하는데, 캐시가 매번 새로 만들어져서 CI에서 이득이 없는 것 같아요. Actions에서 캐시를 유지하려면 어떻게 하나요?
김김영삼4개월 전

맞아요, CI는 매 실행이 깨끗한 환경이라 .next/cache를 명시적으로 저장·복원해줘야 이득이 생깁니다. actions/cache로 물려주세요.

- uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/.next/cache
# 소스가 바뀌면 키가 바뀌어 새 캐시, 아니면 재사용
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.[jt]s', '**/*.[jt]sx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-

포인트는 restore-keys입니다. 정확히 일치하는 캐시가 없어도 가장 최근 유사 캐시를 가져와 증분 빌드를 하게 해줍니다. 이게 없으면 소스 한 줄만 바뀌어도 캐시를 통째로 버려서 말씀하신 상황이 됩니다.

Ctrl+Enter로 등록