일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 프로그래머스
- github
- 함수
- 메일 보내기 react
- nextjs contact us
- 카카오맵 api
- swiper
- 카카오지도 구현
- robots.txt
- 프론트 본인인증
- Til
- Next.js 나이스 본인인증
- JavaScript
- react swiper
- 구글 메일보내기
- 알고리즘
- React 나이스 신원인증
- nextjs
- 빈도수세기
- CSS
- 다중포인터
- react
- next15
- pass인증
- use Client
- nextjs 메일보내기
- 전체 너비로 css
- web3-react
- App Router
- 사이트맵
- Today
- Total
YEV.log
Next.js | App Router 와 Page Router 본문
2년 전쯤 생성한 프로젝트는 Next.js 13을 기반으로 한 page router를 사용하고 있었다.
이제 작은 프로젝트를 시작하려고 Next.js 15로 세팅했더니, 'use client'를 반드시 써야 한다는 등의 에러가..
이유는 App Router로 세팅되었기 때문이었다. 두개의 차이에 대해 알아보자
Page Router | App Router | |
사용가능 버전 | next.js 13 이하 | next.js 13.4 이상 (15에서 많이 개선됨) |
디렉토리 | pages/ | app/ |
라우팅 방식 | 파일 기반 (pages/about.txs -> /about) | 유연한 파일 기반 (pages/about/page.tsx -> /about) |
데이터 패칭 | - getStatidProps - getServerSideProps - getInitialProps |
- fetch() 기반 (React Server Components 사용) - async 컴포넌트에서 직접 데이터 패칭 가능 |
레이아웃 | - 중첩 레이아웃 구현이 복잡 - 클라이언트 컴포넌트와 서버 컴포넌트 분리가 어려움 |
- 중첩 레이아웃 쉽게 구성 가능 - 클라이언트 컴포넌트와 서버 컴포넌트 구분 ('use client') |
App Router 방식 폴더 구조 (app/)
app/
├─ layout.tsx ← 전체 사이트 공통 레이아웃 (헤더, 푸터 등)
├─ mypage/
│ ├─ layout.tsx ← mypage 전용 레이아웃 (좌측 메뉴 포함!)
│ ├─ page.tsx ← /mypage → 인덱스 페이지
│ ├─ orders/
│ │ └─ page.tsx ← /mypage/orders
│ └─ profile/
│ └─ page.tsx ← /mypage/profile
파일 정리
layout.tsx | 이 디렉토리 이하의 모든 route에서 공통 적용되는 레이아웃 |
page.tsx | 이 경로에 해당하는 페이지 본문 (실제 내용) |
loading.tsx | 로딩 중 보여줄 화면 |
error.tsx | 에러 났을 때 보여줄 화면 |
not-found.tsx | 404일 때 보여줄 화면 |
Page Router는 라우팅 파일만 /pages에 정의할 수 있어 공통 레이아웃 관리가 번거로웠지만
App Router는 /app 내에서 layout.tsx와 page.tsx를 함께 정의할 수 있어 구조가 더 직관적이라는 차이점이 있다.
서버 컴포넌트
Page Router에서는 페이지 단위에서 서버 데이터를 불러올 때, 아래 함수를 꼭 사용해주었어야 했다.
- getServerSideProps() : 서버에서 매 요청마다 데이터 불러오기
- getStaticProps() : 정적 페이지 생성용 (빌드 시점 데이터)
- getStaticPaths() : 동적 라우팅 시 정적 경로 지정
App Router 방식에서는
React Server Component + fetch()의 개선 덕분에 페이지뿐 아니라 서버 컴포넌트 단위에서도 서버 데이터를 직접 불러올 수 있게 되었다. (이게 개인적으로 가장 기존 방식의 불편함을 개선해준 부분이지 않을까 생각했다!)
// app/products/page.tsx (Server Component)
async function getProducts() {
const res = await fetch('https://api.example.com/products', { cache: 'no-store' })
return res.json()
}
export default async function ProductPage() {
const products = await getProducts()
return (
<div>
{products.map(p => <div key={p.id}>{p.name}</div>)}
</div>
)
}
App Router에서 쿼리와 파라미터 처리 방식
Page Router에서 쿼리, 파라미터 값을 서버 데이터로 받아오기 위해서는 getServerSideProps를 사용하여야 했고, 그걸 페이지 단위로 내려주어 사용했었다. App Router는 컴포넌트에서 직접 받을 수 있기 때문에 구조가 더 단순하고 유연해졌다.
쿼리
export default function MyPage({ searchParams }: { searchParams: { tab?: string } }) {
const tab = searchParams.tab || 'orders'
return <div>{tab === 'orders' ? '주문 탭' : '프로필 탭'}</div>
}
파라미터
export default function MyPage({ params }: { params: { userId: string } }) {
return <div>{params.userId}님의 마이페이지</div>
}
서버 컴포넌트 vs 클라이언트 컴포넌트
app router 에서 'use client'를 써야하는 이유는 서버 컴포넌트와 클라이언트 컴포넌트를 구분하였기 때문이다.
Page router에서는 클라이언트 컴포넌트와 서버 컴포넌트의 구분이 없었다. 모든 컴포넌트가 클라이언트 컴포넌트로 동작했었다.
- 서버에서 데이터 로딩은 getServerSideProps() 또는 getStaticProps()로 해결.
- 데이터가 서버에서 전달되니 후 클라이언트에서 렌더링이 시작되었다.
App Route방식은 서버 컴포넌트와 클라이언트 컴포넌트를 구분해서 사용하여야 한다.
- 클라이언트 컴포넌트는 'use client' 지시어를 상단에 명시적으로 선언해야한다.
- 서버 컴포넌트인 pages.tsx / layout.tsx 등에는 클라이언트에서 사용하는 useEffect, useState, window 를 사용할 수 없다.
이러한 차이가 필요한 이유는 성능 최적화가 용이하다는 점이다. 서버 컴포넌트는 서버에서 렌더링되므로, 클라이언트 측에 불필요한 JavaScript 코드가 전달되지 않게 되어 성능이 최적화된다. 또한, 서버 컴포넌트와 클라이언트 컴포넌트를 명확히 구분함으로써 각 컴포넌트의 역할이 분명해지고, 코드의 유지보수성이 높아지는 장점이 있다.
'Web > React & Next.js' 카테고리의 다른 글
React | Next.js 환경에서 나이스(PASS) 신원인증 구현하기 (0) | 2023.11.05 |
---|---|
React | 서버없이 메일 보내기 및 구글스프레드시트에 저장 (2) | 2023.06.07 |
React | Kakao Map Api를 사용하여 주소로 지도 그리기 (0) | 2023.05.14 |
Next.js 에서 Next/Image를 사용하여 이미지 처리하기 (0) | 2023.02.16 |
Next.js | Next.js + Styled-Components 초기 세팅 (next 13) (0) | 2023.02.14 |