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 흐름
- 브라우저 요청 → Next.js 서버 수신
getServerSideProps실행 → 데이터 패칭- HTML 생성 + props 직렬화 → 브라우저 전달
- 브라우저에서 React 실행 (hydration)
- 필요 시
useEffect로 추가 데이터 패칭 → 화면 완성
App Router 흐름
- 브라우저 요청 → Next.js 서버 수신
- Server Component에서 React 실행 + 데이터 패칭
- HTML + RSC Payload 생성 → 브라우저 전달
- 브라우저는
'use client'컴포넌트만 선택적 hydration - 화면 완성 (추가 패칭 불필요)
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 실행을 어디서 할 것인가"다.