리액트 서버 컴포넌트는 컴포넌트의 렌더링 로직을 서버에서 수행하여 브라우저로 전송하는 기술로 이를 통해 클라이언트가 다운로드해야 할 자바스크립트 번들 크기를 획기적으로 줄이는 것이 가능.
반면, 클라이언트 컴포넌트는 브라우저에서의 상호작용(이벤트, 상태 관리)을 담당하는 전통적인 방식의 컴포넌트.
useEffect 등 라이프사이클 기능 활용에 사용.실제 프로젝트에서 두 컴포넌트를 분리하여 사용하는 구체적인 사례.
Next.js 앱 라우터 환경에서의 기본 설정 방식.
"use client" 지시어를 명시하여 클라이언트 측에서 실행될 것임을 선언.// 서버 컴포넌트 예시
async function ServerComponent() {
const data = await db.query(); // 서버 전용 로직 직접 실행 가능
return <div>{data.title}</div>;
}
// 클라이언트 컴포넌트 예시
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0); // Hook 사용 가능
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
개발자들이 흔히 겪는 시행착오와 해결 방안.
window, localStorage 등 브라우저 API를 직접 호출하는 오류 발생. 브라우저 전용 기능은 반드시 클라이언트 컴포넌트 내에서 사용 필요.import하여 렌더링 시도. 이 경우 서버 컴포넌트가 클라이언트 컴포넌트로 강제 변환되므로, children prop을 통한 구조적 주입 권장.핵심 요약
- 서버 컴포넌트 중심의 설계: 자바스크립트 번들 최소화 및 성능 향상을 위해 대부분을 서버 컴포넌트로 구성하고 인터랙션 부분만 클라이언트로 분리.
- 실행 환경의 명확한 구분: 서버 컴포넌트는 서버에서 1회 실행, 클라이언트 컴포넌트는 서버(사전 렌더링)와 브라우저(하이드레이션)에서 각각 실행됨을 인지.
- 데이터 직렬화 준수: 서버와 클라이언트 간의 데이터 전달 시 함수와 같은 비직렬화 데이터 전송 불가 및
children패턴을 활용한 컴포넌트 조합 필수.
출처: 한 입 크기로 잘라먹는 Next.js(v15)