리액트 생태계에서 최근 몇 년간 가장 큰 패러다임의 변화를 꼽으라면 단연 **서버 컴포넌트(Server Components)**입니다. Next.js 13부터 도입된 App Router의 기반이기도 한 RSC는, 컴포넌트가 실행되는 위치를 '서버'로 옮김으로써 프론트엔드 개발의 새로운 지평을 열었습니다.
기존의 SSR(Server-Side Rendering)과는 무엇이 다른지, 왜 우리가 RSC를 공부해야 하는지 깊이 있게 다뤄보겠습니다.
1. 🌐 서버 컴포넌트(RSC)란 무엇인가?
말 그대로 서버에서만 실행되는 리액트 컴포넌트입니다. 렌더링 결과물이 브라우저로 전달될 때, 자바스크립트 번들 파일이 아닌 '정적인 결과값(JSON과 유사한 형태)'으로 전달됩니다.
- Client Components: 기존에 우리가 쓰던 컴포넌트입니다. 브라우저에서 실행되며, useState, useEffect 같은 인터랙션이 가능합니다.
- Server Components: 서버에서 실행됩니다. DB에 직접 접근하거나 파일 시스템을 읽을 수 있으며, 브라우저로 전송되는 자바스크립트 양을 획기적으로 줄여줍니다.
2. 🚀 RSC가 해결하는 문제 (장점)
2-1. 제로 번들 사이즈 (Zero Bundle Size)
서버 컴포넌트에서 사용하는 라이브러리(예: date-fns, lucide-react)는 브라우저로 다운로드되지 않습니다. 서버에서 이미 계산이 끝났기 때문입니다. 이는 페이지 로딩 속도를 비약적으로 높여줍니다.
2-2. 백엔드 리소스에 직접 접근
컴포넌트 내부에서 async/await를 사용하여 데이터베이스(DB)나 API에 직접 접근할 수 있습니다. 더 이상 클라이언트에서 데이터를 가져오기 위해 복잡한 useEffect나 API 엔드포인트를 만들지 않아도 됩니다.
// 서버 컴포넌트 예시
async function ProductList() {
const products = await db.product.findMany(); // DB 직접 접근 가능!
return (
<ul>
{products.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
);
}
2-3. 워터폴(Waterfall) 현상 제거
데이터 페칭이 서버에서 이루어지므로, 클라이언트와 서버 간의 왕복 시간(Round-trip)이 줄어듭니다. 여러 개의 중첩된 컴포넌트가 각각 데이터를 호출하더라도 서버 내부 네트워크망에서 빠르게 처리됩니다.
3. ⚖️ SSR(서버 사이드 렌더링)과 무엇이 다른가요?
많은 분이 혼동하는 부분입니다. RSC는 SSR의 대체제가 아니라 상호 보완적인 관계입니다.
| 구분 | SSR (Server-Side Rendering) | RSC (Server Components) |
| 목적 | 초기 HTML을 빠르게 보여줌 (FCP 최적화) | 번들 크기 감소 및 서버 리소스 활용 |
| 결과물 | HTML 문자열 | 특수한 직렬화된 데이터 포맷 |
| 상태 유지 | 하이드레이션(Hydration) 후 상태 초기화 | 클라이언트 상태를 유지하며 부분 업데이트 가능 |
4. 🛠️ 언제 무엇을 써야 할까?
Next.js 환경에서는 기본적으로 모든 컴포넌트가 서버 컴포넌트입니다. 인터랙션이 필요한 경우에만 클라이언트 컴포넌트로 전환합니다.
- 서버 컴포넌트: 데이터 페칭, 보안 민감한 정보(API 키 등) 사용, 큰 라이브러리 사용 시.
- 클라이언트 컴포넌트: useState, useReducer, useEffect 사용, 브라우저 API(window, localStorage) 접근, 이벤트 리스너(onClick 등) 추가 시.
💡 시니어의 조언: "서버 컴포넌트는 최대한 크게, 클라이언트 컴포넌트는 최대한 작게(말단 노드로)" 설계하는 것이 성능 최적화의 핵심입니다.
'개발 > React' 카테고리의 다른 글
| [고급반] Step 4-2. 클린 아키텍처: 관심사 분리와 계층 설계 (0) | 2025.12.23 |
|---|---|
| [고급반] Step 4-1. 테스트와 안정성: Jest와 RTL로 견고한 컴포넌트 만들기 (0) | 2025.12.23 |
| [고급반] Step 3-2. Suspense와 Error Boundary: 선언적 비동기 처리 아키텍처 (0) | 2025.12.23 |
| [고급반] Step 3-1. Concurrent React: useTransition과 useDeferredValue (0) | 2025.12.23 |
| [고급반] Step 2-3. Headless UI 패턴: 스타일에서 독립된 로직의 힘 (0) | 2025.12.23 |