How to optimize your Next.js application for production

김동현·2026년 3월 5일

next.js 공식문서 번역

목록 보기
57/79

title: Next.js 애플리케이션 프로덕션 최적화 가이드 (How to optimize your Next.js application for production)
description: Next.js 애플리케이션을 실제 서비스(프로덕션)에 배포하기 전에 최고의 성능과 사용자 경험을 보장하기 위한 권장 사항들입니다.
url: "https://nextjs.org/docs/app/guides/production-checklist"
version: 16.1.6
lastUpdated: 2026-02-27
prerequisites:


Next.js 애플리케이션을 실제 서비스(프로덕션)에 배포하기 전에, 최고의 사용자 경험, 성능, 그리고 보안을 위해 몇 가지 최적화 기법과 패턴들을 적용하는 것을 꼭 고려해 보셔야 해요.

이 페이지는 여러분이 앱을 개발하는 동안 그리고 프로덕션에 배포하기 직전에 참고할 수 있는 모범 사례(Best Practices)들을 제공합니다. 또한, 여러분이 꼭 알아두셔야 할 Next.js의 자동 최적화 기능들에 대해서도 설명해 드릴게요.

자동 최적화 (Automatic optimizations)

아래에 설명할 Next.js의 최적화 기능들은 기본적으로 켜져 있어서 여러분이 따로 설정할 필요가 없습니다. 정말 편리하죠?

  • 서버 컴포넌트 (Server Components): Next.js는 기본적으로 서버 컴포넌트를 사용해요. 서버 컴포넌트는 말 그대로 서버에서 실행되기 때문에, 클라이언트(브라우저)에서 렌더링하기 위한 JavaScript 파일이 필요하지 않아요. 즉, 사용자가 다운로드해야 하는 클라이언트 측 JavaScript 번들 크기에 전혀 영향을 주지 않는다는 뜻이죠. 상호작용(인터랙션)이 필요한 곳에만 필요에 따라 클라이언트 컴포넌트 (Client Components)를 섞어서 사용하시면 됩니다.

    💡 강사 팁: 서버 컴포넌트는 프론트엔드 성능 최적화의 일등 공신이에요! useStateuseEffect 같은 훅(Hook)은 서버 컴포넌트에서 쓸 수 없으니, 버튼 클릭 같은 이벤트가 필요한 최소한의 영역만 클라이언트 컴포넌트("use client")로 분리해서 트리 아래쪽으로 내리는 습관을 들여보세요.

  • 코드 스플리팅 (Code-splitting): 서버 컴포넌트는 라우트 세그먼트별로 자동 코드 스플리팅을 지원합니다. 또한, 상황에 따라 클라이언트 컴포넌트나 서드파티 라이브러리를 지연 로딩 (lazy loading) 하는 것도 고려해 보세요.

    💡 강사 팁: 무거운 차트 라이브러리나 당장 화면에 보이지 않는 모달 창 같은 건 next/dynamic을 사용해서 지연 로딩 처리를 해주면 초기 로딩 속도를 엄청나게 끌어올릴 수 있습니다.

  • 프리패칭 (Prefetching): 새로운 라우트로 이동하는 링크(<Link>)가 사용자의 화면(뷰포트)에 들어오면, Next.js는 백그라운드에서 해당 라우트를 미리 가져옵니다(Prefetch). 덕분에 다른 페이지로 넘어갈 때 거의 즉시 이동하는 것처럼 느껴지게 되죠! 필요하다면 이 프리패칭 기능을 끌 수도 있어요.

    💡 강사 팁: 한 화면에 게시물 링크가 100개씩 렌더링된다면 어떻게 될까요? 백그라운드에서 100개의 페이지를 미리 불러오느라 서버에 부담이 갈 수 있겠죠. 그럴 때는 <Link prefetch={false}>로 설정해서 마우스를 올렸을 때만 불러오도록 조절하는 센스가 필요합니다.

  • 정적 렌더링 (Static Rendering): Next.js는 빌드할 때 서버와 클라이언트 컴포넌트를 서버에서 정적으로 렌더링하고, 애플리케이션의 성능을 높이기 위해 그 결과를 캐싱해 둡니다. 물론, 실시간 데이터가 필요한 특정 라우트에서는 동적 렌더링 (Dynamic Rendering)을 선택해서 사용할 수도 있어요.

  • 캐싱 (Caching): Next.js는 데이터 요청, 서버/클라이언트 컴포넌트의 렌더링 결과, 정적 에셋(이미지 등) 등을 꼼꼼하게 캐싱합니다. 여러분의 서버, 데이터베이스, 백엔드 서비스로 가는 네트워크 요청 횟수를 획기적으로 줄여주죠. 필요하다면 특정 부분의 캐싱을 무효화하거나 제외할 수도 있습니다.

    💡 강사 팁: 캐싱은 성능 향상의 핵심이지만, 초보자분들이 "어? DB 값을 바꿨는데 왜 화면이 안 바뀌지?" 하고 가장 많이 당황하는 부분이기도 해요. revalidate 옵션이나 revalidatePath 등을 통해 캐시 무효화 전략을 잘 짜는 것이 실력 있는 개발자의 필수 소양입니다.

이러한 기본 설정들은 애플리케이션의 전반적인 성능을 향상시키고, 각 네트워크 요청 시 전송되는 데이터의 양과 비용을 줄이는 데 목적을 두고 있어요.


개발 중일 때 (During development)

애플리케이션을 한창 만들고 계실 때, 최고의 성능과 사용자 경험을 놓치지 않으려면 다음 기능들을 적극적으로 활용하시길 권장해 드려요.

라우팅 및 렌더링 (Routing and rendering)

알아두면 좋은 정보(Good to know): 부분 사전 렌더링(Partial Prerendering, 실험적 기능)을 사용하면 라우트 전체를 동적 렌더링으로 전환하지 않고도 라우트의 일부분만 동적으로 만들 수 있게 될 예정입니다.

데이터 페칭 및 캐싱 (Data fetching and caching)

  • 서버 컴포넌트 (Server Components): 서버 컴포넌트를 활용해서 데이터를 서버에서 직접 가져오는 이점을 맘껏 누리세요.
  • 라우트 핸들러 (Route Handlers): 클라이언트 컴포넌트에서 백엔드 리소스에 접근할 때는 라우트 핸들러를 사용하세요. 하지만 서버 컴포넌트 안에서 또 라우트 핸들러를 호출하는 건 절대 피하셔야 해요! 불필요한 추가 서버 요청이 발생하거든요.

    💡 강사 팁: 이거 초보자분들이 정말 많이 하는 실수입니다. 서버 컴포넌트는 이미 서버 환경이기 때문에 API 엔드포인트를 fetch로 찌를 필요 없이, 데이터베이스 조회 함수나 백엔드 로직을 직접 호출하시면 됩니다.

  • 스트리밍 (Streaming): 데이터를 다 가져올 때까지 화면 전체가 멈춰있는(blocking) 현상을 막기 위해, 로딩 UI(loading.tsx)와 React Suspense를 활용해서 완성된 UI부터 서버에서 클라이언트로 점진적으로 보내주세요(Streaming).
  • 병렬 데이터 페칭 (Parallel Data Fetching): 데이터 요청들이 꼬리를 물고 기다리는 '네트워크 폭포(waterfalls)' 현상을 줄이기 위해 가능하면 데이터를 병렬로 동시에 가져오세요. 또, 필요한 경우 데이터 미리 가져오기 (preloading data) 패턴도 고려해 보세요.
  • 데이터 캐싱 (Data Caching): 내가 보낸 데이터 요청들이 제대로 캐싱되고 있는지 확인하고, 필요하다면 캐싱을 적용하세요. fetch 함수를 사용하지 않는 DB 쿼리 같은 요청들도 unstable_cache를 사용해서 캐싱할 수 있습니다.
  • 정적 이미지 (Static Images): public 디렉토리를 사용하면 이미지 같은 애플리케이션의 정적 에셋들을 자동으로 캐싱할 수 있어요.

UI 및 접근성 (UI and accessibility)

  • 폼 및 유효성 검사 (Forms and Validation): 폼 제출, 서버 측 유효성 검사, 에러 처리 등을 할 때는 '서버 액션(Server Actions)'을 사용하세요.
  • 글로벌 에러 UI (Global Error UI): app/global-error.tsx 파일을 추가하면, 앱 전체에서 잡히지 않은 최상위 에러가 발생했을 때 사용자에게 일관성 있고 접근성 좋은 폴백(fallback) UI와 복구 버튼을 제공할 수 있어요.
  • 글로벌 404 (Global 404): app/global-not-found.tsx 파일을 추가해서, 앱 전체에서 일치하는 라우트가 없을 때 띄워줄 접근성 좋은 404 페이지를 만드세요.
  • 폰트 모듈 (Font Module): 폰트를 사용할 땐 폰트 모듈(next/font)을 사용해 최적화하세요. 폰트 파일을 다른 정적 에셋들과 함께 자동으로 호스팅해주고, 외부 네트워크 요청을 없애주며, 텍스트가 늦게 뜨면서 화면이 밀리는 레이아웃 시프트(layout shift) 현상도 줄여줍니다.
  • <Image> 컴포넌트 (<Image> Component): 일반 <img> 태그 대신 <Image> 컴포넌트를 사용해 이미지를 최적화하세요. 이미지를 자동으로 최적화하고, 레이아웃 시프트를 막아주며, WebP 같은 최신 용량 절감 포맷으로 이미지를 제공해 줍니다.

    💡 강사 팁: <Image>를 쓸 때 레이아웃 시프트를 방지하려면 widthheight 값을 꼭 지정해 주거나, 부모 요소에 맞춰지는 fill 속성을 활용하셔야 해요. 외부 URL의 이미지를 쓸 땐 next.config.js에 해당 도메인을 등록해 주는 것도 절대 잊지 마세요!

  • <Script> 컴포넌트 (<Script> Component): 구글 애널리틱스 같은 서드파티 스크립트를 넣을 땐 <Script> 컴포넌트로 최적화하세요. 스크립트를 자동으로 지연시켜서 브라우저의 메인 스레드를 막지 않게 해줍니다.
  • ESLint: 내장된 eslint-plugin-jsx-a11y 플러그인을 활성화해서, 웹 접근성 문제를 개발 초기에 미리미리 잡아내세요.

보안 (Security)

  • Tainting (데이터 오염 방지): 특정 값이나 데이터 객체에 Taint(오염) 처리를 해서, 비밀번호나 개인정보 같은 민감한 데이터가 클라이언트 측에 실수로 노출되는 것을 원천 차단하세요.
  • 서버 액션 (Server Actions): 서버 액션을 호출하는 사용자가 권한이 있는 사용자인지(인가 처리) 꼭 확인해야 합니다. 권장되는 보안 관행들 (security practices)을 한번 검토해 보세요.
  • 환경 변수 (Environment Variables): .env.* 파일들은 무조건 .gitignore에 추가해서 깃허브에 올라가지 않도록 막고, 클라이언트(브라우저)에서 접근해야 하는 퍼블릭 변수에만 NEXT_PUBLIC_ 접두사를 붙이세요.

    💡 강사 팁: 이거 정말정말 중요한 팁입니다! 결제 API 시크릿 키나 DB 비밀번호 같은 것에 실수로 NEXT_PUBLIC_을 붙이면 브라우저 소스코드에 비밀번호가 그대로 노출됩니다. 무조건 서버에서만 쓸 변수에는 접두사를 붙이지 마세요!

  • 콘텐츠 보안 정책 (Content Security Policy): 크로스 사이트 스크립팅(XSS), 클릭재킹, 그 외 다양한 코드 인젝션 공격 같은 보안 위협으로부터 앱을 보호하기 위해 콘텐츠 보안 정책(CSP)을 추가하는 것을 고려해 보세요.

메타데이터 및 SEO (Metadata and SEO)

  • 메타데이터 API (Metadata API): 페이지 제목, 설명 등을 잘 설정해서 검색 엔진 최적화(SEO) 점수를 높여보세요. 메타데이터 API가 도와줄 거예요.
  • 오픈 그래프 (OG) 이미지 (Open Graph (OG) images): 카카오톡이나 트위터 같은 소셜 미디어에 링크를 공유했을 때 예쁘게 뜰 수 있도록 OG 이미지를 만들어 두세요.
  • 사이트맵 (Sitemaps)로봇 (Robots): 사이트맵 파일과 robots.txt 파일을 자동으로 생성해서 구글 같은 검색 엔진 봇들이 여러분의 페이지를 잘 긁어가고(크롤링) 색인(인덱싱)할 수 있도록 도와주세요.

타입 안정성 (Type safety)

  • TypeScript 및 TS 플러그인 (TS Plugin): TypeScript와 Next.js 전용 TypeScript 플러그인을 사용하세요. 타입 안정성을 대폭 높여주고 개발 도중에 에러를 빨리 찾아내게 해줍니다.

프로덕션 배포 전 (Before going to production)

실제 서비스로 배포하기 직전에, 터미널에서 next build 명령어를 실행해 로컬 환경에서 앱을 빌드해 보세요. 빌드 에러가 없는지 확실히 잡고 넘어갈 수 있습니다. 그 다음 next start 명령어로 실행하면, 실제 프로덕션과 거의 똑같은 환경에서 애플리케이션의 진짜 성능을 측정해 볼 수 있습니다. (개발 모드인 next dev 때보다 훨씬 빠르답니다!)

코어 웹 바이탈 (Core Web Vitals)

  • 라이트하우스 (Lighthouse): 크롬 브라우저를 '시크릿 모드'로 열고 라이트하우스 검사를 돌려보세요. 사용자들이 여러분의 사이트를 어떻게 경험할지 더 잘 이해할 수 있고, 어떤 부분을 개선해야 할지 힌트를 얻을 수 있습니다. 이건 시뮬레이션 테스트이므로 실제 사용자 데이터(Core Web Vitals 필드 데이터)와 함께 비교해서 보셔야 해요.

    💡 강사 팁: 왜 꼭 시크릿 모드에서 해야 할까요? 우리가 평소에 쓰는 크롬 확장프로그램(광고 차단기, 번역기 등)이 페이지 렌더링에 간섭해서 라이트하우스 점수를 깎아먹을 수 있거든요. 정확한 측정을 위해선 꼭 시크릿 모드로 켜주세요!

  • useReportWebVitals 훅 (useReportWebVitals hook): 이 훅을 사용하면 앱의 코어 웹 바이탈(Core Web Vitals) 지표 데이터를 수집해서 구글 애널리틱스 같은 분석 도구로 보낼 수 있습니다.

번들 분석하기 (Analyzing bundles)

프론트엔드 최적화의 꽃은 번들 다이어트죠! @next/bundle-analyzer 플러그인을 사용해서 여러분이 빌드한 JavaScript 번들의 크기를 시각적으로 분석해 보세요. 애플리케이션 성능을 깎아먹고 있는 용량 큰 모듈이나 외부 의존성(라이브러리)을 쉽게 찾아낼 수 있습니다.

💡 강사 팁: 이 애널라이저 화면을 띄워놓고 보면 정말 놀라실 거예요. "내가 쓰지도 않는 라이브러리가 이렇게 크게 들어가 있었다고?" 하면서 불필요한 코드를 덜어내는 재미가 쏠쏠합니다.

그 외에도, 프로젝트에 새로운 라이브러리(의존성)를 추가할 때 그게 앱 용량에 어떤 영향을 미칠지 미리 알려주는 유용한 도구들이 있어요. 한 번 활용해 보세요:


모든 공식 문서의 의미론적 개요(Semantic overview)를 보시려면, https://nextjs.org/docs/sitemap.md 를 참고해 주세요.

이용 가능한 모든 공식 문서의 전체 색인(Index)을 보시려면, https://nextjs.org/docs/llms.txt 를 참고해 주세요.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글