클라이언트 컴포넌트와 서버 컴포넌트의 동작 원리 분석

derek·2024년 10월 11일
1

Next.js 13버전부터 클라이언트 컴포넌트와 서버 컴포넌트라는 개념이 도입되었다.

우리는 종종 하이브리드 방식으로 한 페이지에서 서버 컴포넌트와 클라이언트 컴포넌트를 함께 사용하는데, 빌드 시 이들이 어떻게 생성되고 동작하는지 궁금해서 간단한 테스트를 진행했다.

우선 큰 틀은 그대로 유지하면서, 서버 컴포넌트를 아래와 같이 작성했다:

// app/page.tsx
import Counter from "@/components/Counter";
import os from "os";

export default function Home() {
  console.log("Server Component!!");
  console.log(os.hostname());
  return (
    <>
      <h1>Home</h1>
      <Counter />
    </>
  );
}

그 다음, Counter라는 클라이언트 컴포넌트를 아래와 같이 만들어서 임포트했다:

// component/Counter.tsx
"use client";

import React from "react";

export default function Counter() {
  console.log("Client Component!!");


  const [count, setCount] = React.useState(0);

  return (
    <>
      <button onClick={() => setCount((num) => num + 1)}>+</button>
      <div>{count}</div>
    </>
  );
}

  1. 빌드를 진행하니 최적화가 완료되고 컴파일 및 린팅이 끝났다는 메시지가 나타났다
  2. 어떤 페이지를 정적으로 생성할 수 있을지 확인했고, 서버 컴포넌트뿐만 아니라 클라이언트 컴포넌트도 실행된 것을 확인할 수 있었다

왜 클라이언트 컴포넌트인데도 서버에서 실행되었을까? 이 의문이 생겨 yarn start로 실행해보았다

네트워크 탭에서 서버로부터 어떤 파일들이 전송되는지 살펴보니, 처음 받아온 정적 HTML에 우리가 만든 Counter 클라이언트 컴포넌트도 포함되어 있었다

이로써 "클라이언트 컴포넌트"라는 말은 단순히 클라이언트 사이드 렌더링을 의미하는 것이 아니라, 사용자의 클릭과 같은 이벤트를 처리하는 코드가 브라우저에서 실행되어야 한다는 의미라는 것을 알 수 있었다

정리하자면, 빌드 시점에 Next.js가 우리의 페이지를 검사하면서 클라이언트 컴포넌트를 발견하면, 정적으로 생성할 수 있는 요소들을 확인하고 HTML로 변환한다. 그래서 클라이언트 컴포넌트에서 작성한 console.log가 실행되었고, 이후 클릭과 같은 이벤트 처리를 위해 하이드레이션이 이루어진다는 것을 알 수 있었다.

마지막으로, 정말 React 컴포넌트인지 확인해보려면 Chrome Extension인 React Components에서는 상태(state)를 갖춘 가장 하위의 Counter 컴포넌트를 확인할 수 있습니다:

profile
derek

0개의 댓글