둘의 큰 차이점은 어디에서 렌더링이 일어나는가에 따라 달라집니다.
우선 클라이언트 사이드 렌더링(CSR)의 경우에는 우리가 사용하는 기본 리액트의 렌더링 기법입니다.
브라우저는 서버로부터 HTML과 자바스크립트 파일을 받고 난 후에 클라이언트, 즉 유저가 직접 렌더링하는 방식입니다.
장점이라면 페이지 이동 속도가 빠르고 서버의 부담을 줄일 수 있다는 것입니다.비유하자면 밀키트라고 보시면 됩니다.
고객이 재료를 모두 집으로 가져와서 요리해서 먹어야 합니다.
미리 조리되기까지 기다리지 않고 집으로 바로 가져올 수 있다는 장점과, 요리사가 따로 일하지 않아도 된다는 장점이 있습니다.반면에 서버 사이드 렌더링(SSR)은 말 그대로 서버에서 미리 렌더링을 한 뒤에 완성된 페이지를 클라이언트에게 전송하는 기법입니다.
리액트 기반 프레임워크인 Next.js의 가장 큰 장점이기도 합니다.
서버 사이드 렌더링의 장점은 클라이언트 사이드 렌더링에서 지원하기 어려웠던 SEO에 유리하다는 점입니다.이러한 특징은 배달 음식에 비유할 수 있습니다.
고객은 이미 완성된 음식을 받아서 바로 먹을 수 있습니다.
그러면 요리를 못하는 사람은 음식을 조리할 필요 없이 그 자리에서 먹으면 됩니다.이어서 서버 사이드 렌더링이 SEO에 유리한 이유는 바로 검색 엔진의 크롤링 기술에 있습니다.
클라이언트 사이드 렌더링은 브라우저 개발자 도구의 네트워크 탭에 가보시면 초기에 브라우저에서 내려주는 화면이 전혀 없습니다.
"자바스크립트가 필요합니다"와 같은 문구만이 나와있을 뿐입니다.
왜냐하면 클라이언트가 필요한 파일을 다운받아 직접 렌더링하기 때문입니다.
그러나 크롤링 도구는 이러한 파일을 모두 다운받을 수는 있어도 직접 렌더링하지는 못합니다.반면에 서버 사이드 렌더링의 경우에는 개발자 도구의 네트워크 탭에 가보면 완성된 페이지를 다운받아오기 때문에 검색 엔진 크롤링 도구는 이러한 완성된 페이지를 받아 크롤링을 실행해 SEO에 좀 더 유리하게 됩니다.
사용자가 페이지에 처음 들어오면
➡️ 화면 생성 책임이 클라이언트(브라우저) 쪽에 있다.
"use client" 컴포넌트에서 useEffect로 fetch한다.
클라이언트 훅(useState, useEffect)을 적극 활용한다.
예제
"use client";
import { useEffect, useState } from "react";
export default function PostsPage() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch("/api/posts")
.then((res) => res.json())
.then(setPosts);
}, []);
return (
<main>
{posts.map((p) => (
<div key={p.id}>{p.title}</div>
))}
</main>
);
}
➡️ HTML은 거의 빈 상태로 내려가고, 브라우저에서 JS가 실행된 후 내용이 채워진다.
사용자가 페이지에 들어오면
➡️ 첫 화면 렌더링을 서버에서 미리 해둔다.
기본이 서버 컴포넌트라서, RSC(React Server Component) + 서버에서 fetch하는 것이 사실상 SSR과 비슷한 위치이다.
// app/posts/page.tsx (서버 컴포넌트)
export default async function PostsPage() {
const res = await fetch("https://example.com/api/posts", {
cache: "no-store", // 매 요청마다 새로
});
const posts = await res.json();
return (
<main>
{posts.map((p: any) => (
<div key={p.id}>{p.title}</div>
))}
</main>
);
}
➡️ 여기서 만들어진 HTML이 서버에서 렌더링되어 내려오고, 필요할 경우 그 아래에 클라이언트 컴포넌트를 섞어서 인터랙션을 붙인다.
실전에서는
이렇게 섞는 패턴이 제일 많다.
| 기준 | CSR | SSR |
|---|---|---|
| 어디에서 HTML을 만드는가? | 브라우저에서 JS가 실행된 후 DOM 생성 | 서버에서 리액트 렌더링으로 HTML 생성 |
| 첫 화면 표시 시점 | JS 다운로드/실행 + 데이터 fetch 후에야 완성된 화면 | HTML 수신 직후 내용이 바로 보임 |
| SEO | JS 의존 ➡️ 검색엔진이 JS 실행 못 하면 불리 | HTML에 내용이 포함 ➡️ SEO 유리 |
| TTFB | 서버는 정적 파일만 주면 되므로 상대적으로 짧을 수 있음 | 서버가 렌더링 후 보내야 해서 TTFB가 길어질 수 있음 |
| FCP/사용자 체감 | JS와 데이터 로딩이 늦으면 빈 화면/로딩이 길어질 수 있음 | 콘텐츠는 바로 뜨고, 이후 JS 로딩 동안도 읽기는 가능함 |
| 서버 부하 | 적음 (렌더링은 클라이언트) | 큼 (요청마다 렌더링) |
| 캐싱 | JS 번들은 정적으로 CDN 캐싱 | 사용자별/요청별 데이터 섞이므로 캐싱 전략 고민 필요 |
| 개인화 | 클라이언트에서 토큰/스토리지 기반으로 개인화 적용 용이 | 가능하지만, 쿠키/세션 기반으로 서버에서 처리해야 함 |
| 구현 난이도 | SPA와 비슷, 브라우저 위주 사고 | 데이터 fetching, 캐싱, SEO, 서버 성능까지 같이 고려해야 함 |