Post

서버 컴포넌트 vs 클라이언트 컴포넌트

서버·클라이언트 컴포넌트 책임 분리, hydration 비용, 안티패턴과 실무 판단 기준

서버 컴포넌트 vs 클라이언트 컴포넌트

“어디서 실행되는가”가 아니라 “어디까지 책임지는가”

React Server Components(RSC)는 많은 혼란을 낳았다.
이유는 단순하다. 대부분이 이 개념을 물리적 서버/클라이언트 구분으로 이해하기 때문이다.

이 글의 핵심 전제는 다음이다.

서버 컴포넌트와 클라이언트 컴포넌트의 차이는
배포 위치가 아니라, 실행 책임과 비용 분리다.


1. 서버 컴포넌트의 본질

“서버에서 렌더링된다”는 말은 절반만 맞다

서버 컴포넌트의 본질은 다음 한 문장으로 요약된다.

브라우저로 전달되지 않아도 되는 React 컴포넌트

핵심 특성

  • 브라우저 JS 번들에 포함되지 않음
  • hydration 대상이 아님
  • 서버에서 실행되고 결과만 HTML/스트림으로 전달

즉, 서버 컴포넌트는

  • UI를 “보여주기”는 하지만
  • UI를 “관리”하지는 않는다

👉 서버 컴포넌트는 렌더링 전용 컴포넌트다.


흔한 오해 정리

❌ “서버 컴포넌트는 백엔드 코드다”
→ 아니다. React 컴포넌트이며 UI 트리를 구성한다.

❌ “서버 컴포넌트는 항상 SSR이다”
→ 아니다. SSG, 스트리밍, 캐시된 결과 모두 가능하다.

❌ “서버 컴포넌트는 느리다”
→ 오히려 클라이언트 JS 제거로 체감 성능은 개선된다.


2. 클라이언트 컴포넌트가 필요한 조건

“할 수 있어서”가 아니라 “불가피해서” 사용한다

NextJS App Router에서 기본값은 서버 컴포넌트다.
클라이언트 컴포넌트는 예외 케이스다.

클라이언트 컴포넌트가 필요한 경우

다음 중 하나라도 해당하면 필요하다.

  • 브라우저 전용 API 사용 (window, document 등)
  • 사용자 입력 처리
  • 이벤트 핸들러(onClick 등)
  • 클라이언트 상태(useState, useReducer)
  • useEffect 사용

이 조건은 모두 하나로 귀결된다.

렌더링 이후에도 UI가 스스로 변화해야 하는가?

YES → 클라이언트 컴포넌트
NO → 서버 컴포넌트


중요한 설계 원칙

클라이언트 컴포넌트는
UI 트리의 말단에 위치해야 한다

  • 상위는 서버 컴포넌트
  • 인터랙션이 필요한 최소 단위만 클라이언트

이 원칙을 어기면 비용이 폭증한다.


3. Hydration 비용과 렌더링 흐름

“보이는 것”과 “살아있는 것”의 차이

전통적인 React SPA 흐름

  1. 빈 HTML 수신
  2. JS 다운로드
  3. React 실행
  4. 전체 UI hydration

👉 모든 UI가 브라우저에서 살아난다


App Router + 서버 컴포넌트 흐름

  1. 서버에서 UI 트리 생성
  2. HTML + 스트리밍 전송
  3. 클라이언트 컴포넌트만 hydration

👉 살아야 할 것만 살아난다


Hydration 비용이란?

  • JS 파싱
  • 이벤트 바인딩
  • 상태 초기화

이 비용은:

  • 컴포넌트 수
  • 트리 깊이
  • 상태 복잡도

에 비례한다.

서버 컴포넌트는 이 비용을 근본적으로 제거한다.


4. 남용 사례와 안티패턴

안티패턴 1: 'use client'를 상단에 붙이고 시작

  • “나중에 생각하자”는 접근
  • 결과: 전체 트리 클라이언트화
  • 서버 컴포넌트 이점 소멸

안티패턴 2: 서버 데이터를 클라이언트 상태로 재포장

  • 서버 캐시 무력화
  • 중복 fetch
  • 불필요한 리렌더링

안티패턴 3: 서버 컴포넌트에서 클라이언트 로직 흉내

  • 불필요한 분기
  • 책임 혼재
  • 가독성 저하

5. 실무 판단 기준 체크리스트

컴포넌트를 작성하기 전, 아래 질문을 순서대로 던져라.

  1. 이 컴포넌트는 렌더링 이후에도 변해야 하는가?
  2. 브라우저 API가 필요한가?
  3. 사용자 입력을 직접 다루는가?
  4. 상태가 없다면 서버에서 끝낼 수 있는가?
  5. 이 컴포넌트를 클라이언트로 만들면
    상위 컴포넌트까지 전염되지 않는가?

5번에서 YES라면, 설계가 잘못됐다.


결론: 서버 컴포넌트는 “최적화 기법”이 아니다

서버 컴포넌트는 성능 트릭이 아니다.

  • 실행 책임 분리
  • 비용 위치 이동
  • UI의 생명주기 단순화

이를 통해 NextJS는
React 애플리케이션을 ‘운영 가능한 구조’로 만든다.

서버 컴포넌트를 잘 쓴다는 것은
React를 덜 쓰는 것이 아니라,
React를 정확히 쓰는 것이다.


This post is licensed under CC BY 4.0 by the author.