Next.js는 풀스택 웹 애플리케이션을 만들기 위한 React 프레임워크다.
React만으로 SPA를 구성할 때 느꼈던 한계들을, 비교적 자연스럽게 보완해준다.

가장 먼저 체감되는 건 파일 시스템 기반 라우팅이다.
path.png 라우팅을 코드로 선언하지 않아도 되고, 폴더 구조 자체가 URL이 된다.

이 외에도 Next.js가 제공하는 핵심 기능들은 대부분
“렌더링과 데이터 흐름을 어떻게 제어할 것인가”에 집중되어 있다.

  • 렌더링 최적화
  • 데이터 fetch 및 캐싱 전략
  • 다양한 스타일링 방식 지원(CSS Modules, Tailwind, Sass, CSS-in-JS)
  • 이미지, 폰트, 스크립트 최적화
  • 메타데이터 API 제공(SEO)
  • TypeScript 기본 지원

App Router vs Page Router

Next.js에는 두 가지 라우팅 방식이 있다.

App Router

App Router는 React의 최신 기능을 전제로 설계되어 있다.
서버 컴포넌트, 스트리밍 같은 기능을 자연스럽게 사용할 수 있다.

렌더링 단위가 페이지가 아니라 컴포넌트로 쪼개지면서,
라우트 단위 제어보다 더 세밀한 렌더링 전략이 가능해졌다.

Page Router

Page Router는 초기 Next.js부터 사용되던 방식이다.
SSR, SSG 등 기존의 렌더링 패턴을 계속 지원한다.

이미 Page Router 기반으로 구성된 프로젝트라면
굳이 무리해서 App Router로 옮기지 않아도 된다.


서버 컴포넌트

서버 컴포넌트는 번들링 이전 단계에서,
클라이언트 앱이나 SSR 서버와는 분리된 환경에서 실행된다.

여기서 말하는 “서버”는

  • 빌드 타임에 CI 서버일 수도 있고
  • 요청마다 실행되는 웹 서버일 수도 있다

중요한 점은,
서버 컴포넌트는 클라이언트로 JavaScript 번들을 보내지 않는다는 것이다.

그래서 데이터 fetch나 민감한 로직을
클라이언트에 노출하지 않고 처리할 수 있다.


서버 컴포넌트 렌더링 흐름

서버 컴포넌트의 렌더링은 한 번에 끝나지 않는다.
라우팅 세그먼트와 Suspense 경계를 기준으로 청크 단위로 나뉘어 처리된다.

Server

  • React는 서버 컴포넌트 트리를
    RSC Payload라는 특수한 데이터 형태로 생성한다.
  • 이 Payload와 클라이언트 컴포넌트용 JavaScript instruction을 사용해
    HTML을 만든다.

Client

  • HTML을 즉시 화면에 표시한다
    (초기 진입이나 새로고침 시점)
  • RSC Payload를 기반으로
    서버/클라이언트 컴포넌트 트리를 reconcile 한다
  • 클라이언트 컴포넌트에 대해서만 hydrate가 수행된다

RSC Payload

RSC Payload는
렌더링된 서버 컴포넌트 트리를 표현한 경량 바이너리 데이터다.

이 안에는 다음 정보들이 포함된다.

  • 서버 컴포넌트의 렌더링 결과
  • 클라이언트 컴포넌트가 들어갈 위치 정보
  • 클라이언트 컴포넌트에 전달되는 props
  • 필요한 JavaScript 파일에 대한 참조

이 구조 덕분에
클라이언트는 전체 React 트리를 다시 만들지 않아도 된다.


렌더링 방식 정리

기본적인 렌더링 방식부터 정리해보면 다음과 같다.

CSR

  • 서버에서 HTML과 JS를 받는다
  • JS 실행 이후에 화면이 그려진다

SSR

  • 서버에서 HTML을 먼저 렌더링한다
  • 화면이 먼저 보이고, 이후 JS가 실행된다

Next.js의 서버 렌더링 전략

App Router 기준에서 기본값은 정적 렌더링(SSG) 이다.

정적 렌더링 (Static Rendering)

  • cookies, headers 같은 Dynamic API 사용 불가
  • 데이터 캐싱 가능
  • 빌드 타임 또는 revalidation 시점에 HTML 생성

동적 렌더링 (Dynamic Rendering)

  • 요청 시점마다 렌더링
  • revalidate 옵션을 주면 ISR 형태로 동작

Streaming

Page Router 시절에는 페이지 단위로 렌더링 방식을 정했지만,
App Router에서는 컴포넌트 단위로 스트리밍이 가능하다.

stream1.png stream2.png

렌더링 흐름은 대략 다음 순서다.

  1. 서버에서 페이지에 필요한 데이터 fetch
  2. HTML 렌더링
  3. HTML/CSS/JS 전송
  4. 비인터랙티브 UI 표시
  5. hydrate를 통해 인터랙션 활성화

stream3.png


캐싱

Next.js에는 네 가지 캐싱 메커니즘이 있다.

Next.js 14까지는 기본값이 on이었고,
15부터는 기본값이 off로 변경되었다.

  • Request Memoization (React)
  • Data Cache
  • Full Route Cache
  • Router Cache


cache1.png cache2.png

React Memoization

React의 기능이다.
동일한 요청에 대해 같은 결과를 재사용한다.

cache3.png

Data Cache

  • fetch API 확장 기능
  • 메모리 기반이 아니라 지속 캐시(persistent)

RSC Payload와 HTML 캐싱에 영향을 준다.

Full Route Cache

  • 정적으로 렌더링된 라우트에 적용
  • 빌드 타임 또는 revalidation 시점에 생성된다

Router Cache

  • 클라이언트 측 in-memory 캐시
  • 라우터 이동 시 재사용된다
chanhee.kim's profile image

chanhee.kim

2026-01-25 11:27

Read more posts by this author