export default function Page() {
// 1. 불러온 데이터를 보관할 State 생성
const [state, setState] = useState(null);
// 2. 데이터 페칭 함수 생성
const fetchData = async () => {
const response = await fetch("/api");
const data = await response.json();
setState(data);
};
// 3. 컴포넌트 마운트 시점에 데이터 페칭 함수 호출
useEffect(() => {
fetchData();
}, []);
// 4. 데이터 로딩 중일 때 예외 처리
if (!state) return <p>Loading...</p>;
return <div>{JSON.stringify(state)}</div>;
}
React의 CSR 방식에서는 데이터 페칭이 컴포넌트 마운트 이후 (useEffect) 발생
따라서 사용자는 FCP 이후에도 데이터 로딩을 기다려야 한다.
❌ 데이터 요청 시점이 느리다 (컴포넌트 마운트 이후)
❌ SEO 최적화가 어렵다 → HTML이 먼저 로드되고, JavaScript 실행 후 데이터를 가져오기 때문에 검색 엔진이 크롤링하기 어려움
export async function getServerSideProps() {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
return { props: { data } }; // 데이터를 props로 전달
}
export default function Page({ data }) {
return <div>{JSON.stringify(data)}</div>;
}
Next의 사전 렌더링 방식에서는 데이터 페칭이 완료된 상태로 화면을 렌더링한다.
✔️ 데이터 요청 시점이 빠르다 → 서버에서 데이터가 포함된 상태로 렌더링된 HTML 생성
데이터 페칭 : 사전 렌더링 중 발생 (컴포넌트 마운트 이후에도 발생 가능)
✔️ SEO 최적화 가능 → 검색 엔진이 완전한 HTML을 가져갈 수 있음
❌ 요청할 때마다 서버에서 데이터 가져옴 → 서버 부하가 클 수 있음
export async function getStaticProps() {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
return { props: { data } };
}
export default function Page({ data }) {
return <div>{JSON.stringify(data)}</div>;
}
용량 큰 이미지가 많은 것처럼, 렌더링이 오래 걸릴 것으로 예상되는 경우에는 FCP가 오히려 CSR보다 늦어질 수 있다.
이러한 상황을 방지하기 위해 빌드 타임에 일부 페이지들을 렌더링 하도록 설정할 수 있다.
빌드 시 데이터를 미리 가져와 정적 페이지를 생성한다.
✔️ 빌드 타임에 데이터를 가져와 HTML을 생성
✔️ SEO 최적화 + 빠른 속도 → 정적 파일이므로 CDN에서 빠르게 제공 가능
❌ 실시간 데이터 반영 어려움 → 데이터가 바뀌면 다시 빌드해야 함
❌ 사용자별 정보 제공이 어려움 → 사용자가 만 명인 경우, 그만큼의 정적 파일들을 미리 렌더링해야 하므로 서버 부하가 심함
export async function getStaticProps() {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
return {
props: { data },
revalidate: 60, // 60초마다 데이터 갱신
};
}
SSG의 단점을 보완하여 일부 데이터만 갱신한다.
✔️ 정적 페이지지만 일정 주기로 새 데이터 반영 가능
✔️ SSG처럼 빠르면서도, 최신 데이터 유지 가능
❌ 완벽한 실시간 업데이트는 어려움
| React (CSR) | Next.js (SSR) | Next.js (SSG) | Next.js (ISR) | |
|---|---|---|---|---|
| 렌더링 시점 | 클라이언트에서 실행 | 요청 시 서버에서 실행 | 빌드 시 미리 생성 | 빌드 후 일정 시간마다 갱신 |
| 속도 | 느림 (데이터 페칭 이후 렌더링) | 중간 (서버 처리 후 응답) | 매우 빠름 (정적 페이지 제공) | 빠름 (CDN + 정적 페이지 업데이트) |
| SEO | ❌ (JavaScript 실행 후 데이터 가져옴) | ✅ (서버에서 HTML 생성) | ✅✅ (완전한 정적 HTML 제공) | ✅ (SEO 유지 + 최신 데이터) |
| 최신 데이터 반영 | 즉시 가능 | 즉시 가능 | 불가능 (빌드해야 반영) | 일정 주기로 자동 갱신 |
| 서버 부담 | 없음 (클라이언트에서 처리) | 높음 (요청마다 서버 렌더링) | 낮음 (정적 파일 제공) | 낮음 (정적 파일 제공 + 재생성) |
→ 로그인한 사용자 정보, 실시간 검색 결과, 뉴스 기사
→ 블로그, 문서 페이지, 제품 소개 페이지
→ 뉴스 사이트, 커머스 사이트 (상품 정보 갱신)
→ 대시보드, 관리 페이지, 내부 시스템