Archive.sakamoto
Next.jsRenderingArchitecture

Page Router vs App Router

Page Router와 App Router의 렌더링 모델 차이와 각각 어떤 상황에서 선택해야 하는지 알아보자!

Sakamoto·

1. 핵심 개념

Page Router

  • 브라우저(클라이언트) 중심 React 렌더링 모델
  • 서버는 HTML과 props를 만들어주는 보조 역할
  • React 실행의 주체는 브라우저

App Router

  • 서버 중심 React 렌더링 모델
  • React가 서버에서 먼저 실행됨
  • HTML + RSC Payload를 내려주고 클라이언트는 이어받아서 hydration

2. 왜 이렇게 설계하는가

Page Router는 React가 항상 브라우저에서 실행되는 구조라, 서버는 데이터를 props로 내려주는 보조 역할에 그쳤다. 이 구조는 단순하지만 JS 번들 전체를 클라이언트로 내려야 하고, 데이터 패칭 시점이 늦어지는 문제가 있었다.

App Router는 React 자체를 서버에서 실행시켜 이 문제를 구조적으로 해결했다. 서버에서 데이터를 먼저 가져오고 HTML을 완성한 뒤 클라이언트로 내려주기 때문에, 초기 로딩 속도와 번들 사이즈 모두 개선된다.

💡 면접 tip

"Page Router와 App Router의 차이가 뭔가요?" 질문엔 단순히 폴더 구조나 파일명 차이가 아니라, "React 실행 위치가 브라우저에서 서버로 이동한 렌더링 모델의 패러다임 전환"이라고 설명하면 된다.


3. 사용 원리 (코드 실행 흐름)

Page Router

// pages/posts/[id].tsx
 
// [입력] 요청 수신 → 서버에서 데이터 패칭
export const getServerSideProps = async () => {
  const data = await fetchPost();
  // [처리] 서버는 데이터를 props로 변환
  return { props: { data } };
};
 
// [출력] 브라우저에서 React 실행 → 렌더링
const Page = ({ data }) => {
  return <div>{data.title}</div>;
};
  • React 컴포넌트는 항상 클라이언트 실행
  • 서버는 props 전달만 담당

App Router

// app/posts/[id]/page.tsx
 
// [입력] 요청 수신
const Page = async () => {
  // [처리] 서버 컴포넌트에서 React 직접 실행 + 데이터 패칭
  const data = await fetchPost();
  // [출력] HTML + RSC Payload 생성 → 클라이언트 전달
  return <Client data={data} />;
};
  • React 자체가 서버에서 실행
  • 클라이언트는 필요한 컴포넌트만 hydration

4. 데이터 흐름 (입력 → 처리 → 출력)

Page Router 흐름

  1. 브라우저 요청 → Next.js 서버 수신
  2. getServerSideProps 실행 → 데이터 패칭
  3. HTML 생성 + props 직렬화 → 브라우저 전달
  4. 브라우저에서 React 실행 (hydration)
  5. 필요 시 useEffect 로 추가 데이터 패칭 → 화면 완성

App Router 흐름

  1. 브라우저 요청 → Next.js 서버 수신
  2. Server Component에서 React 실행 + 데이터 패칭
  3. HTML + RSC Payload 생성 → 브라우저 전달
  4. 브라우저는 'use client' 컴포넌트만 선택적 hydration
  5. 화면 완성 (추가 패칭 불필요)

5. 주요 차이점 비교

구분 Page Router App Router
React 실행 위치 브라우저 서버 + 브라우저
기본 렌더링 CSR SSR
데이터 패칭 getServerSideProps / CSR 컴포넌트 내부 (async/await)
클라이언트 선언 기본 'use client' 필요
레이아웃 _app.tsx layout.tsx
로딩/에러 처리 상태 처리 파일 기반 (loading.tsx, error.tsx)

6. 실무 사용 패턴

Page Router를 선택하는 경우

  • 기존 레거시 프로젝트 유지보수
  • 팀이 App Router 학습 비용을 감당하기 어려운 경우
  • 단순한 CSR 위주 서비스

App Router를 선택하는 경우

  • 신규 프로젝트
  • SEO + 초기 로딩 성능이 중요한 서비스
  • 서버/클라이언트 렌더링 전략을 세밀하게 컨트롤해야 하는 경우

🔧 실무 point

실무에서는 App Router 기준으로 "이 컴포넌트가 서버에서 실행돼야 하나, 클라이언트에서 실행돼야 하나"를 먼저 판단하는 습관이 중요하다. 기본값이 Server Component이므로, 'use client'는 꼭 필요한 최소 단위에만 붙이는 것이 원칙이다.


7. 자주 하는 실수 / 주의사항

잘못된 방법: App Router에서 데이터 패칭을 여전히 useEffect 로 처리

'use client';
 
export default function Page() {
  const [data, setData] = useState(null);
  
  // ❌ 클라이언트에서 패칭 → 번들 증가 + 패칭 시점 늦어짐
  useEffect(() => {
    fetch('/api/data').then(res => res.json()).then(setData);
  }, []);
}

올바른 방법: Server Component에서 직접 패칭

// ✅ 서버에서 직접 패칭 → 번들 미포함 + 초기 렌더에 데이터 포함
export default async function Page() {
  const data = await fetchData();
  return <div>{data.title}</div>;
}

🔎 이유: App Router에서 useEffect 패칭은 클라이언트 번들 증가 + 데이터 패칭 시점이 늦어지는 문제가 생긴다. Server Component에서 직접 패칭하면 번들에 포함되지 않고 서버에서 바로 실행된다.


8. 한 줄 요약

Page Router는 React를 브라우저에서 실행하고 서버는 데이터 전달만 담당하는 클라이언트 중심 모델이다.

App Router는 React가 서버에서 먼저 실행되어 HTML과 RSC Payload를 생성한 뒤 필요한 부분만 클라이언트가 hydration하는 서버 중심 모델이다.

선택 기준은 "React 실행을 어디서 할 것인가"다.