노트

Next.js output: 'standalone'

Next.js Standalone Output

인프라#nextjs#docker · 연결된 개념 4개

쉽게 말하면

standalone 출력은 여행지에서 쓸 것만 골라 담은 캐리어 같아요. 집 전체인 node_modules를 통째로 옮기지 않아도, 빌드 때 실제로 쓰는 파일만 추려 담아서 서버 파일 하나로 바로 실행돼요.

비유가 깨지는 곳 이 캐리어엔 정적 파일이 기본으로 안 들어가요. public/과 .next/static은 직접 복사해야 해서, CDN이 서빙하는 운영은 멀쩡해도 노드가 직접 서빙하는 검증 환경만 화면이 깨질 수 있어요.

output: 'standalone'은 next build가 프로덕션 실행에 필요한 파일만 골라 .next/standalone 폴더에 모아 주는 빌드 출력 모드다. 이 폴더는 node_modules를 다시 설치하지 않고 node server.js 하나로 실행된다.

기본 모드와 무엇이 다른가

기본 모드의 .next는 혼자서는 돌지 않는다. next start를 하려면 옆에 package.json과 dependencies 전체가 설치된 node_modules가 있어야 한다. 그래서 배포 서버에서 소스를 받고 패키지를 설치한 뒤 빌드 결과를 덮어쓰는 식으로, 실행 직전에 "조립"하게 된다.

standalone은 빌드 때 이 조립을 끝낸다.

  • 파일 트레이싱(Output File Tracing): 빌드 중 @vercel/nft가 import·require·fs 사용을 정적으로 분석해 각 페이지가 불러올 수 있는 파일을 모은다. standalone은 그 목록대로 node_modules의 필요한 파일만 복사한다
  • 최소 서버: next CLI 대신 쓰는 server.js가 함께 나온다. 포트와 호스트는 PORT·HOSTNAME 환경 변수로 정한다
.next/standalone/
  server.js        next CLI 없이 실행하는 서버 진입점
  package.json
  node_modules/    트레이싱으로 추린 패키지만
  .next/           서버 렌더에 필요한 빌드 결과

직접 복사해야 하는 두 폴더

public/과 .next/static(JS 청크·CSS)은 기본으로 들어가지 않는다. 문서는 이 정적 파일을 CDN이 서빙하는 구성을 전제로 한다. 서버가 직접 서빙하게 하려면 빌드 뒤 복사한다. 그러면 server.js가 알아서 서빙한다.

cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/

환경마다 구성이 다르면 함정이 된다. 정적 자산을 CDN(assetPrefix)으로 보내는 운영 환경은 복사를 빠뜨려도 멀쩡하다. 그런데 CDN 없이 노드가 직접 서빙하는 검증 환경만 화면이 깨진다. 운영에서 통과했다고 안심하면 안 된다.

트레이싱 조정

  • outputFileTracingRoot: 모노레포에서는 기본 트레이싱 루트가 앱 폴더라 바깥 공용 패키지가 빠진다. 루트를 레포 최상단으로 올린다
  • outputFileTracingIncludes·outputFileTracingExcludes: 트레이싱이 놓치는 파일을 넣거나, 쓰지 않는데 딸려 오는 파일을 뺀다. 키는 라우트 글롭('/*', '/api/*'), 값은 프로젝트 루트 기준 파일 글롭이다. Edge 런타임 라우트와 완전 정적 페이지에는 적용되지 않는다
module.exports = {
  output: 'standalone',
  images: { unoptimized: true },   // 이미지 최적화를 안 쓴다면
  outputFileTracingExcludes: {
    '/*': ['node_modules/sharp/**/*', 'node_modules/@img/**/*'],
  },
}

위 예는 문서의 공식 예가 아니다(문서는 반대로 outputFileTracingIncludes로 sharp를 넣는 예를 든다). 이처럼 쓰지 않는 네이티브 모듈을 빼면 결과물이 작아질 뿐 아니라, 빌드 머신과 실행 머신의 CPU 아키텍처를 맞춰야 하는 제약도 풀린다(CPU 아키텍처와 네이티브 모듈).

컨테이너와 잘 맞는 이유

폴더 하나가 곧 배포 단위라서 Dockerfile: 레이어 캐시와 멀티 스테이지의 실행 스테이지가 COPY 몇 줄과 CMD ["node", "server.js"]로 끝난다. 이미지 안에서 다시 설치하지 않으니 이미지가 작고, devDependencies나 소스 코드가 실행 이미지에 들어가지 않는다. 컨테이너가 없는 기존 VM 배포에서도 "설치 단계 삭제, 실행 명령 교체"만으로 먼저 검증해 볼 수 있다.

COPY .next/standalone ./
COPY .next/static ./.next/static
COPY public ./public
CMD ["node", "server.js"]

출처: Next.js - output · Next.js - output: Caveats

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • next-intl과 서버 컴포넌트 친화 i18n

    next-intl은 Next.js App Router와 서버 컴포넌트를 전제로 설계된 국제화(Internationalization, i18n) 라이브러리다. 번역 메시지를 React Context가 아니라 요청 단위 설정 함수에서 읽어서, 번역만 쓰는 컴포넌트를 서버 컴포넌트로 남길 수 있다.

  • Pages Router에서 App Router로

    App Router는 Next.js 13에서 도입된 app/ 디렉터리 기반 라우터로, 서버 컴포넌트·중첩 레이아웃(Nested Layouts)·스트리밍을 기본으로 한다. pages/ 기반의 Pages Router에서 옮길 때 바뀌는 생각을 정리한다.

  • Next.js 16 변경점

    Next.js 16(2025년 10월 정식)은 Turbopack 기본화와 명시적 캐싱(Cache Components)이 핵심인 메이저 버전이다. 2026년 기준 업그레이드 가이드에서 중요한 것만 추린다.

  • NestJS

    NestJS는 TypeScript를 전제로 모듈·의존성 주입(Dependency Injection, DI)·데코레이터(decorator) 구조를 제공하는 Node.js 서버 프레임워크다. 2017년 Kamil Myśliwiec가 만들었고, 구조를 강제하는 방식 때문에 흔히 "Node.js의 Spring"이라 불린다.

  • 배럴 파일과 re-export

    배럴 파일(Barrel File)은 여러 모듈의 export를 index.ts 하나에 모아 다시 내보내(re-export) 진입점을 하나로 만드는 파일이다. 쓰는 쪽은 import { Button, Input } from './components'처럼 한 경로에서 가져온다.

보기 옵션