Ch 02. 서버에서만 실행된다는 것 — RSC의 동작 원리
두 가지를 동시에 보내는 서버
Next.js가 페이지를 응답할 때 두 가지를 함께 보냅니다. HTML과 RSC 페이로드입니다.
HTML은 브라우저가 즉시 화면을 그릴 수 있게 해줍니다. 자바스크립트가 실행되기 전에도 내용이 보입니다.
RSC 페이로드(React Server Component Payload)는 리액트가 브라우저에서 트리를 재구성하기 위한 데이터입니다. JSON과 유사한 형태로, 서버 컴포넌트가 렌더링한 결과물을 담고 있습니다.
RSC 페이로드란
RSC 페이로드는 서버에서 컴포넌트를 실행한 결과를 직렬화한 것입니다. 브라우저의 리액트는 이 데이터를 받아, 자신이 가진 클라이언트 컴포넌트 코드와 결합해 전체 UI 트리를 만듭니다.
이 과정을 하이드레이션(Hydration)이라고 합니다. 물기 없는 HTML에 물(인터랙티비티)을 붓는 것에 빗댄 표현입니다.
[서버]1. Server Component 실행2. HTML 생성3. RSC 페이로드 생성 (Server Component 결과 직렬화)[브라우저]1. HTML 수신 → 즉시 화면 표시2. JS 번들 다운로드3. RSC 페이로드 수신4. 하이드레이션 → 클릭, 입력 등 상호작용 활성화
console.log는 어디에 출력되나
이 질문이 Server Component를 이해하는 좋은 방법입니다.
// 파일: app/page.tsx
export default function HomePage() {
console.log('이 로그는 어디에 찍힐까요?');
return <h1>안녕하세요</h1>;
}
```text
답은 **서버 터미널**입니다. 브라우저 콘솔에는 아무것도 나타나지 않습니다. Server Component이기 때문에 이 코드는 서버에서 실행됩니다. `npm run dev`를 실행한 터미널 창에서 로그를 볼 수 있습니다.
반면 Client Component에서의 `console.log`는 브라우저 콘솔에 출력됩니다.
```tsx
// 파일: app/components/Counter.tsx
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
console.log('현재 카운트:', count); // 브라우저 콘솔에 출력
return (
<button onClick={() => setCount((c) => c + 1)}>
클릭: {count}
</button>
);
}
이 차이를 인식하는 것만으로도 디버깅이 훨씬 쉬워집니다.
Server Component는 다시 실행되지 않는다
Client Component는 상태가 바뀌면 다시 렌더링됩니다. useState로 값이 바뀌면 컴포넌트 함수가 다시 호출됩니다.
Server Component는 다릅니다. 최초 요청 시에 서버에서 한 번 실행되고, 그 결과가 클라이언트로 전달됩니다. 이후에는 다시 실행되지 않습니다.
Server Component에서 데이터를 바꾸려면, 서버에 새 요청을 보내야 합니다. 링크를 클릭하거나, 폼을 제출하거나, Server Action을 호출하는 방식으로요. 리액트 상태(useState)로 Server Component를 업데이트할 방법은 없습니다.
실제로 어떻게 보이나
개발자 도구의 네트워크 탭을 열고 Next.js 페이지에 접속해보면, 페이지 응답 외에 _next/... 경로로 RSC 페이로드가 요청되는 것을 볼 수 있습니다. 특히 클라이언트 사이드 내비게이션을 할 때 (링크를 클릭할 때) RSC 페이로드 요청이 발생합니다.
이 페이로드의 내용을 직접 볼 필요는 없지만, "아, 서버에서 이런 데이터를 만들어서 보내주는구나"라고 이해하면 충분합니다.
다음 챕터에서는
다음 챕터에서는 서버와 클라이언트의 경계를 직접 만드는 방법, "use client" 선언을 살펴봅니다. 어떤 상황에서 Client Component가 필요하고, Server Component 안에 Client Component를 어떻게 넣는지 알아봅니다.