Post

Next.js는 왜 서버 컴포넌트에서 데이터 호출을 권장할까?

Next.js 13 서버 컴포넌트

Next.js 13부터 app/ 디렉토리와 함께 등장한 서버 컴포넌트(Server Components)는 많은 변화를 가져왔습니다.

그 중 하나가 바로 데이터 패칭의 위치에 대한 새로운 권장 방식입니다.

타입설명
서버 컴포넌트 (.tsx, 기본)데이터 fetch, DB 접근, SEO에 적합
클라이언트 컴포넌트 (“use client”)상태 관리, 이벤트 핸들링 등 UI 상호작용 담당

✅ 왜 서버 컴포넌트에서 데이터를 불러오라고 할까? 서버에서 데이터를 불러오면 어떤 이점이 있을까요?

이유설명
보안API 키, DB 토큰 등 민감 정보는 서버에서만 사용 → 클라이언트에 노출되지 않음
성능서버에서 먼저 데이터를 준비해서 클라이언트에 렌더된 HTML로 제공 → 초기 로딩 빠름
SEO클라이언트에서 fetch하는 방식은 크롤러가 내용을 인식하기 어려움 → 서버 렌더가 유리
내장 캐싱 지원Next.js의 fetch는 revalidate, cache, no-store 등 다양한 캐싱 전략 내장
불필요한 JS 줄이기클라이언트에서 무거운 fetch 로직이 없어짐 → 번들 사이즈 감소


🔍 반대로 클라이언트에서 fetch할 경우 생기는 문제

  • 로딩 시간 증가 → 화면 진입 시 빈 UI → useEffect로 fetch → 느려짐

  • SEO 손실 → 화면은 비었는데 크롤러가 보는 건 JS 뿐

  • 보안 취약 → API 호출 시 인증 토큰/키가 클라이언트에 노출될 수 있음

  • 캐싱 어려움 → React Query 등의 라이브러리를 사용하더라도 Next.js의 fetch() 캐싱 전략은 활용 불가




React Query 데이터 패칭

React Query는 클라이언트에서 다음 역할을 해줍니다.

  • 캐시된 데이터를 빠르게 보여줌

  • 포커스 시 자동 리패치

  • 오류 처리, 로딩 상태 등 핸들링

  • 사용자 액션 기반 추가 fetch 처리 (검색, 필터 등)


1
2
3
4
5
6
7
8
9
10
// 서버 컴포넌트 (page.tsx)
const queryClient = new QueryClient();
await queryClient.prefetchQuery({ queryKey: ["interestZones"], queryFn: fetchZones });
const dehydratedState = dehydrate(queryClient);

return (
  <Hydrate state={dehydratedState}>
    <ClientComponent />
  </Hydrate>
);
1
2
3
// 클라이언트 컴포넌트
"use client";
const { data } = useQuery({ queryKey: ["interestZones"], queryFn: fetchZones });


이 구조는 서버에서 모든 필요한 데이터를 fetch 클라이언트 컴포넌트는 캐시만 사용 (useQuery + hydrate) 이다.


장점설명
서버 fetch보안, SEO, 초기 속도 모두 이득
클라이언트에서는 캐시 사용만추가 네트워크 요청 없음
React Query의 생태계 활용리패치, 캐시 시간, 오류 처리 등 그대로 사용 가능
CSR/SSR 유연하게 전환 가능prefetch 없는 경우엔 자동 클라이언트 fetch로 fallback




컴포넌트 단위 데이터 패칭 전략

1️⃣ 페이지 단위 데이터 패칭 (Page-level Fetching) 서버 컴포넌트에서 모든 필요한 데이터를 한꺼번에 불러오고 하위 컴포넌트에는 props로 전달하는 방식

🧩 적합한 상황

  • 초기 진입 시 반드시 필요한 데이터
  • SEO가 중요한 콘텐츠 (뉴스, 상세 페이지 등)
  • 서버 렌더링이 유리한 경우


2️⃣ 컴포넌트 단위 데이터 패칭 (Component-level Fetching) 클라이언트 컴포넌트에서 useQuery, useEffect 등을 통해 컴포넌트 내부에서 직접 데이터를 fetch

🧩 적합한 상황

  • 사용자 상호작용 이후 로딩되는 데이터 (예: 댓글, 필터)
  • modal / tab 내부 콘텐츠
  • 페이지와 무관한 유틸성 UI




정리해서 기억하면 좋은 기준

판단 기준fetch 위치
초기 진입 시 항상 필요함page.tsx 서버에서 prefetch + hydrate
특정 조건/행동 후 필요클라이언트 컴포넌트 내 fetch
SEO 중요 + 빠른 로딩 필요서버 fetch
사용자의 동적 행동 기반 데이터클라이언트 fetch
This post is licensed under CC BY 4.0 by the author.