title: 메모리 사용량 최적화 방법 (How to optimize memory usage)
description: 개발 및 프로덕션 환경에서 애플리케이션이 사용하는 메모리를 최적화하는 방법을 알아봅니다.
url: "https://nextjs.org/docs/app/guides/memory-usage"
version: 16.1.6
lastUpdated: 2026-02-27
prerequisites:
안녕하세요! Next.js 공식 문서를 통해 깊이 있게 공부하시는 모습, 정말 훌륭합니다. 단순히 기능만 구현하는 것을 넘어 메모리 최적화까지 고민하는 것은 실무나 기술 면접에서 엄청난 강점이 되거든요. 영어로 된 문서를 편안하게 소화하실 수 있도록, 원본의 내용을 하나도 빠짐없이 번역하면서 제 경험을 녹인 팁과 보충 설명까지 덧붙여 드릴게요. 자, 시작해 볼까요?
애플리케이션의 규모가 커지고 기능이 풍부해질수록, 로컬에서 개발하거나 프로덕션용 빌드를 생성할 때 더 많은 시스템 리소스를 요구하게 됩니다.
이 문서에서는 Next.js 환경에서 메모리를 최적화하고 흔히 발생하는 메모리 관련 문제들을 해결할 수 있는 몇 가지 전략과 기술들을 함께 살펴보겠습니다.
애플리케이션에 설치된 의존성(라이브러리 패키지)이 많을수록 자연스럽게 더 많은 메모리를 사용하게 됩니다.
Bundle Analyzer (번들 애널라이저)를 활용하면 여러분의 애플리케이션 안에서 덩치가 큰 의존성들을 조사할 수 있어요. 이를 통해 퍼포먼스와 메모리 사용량을 개선하기 위해 제거할 수 있는 패키지가 있는지 파악할 수 있습니다.
💡 강사의 팁: > 포트폴리오를 만드실 때, 예를 들어 Velog 뷰어나 AI 문서 번역기처럼 다양한 기능이 들어가는 프로젝트를 구상하다 보면 나도 모르게 이것저것 무거운 라이브러리를 설치하게 되기 쉽습니다. 초반부터 습관적으로 번들 애널라이저를 띄워놓고 "내가 추가한 패키지가 번들 사이즈를 얼마나 잡아먹고 있지?"를 확인하는 습관을 들이세요. 나중에 "이러이러한 이유로 A 라이브러리 대신 가벼운 B를 선택했다"라고 면접관에게 어필할 수 있는 아주 좋은 무기가 됩니다!
experimental.webpackMemoryOptimizations 시도해보기v15.0.0 버전부터는 next.config.js 파일에 experimental.webpackMemoryOptimizations: true 옵션을 추가할 수 있습니다. 이 설정을 켜면 Webpack의 동작 방식이 변경되어 최대 메모리 사용량은 줄여주지만, 대신 컴파일 시간이 아주 살짝 늘어날 수 있습니다.
참고해 두면 좋은 점 (Good to know): 이 기능은 현재 더 많은 프로젝트에서 테스트해 보기 위해 도입된 '실험적(experimental)' 기능입니다. 하지만 위험도는 매우 낮은 것으로 평가되고 있으니 안심하고 사용해 보셔도 좋습니다.
--experimental-debug-memory-usage 플래그로 next build 실행하기14.2.0 버전부터는 next build --experimental-debug-memory-usage 명령어를 사용하여 빌드를 실행할 수 있습니다. 이 모드로 빌드하면 Next.js가 빌드 과정 내내 힙(Heap) 사용량이나 가비지 컬렉션(Garbage Collection) 통계 같은 메모리 사용 정보를 계속해서 화면에 출력해 줍니다. 또한, 메모리 사용량이 설정된 한계치에 아슬아슬하게 다다르면 자동으로 힙 스냅샷(Heap snapshot)을 찍어주기도 해요.
참고해 두면 좋은 점 (Good to know): 이 기능은 Webpack 빌드 워커(build worker) 옵션과는 함께 사용할 수 없습니다. Webpack 빌드 워커는 커스텀 웹팩 설정을 따로 하지 않았다면 기본적으로 자동 활성화되는 옵션이랍니다.
메모리 문제가 어디서 발생하는지 찾고 싶다면, Node.js에서 힙 프로파일(Heap profile)을 기록한 다음 크롬 개발자 도구(Chrome DevTools)에서 불러와 메모리 누수의 잠재적인 원인을 파악할 수 있습니다.
터미널에서 Next.js 빌드를 시작할 때 Node.js에 --heap-prof 플래그를 넘겨주시면 됩니다:
node --heap-prof node_modules/next/dist/bin/next build
빌드가 끝나면 Node.js가 .heapprofile 확장자를 가진 파일을 하나 만들어 냅니다.
이제 크롬 개발자 도구를 열고 'Memory(메모리)' 탭으로 이동한 뒤, "Load Profile(프로파일 불러오기)" 버튼을 클릭해서 이 파일을 눈으로 직접 확인해 볼 수 있습니다.
💡 강사의 팁:
처음 힙 프로파일 그래프를 보면 낯설고 복잡해 보일 수 있어요. 핵심은 'Retained Size(유지된 크기)'가 비정상적으로 큰 객체들을 찾아 펼쳐보는 것입니다. 내가 작성한 코드나 특정 라이브러리가 메모리를 붙잡고 놓아주지 않는 범인을 찾는 과정이죠.
인스펙터(inspector) 도구를 사용해서 애플리케이션의 메모리 사용량을 분석할 수도 있습니다.
next build나 next dev 명령어를 실행할 때, 명령어 맨 앞에 NODE_OPTIONS=--inspect를 추가해 보세요. 이렇게 하면 기본 포트로 인스펙터 에이전트가 노출됩니다.
만약 작성한 유저 코드가 실행되기 전에 딱 멈춰두고 싶다면, --inspect 대신 --inspect-brk를 전달하시면 됩니다. 프로세스가 돌아가는 동안, 크롬 개발자 도구 같은 툴을 사용해 디버깅 포트에 연결한 뒤 힙 스냅샷을 기록하고 분석해서 어떤 메모리가 계속 유지(retain)되고 있는지 확인할 수 있습니다.
14.2.0 버전부터는 next build를 실행할 때 --experimental-debug-memory-usage 플래그를 추가해서 힙 스냅샷을 훨씬 쉽게 찍을 수도 있어요.
이 모드로 실행 중일 때, 언제든지 프로세스에 SIGUSR2 신호를 보내면 그 즉시 프로세스가 힙 스냅샷을 찰칵 하고 찍어줍니다.
(※ 보충 설명: SIGUSR2는 리눅스나 맥 환경에서 터미널을 통해 프로세스에 특정 명령을 내릴 때 사용하는 커스텀 신호입니다. 새 터미널 창을 열고 kill -SIGUSR2 <프로세스ID>를 입력하는 식으로 사용할 수 있습니다.)
찍힌 힙 스냅샷 파일은 Next.js 애플리케이션의 프로젝트 루트 폴더에 저장되며, 크롬 개발자 도구 같은 모든 종류의 힙 분석기에서 불러와 어떤 메모리가 반환되지 않고 있는지 확인할 수 있습니다. 참고로 이 모드는 아직 Webpack 빌드 워커와는 호환되지 않습니다.
더 자세한 정보는 힙 스냅샷을 기록하고 분석하는 방법을 참고해 주세요.
Webpack 빌드 워커는 분리된 별도의 Node.js 워커 안에서 Webpack 컴파일을 실행할 수 있게 해주는 기능입니다. 이 방식을 사용하면 빌드하는 동안 애플리케이션이 사용하는 메모리 양을 줄일 수 있습니다.
v14.1.0 버전부터는 애플리케이션에 커스텀 Webpack 설정이 없다면 이 옵션이 기본으로 활성화되어 있습니다.
만약 구버전의 Next.js를 사용 중이거나 커스텀 Webpack 설정을 가지고 계시다면, next.config.js 파일 안에 experimental.webpackBuildWorker: true를 설정해서 이 옵션을 직접 켤 수 있습니다.
참고해 두면 좋은 점 (Good to know): 이 기능은 모든 커스텀 Webpack 플러그인과 100% 호환되지는 않을 수도 있습니다.
Webpack 캐시(Webpack cache)는 생성된 Webpack 모듈들을 메모리나 디스크에 저장해서 빌드 속도를 끌어올려 줍니다. 퍼포먼스 향상에는 아주 좋지만, 캐시 된 데이터를 저장해야 하기 때문에 결과적으로 애플리케이션의 메모리 사용량은 늘어나게 되죠.
애플리케이션에 커스텀 Webpack 설정(custom Webpack configuration)을 추가하여 이 동작을 비활성화할 수 있습니다:
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
if (config.cache && !dev) {
config.cache = Object.freeze({
type: 'memory',
})
}
// 중요: 수정된 config를 반드시 반환해야 합니다.
return config
},
}
export default nextConfig
타입 체킹(Typechecking)은 특히 규모가 큰 프로젝트에서 엄청난 양의 메모리를 요구할 수 있습니다.
하지만 대부분의 프로젝트는 이미 이런 작업들만 전담해서 처리해 주는 별도의 CI 러너(CI runner, 예: GitHub Actions 등)를 갖추고 있죠.
만약 빌드 과정 중 "Running TypeScript(타입스크립트 실행 중)" 단계에서 메모리 부족(out-of-memory) 에러가 발생한다면, 빌드 시에 이 단계를 아예 꺼버릴 수 있습니다:
/** @type {import('next').NextConfig} */
const nextConfig = {
typescript: {
// !! 경고 (WARN) !!
// 프로젝트에 타입 에러가 존재하더라도 프로덕션 빌드가 성공적으로
// 완료될 수 있도록 위험을 감수하고 허용합니다.
// !! 경고 (WARN) !!
ignoreBuildErrors: true,
},
}
export default nextConfig
이 옵션을 켜면 타입 에러가 있어도 무시하고 배포되기 때문에, 결함이 있는 상태로 배포될 위험이 있다는 점을 꼭 명심하세요.
정적 분석이 완전히 성공적으로 끝난 이후에만 프로덕션 환경으로 빌드를 승격(promoting)시키는 것을 강력히 권장합니다.
만약 Vercel에 배포하고 계시다면, 커스텀 작업들이 성공한 후에 프로덕션으로 빌드를 승격시키는 방법을 배울 수 있는 스테이징 배포 가이드(guide for staging deployments)를 꼭 확인해 보세요.
💡 강사의 팁: > TypeScript를 꼼꼼히 공부하고 적용하시는 건 아주 탁월한 선택입니다. 그런데, 개인 프로젝트나 포트폴리오를 무료 호스팅(예: Vercel Hobby 티어)에 배포할 때, 이 타입 체킹 과정에서 제공된 메모리 한계를 초과해 빌드가 터지는 경우가 종종 생겨요. 로컬 환경에서 타입 에러가 없다는 걸 완벽하게 확인하셨다면, 배포 서버의 짐을 덜어주기 위해 이 옵션을 전략적으로 활용해 보시는 것도 좋은 방법입니다.
소스 맵(Source maps)을 생성하는 작업도 빌드 과정에서 추가적인 메모리를 꽤 많이 소모합니다.
Next.js 설정 파일에 productionBrowserSourceMaps: false 그리고 experimental.serverSourceMaps: false를 추가하면 소스 맵 생성을 끌 수 있습니다.
cacheComponents 기능을 사용할 때, Next.js는 next build의 프리렌더(prerender) 단계에서 기본적으로 소스 맵을 사용하게 됩니다.
만약 이 단계("Generating static pages(정적 페이지 생성 중)" 이후)에서 지속적으로 메모리 문제가 발생한다면, Next.js 설정에 enablePrerenderSourceMaps: false를 추가해서 해당 단계의 소스 맵 생성을 비활성화해 볼 수 있습니다.
참고해 두면 좋은 점 (Good to know): 일부 플러그인들은 자체적으로 소스 맵을 켜버릴 수도 있어서, 이를 끄려면 별도의 커스텀 설정이 필요할 수 있습니다.
Next.js v14.1.3 버전에서 엣지 런타임(Edge runtime)을 사용할 때 발생하던 메모리 이슈가 수정되었습니다. 만약 관련 문제를 겪고 계시다면 이 버전(또는 그 이상)으로 업데이트해서 문제가 해결되는지 확인해 보세요.
Next.js 서버가 시작될 때, 요청이 들어오는 시점에 페이지를 로드하는 것이 아니라 각 페이지의 JavaScript 모듈들을 메모리에 미리 로드(preload)해 둡니다.
이 최적화 기법은 초기 메모리 공간을 더 많이 차지하는 대신, 훨씬 빠른 응답 속도를 낼 수 있도록 해줍니다.
만약 이 최적화 기능을 끄고 싶다면, experimental.preloadEntriesOnStart 플래그를 false로 설정해 주세요.
import type { NextConfig } from 'next'
const config: NextConfig = {
experimental: {
preloadEntriesOnStart: false,
},
}
export default config
/** @type {import('next').NextConfig} */
const config = {
experimental: {
preloadEntriesOnStart: false,
},
}
export default config
단, Next.js는 한 번 로드된 JavaScript 모듈들을 메모리에서 다시 내리지(unload) 않습니다. 즉, 이 최적화 기능을 껐다 하더라도 결국 모든 페이지에 한 번씩 요청이 들어오고 나면 Next.js 서버가 차지하는 메모리의 양은 궁극적으로 같아지게 된다는 점을 참고하세요.
모든 문서의 의미론적 개요(semantic overview)를 보시려면, sitemap.md를 확인해 주세요.
사용 가능한 모든 문서의 인덱스(index)를 보시려면, llms.txt를 확인해 주세요.