React

[react-router] CSR, SSR, loader, HydrationBoundary (framwork)

hyriver(강화영) 2026. 8. 7. 16:14

 

SSR / CSR / loader 정리

1. 서버와 브라우저

브라우저 — 사용자 개인의 노트북, 핸드폰에서 도는 것. 사람마다 각자 있음
서버 — 모든 사용자의 요청을 받는 Node 프로세스

개발 중   내 컴퓨터: Node 프로세스(서버) + 크롬(브라우저)  ← 한 기계
배포 후   AWS: Node 프로세스 / 사용자 기기: 크롬

 

터미널은 컴퓨터가 아니라 프로세스의 출력을 보여주는 창. npm run dev로 띄운 Node 프로세스가 서버 역할을 하고, 그게 출력한 글자가 터미널에 나옴.

 

loader는 서버에서 돌기 때문에 console.log가 터미널에만 찍힘.


2. CSR vs SSR

컴포넌트 함수를 어디서 실행하느냐의 차이.

  CSR SSR
서버에서 실행 ✅ 서버에서 실행 후 HTML 생성
브라우저에서 실행 ✅ DOM 생성 ✅ 검증 + 이벤트 연결
총 실행 1번 2번
서버가 보내는 것 <div id="root"></div> 내용이 채워진 HTML

 

SSR에서 두 번째 실행이 하이드레이션. 화면을 새로 그리는 게 아니라 이미 있는 DOM에 이벤트와 상태를 붙이는 작업.

 

여기서 나오는 차이

CSR — 하이드레이션 불일치가 없음. new Date(), Math.random(), window 자유롭게 사용 가능

SSR — 두 실행 결과가 같아야 함. 다르면 경고, 심하면 React가 서버 HTML을 버리고 다시 그림(SSR 이점 소멸). 서버에는 window가 없어서 방어 필요

useEffect(() => {
  const w = window.innerWidth;  // useEffect는 브라우저에서만 실행
}, []);

3. HydrationBoundary

역할

서버 캐시를 브라우저 캐시로 옮기는 것.

서버와 브라우저는 다른 메모리라서 QueryClient도 각자 존재함. loader가 서버 쪽을 채워도 useQuery는 브라우저 쪽만 보기 때문에 "데이터 없네" 하고 다시 요청함.

단절을 잇는 방법

  • dehydrate — 서버 캐시를 JSON으로 변환
  • HydrationBoundary — 그 JSON을 브라우저 캐시에 넣어줌

전체 흐름

1. 서버에서 QueryClient 생성      ← 요청마다 새로 만들어야 함
2. ensureQueryData로 API 호출
3. dehydrate로 JSON 변환
4. HTML에 실어 전송
5. HydrationBoundary가 브라우저 QueryClient에 부어줌

언제 필요 없나

loader만 사용 ❌ useLoaderData로 끝
loader + React Query ✅ 두 시스템을 잇는 다리
React Query만 사용 ❌ 브라우저에서 가져오니 옮길 게 없음

 

useQuery는 useLoaderData를 안 봄. 자기 캐시만 봄. 그래서 다리가 필요한 것.

// loader만 쓰면 이게 끝
export async function loader() {
  return { influencers: await getInfluencerList() };
}

export default function Home() {
  const { influencers } = useLoaderData();
  return <InfluencerList items={influencers} />;
}

4. loader를 쓰는 이유

  1. SEO — 서버가 데이터까지 채운 HTML을 보내니 크롤러가 읽을 수 있음
  2. 하이드레이션 깜빡임 방지 — 캐시를 안 넘기면 목록이 보였다가 사라졌다가 다시 나타남

그럼 왜 굳이 useQuery까지 쓰나

useLoaderData가 더 간단한데도 쓰는 이유:

  1. 프로젝트가 React Query 기반이라 일관성
  2. 다른 페이지에서도 같은 요청을 쓰므로 캐시 공유

useLoaderData는 라우트에 종속돼서 다른 페이지와 캐시를 공유하지 못함. React Query는 queryKey 기준이라 라우트와 무관하게 재사용됨.


5. SSR 확인 방법

Cmd + Option + U (맥) 또는 우클릭 → 페이지 소스 보기 → Cmd + F로 검색

  • SSR로 그린 데이터 → 나옴
  • CSR로 가져온 데이터 → 안 나옴

CSR 데이터는 브라우저가 JS를 실행한 뒤 DOM에 들어가는데, 소스 보기는 서버가 보낸 원본 HTML만 보여주기 때문. 크롤러가 보는 것도 이 화면.

 


한 줄 요약

컴포넌트 함수를 서버에서 실행하면 SSR,
브라우저에서만 실행하면 CSR이고,
loader는 서버에서 데이터를 미리 가져오는 역할,
HydrationBoundary는 그 데이터를 브라우저 캐시로 옮기는 다리다