[Next.js] 리액트 서버 컴포넌트

Melcoding·2026년 1월 4일

Next.js

목록 보기
11/27

개념 설명: 서버 컴포넌트와 클라이언트 컴포넌트

리액트 서버 컴포넌트는 컴포넌트의 렌더링 로직을 서버에서 수행하여 브라우저로 전송하는 기술로 이를 통해 클라이언트가 다운로드해야 할 자바스크립트 번들 크기를 획기적으로 줄이는 것이 가능.
반면, 클라이언트 컴포넌트는 브라우저에서의 상호작용(이벤트, 상태 관리)을 담당하는 전통적인 방식의 컴포넌트.

  • 서버 컴포넌트: 서버에서만 실행되며, 데이터베이스 직접 접근이나 보안이 필요한 로직 처리에 적합.
  • 클라이언트 컴포넌트: 브라우저에서 실행되며, 버튼 클릭, 입력 폼 처리, useEffect 등 라이프사이클 기능 활용에 사용.

사용 상황 예시

실제 프로젝트에서 두 컴포넌트를 분리하여 사용하는 구체적인 사례.

  • 서버 컴포넌트 활용: 데이터베이스에서 포스트 목록을 불러오거나, 외부 API로부터 정적인 데이터를 호출하여 화면을 구성할 때 주로 사용.
  • 클라이언트 컴포넌트 활용: 게시글의 '좋아요' 버튼, 검색창의 실시간 입력 값 처리, 모달 창 열고 닫기 등 사용자 액션이 필요한 UI에 적합.
  • 하이브리드 구성: 페이지 전체 레이아웃과 데이터 로딩은 서버 컴포넌트로 처리하고, 그 내부의 세부적인 인터랙션 요소만 클라이언트 컴포넌트로 배치하는 방식이 권장.

기본 문법

Next.js 앱 라우터 환경에서의 기본 설정 방식.

  • 서버 컴포넌트 (Default): 별도의 지시어 없이 작성된 모든 컴포넌트는 기본적으로 서버 컴포넌트로 동작.
  • 클라이언트 컴포넌트 선언: 파일 최상단에 "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을 통한 구조적 주입 권장.
  • 직렬화 불가능한 Props 전달: 서버에서 클라이언트로 함수(Function)나 클래스 인스턴스를 Props로 전달할 때 에러 발생. 네트워크 전송을 위해 반드시 JSON으로 변환 가능한 데이터(문자열, 숫자, 단순 객체 등)만 전달 가능.

핵심 요약

  • 서버 컴포넌트 중심의 설계: 자바스크립트 번들 최소화 및 성능 향상을 위해 대부분을 서버 컴포넌트로 구성하고 인터랙션 부분만 클라이언트로 분리.
  • 실행 환경의 명확한 구분: 서버 컴포넌트는 서버에서 1회 실행, 클라이언트 컴포넌트는 서버(사전 렌더링)와 브라우저(하이드레이션)에서 각각 실행됨을 인지.
  • 데이터 직렬화 준수: 서버와 클라이언트 간의 데이터 전달 시 함수와 같은 비직렬화 데이터 전송 불가 및 children 패턴을 활용한 컴포넌트 조합 필수.

출처: 한 입 크기로 잘라먹는 Next.js(v15)

0개의 댓글