RSC (React Server Component)
- RSC는 React Server Component의 줄임말입니다.
- 서버 컴포넌트라고 불리며, 이는 React 18부터 도입된 개념으로, 컴포넌트를 서버에서 렌더링하고 그 결과를 클라이언트로 전달합니다.
- 서버 컴포넌트의 특징:예를 들어, 서버 컴포넌트는 데이터베이스와의 통신, API 호출 등을 통해 데이터를 가져와 클라이언트에게 미리 HTML 형태로 전달할 수 있습니다. 이 과정에서 브라우저에 불필요한 JavaScript가 줄어들기 때문에 초기 로딩 속도를 개선할 수 있습니다.
- 클라이언트로 전달할 HTML을 서버에서 미리 생성합니다. 이는 서버의 리소스를 활용해서 클라이언트의 부담을 줄이는 데 도움이 됩니다.
- 서버 컴포넌트에서는 상태 관리 훅(useState, useEffect 등)을 사용할 수 없으며, 브라우저 전용 API도 사용할 수 없습니다. 대신 데이터를 가져오거나, 백엔드와 직접 통신하는 작업에 적합합니다.
- 일반적으로 비동기 데이터 로딩에 용이하고, 초기 페이지 로딩 성능을 개선하는 데 도움이 됩니다.
RCC (React Client Component)
- RCC는 React Client Component의 줄임말입니다.
- 클라이언트 컴포넌트라고 불리며, 기존에 우리가 흔히 사용하던 방식의 React 컴포넌트를 의미합니다.
- 클라이언트 컴포넌트의 특징:
- 브라우저에서 실행되며, 사용자와의 상호작용을 처리하기 위한 이벤트 핸들러(onClick, onChange 등)를 사용합니다.
- 상태 관리(useState, useEffect 등) 및 브라우저 API (localStorage, window 등)를 활용할 수 있습니다.
- 클라이언트 컴포넌트는 'use client' 지시어를 사용해 명시할 수 있으며, 이를 통해 명확하게 클라이언트에서 렌더링해야 하는 컴포넌트임을 나타냅니다.
클라이언트 컴포넌트는 사용자가 클릭하거나 스크롤하는 등 상호작용을 다룰 수 있어야 하는 UI 부분에 주로 사용됩니다. 브라우저와의 상호작용이 필요한 컴포넌트들은 클라이언트 컴포넌트로 작성됩니다.
RSC와 RCC의 차이점
- 렌더링 위치:
- RSC: 서버에서 렌더링합니다. 이 컴포넌트는 데이터 처리를 서버 측에서 수행하고, 클라이언트에 결과만 보내줍니다.
- RCC: 브라우저에서 렌더링합니다. 클라이언트에서 사용자와의 상호작용을 처리합니다.
- 상태 및 이벤트 처리:
- RSC: 상태나 이벤트 처리 관련 훅(useState, useEffect)을 사용할 수 없습니다.
- RCC: 상태 관리와 이벤트 처리를 위해 여러 가지 React 훅을 사용할 수 있습니다.
- 사용 예:
- RSC: 백엔드와 통신하는 데이터 로딩, 초기 렌더링에서 복잡한 JavaScript 계산을 서버에서 처리하고 싶을 때.
- RCC: 사용자의 입력, 버튼 클릭, 상호작용 등 클라이언트 쪽에서 사용자 경험을 개선하는 데 사용.
예시 코드
아래는 두 종류의 컴포넌트를 비교한 간단한 예시입니다.
React Server Component (RSC):
// 서버 컴포넌트
export default async function ServerComponent() {
const data = await fetchData();// 서버에서 데이터를 가져옴
return (
<div>
<h1>서버에서 데이터를 렌더링합니다.</h1>
<p>{data}</p>
</div>
);
}
React Client Component (RCC):
'use client';
import { useState } from 'react';
// 클라이언트 컴포넌트
export default function ClientComponent() {
const [count, setCount] = useState(0);
return (
<div>
<h1>클라이언트에서 카운터를 사용합니다.</h1>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
</div>
);
}
이렇게 RSC와 RCC는 각각 서버와 클라이언트에서 수행하는 역할에 맞게 사용됩니다. 서버에서 미리 데이터를 준비해 최적화된 HTML을 제공하거나 클라이언트 측에서 필요한 상호작용을 다룰 수 있도록 컴포넌트를 구분함으로써 전체 웹 애플리케이션의 성능을 개선하는 데 큰 도움이 됩니다.
Server Component vs Client Component
- 데이터 가져오기 (Fetch data)
- 서버 컴포넌트: 가능 (✅)
- 클라이언트 컴포넌트: 불가능 (❌)
- 백엔드 리소스에 직접 접근하기 (Access backend resources directly)
- 서버 컴포넌트: 가능 (✅)
- 클라이언트 컴포넌트: 불가능 (❌)
- 서버에서 민감한 정보 유지하기 (Access tokens, API keys 등)
- 서버 컴포넌트: 가능 (✅)
- 클라이언트 컴포넌트: 불가능 (❌)
- 서버에서 큰 종속성 유지하기 / 클라이언트 측 자바스크립트 줄이기 (Keep large dependencies on the server / Reduce client-side JavaScript)
- 서버 컴포넌트: 가능 (✅)
- 클라이언트 컴포넌트: 불가능 (❌)
- 상호작용 추가 및 이벤트 리스너 추가 (Add interactivity and event listeners, 예: onClick(), onChange() 등)
- 서버 컴포넌트: 불가능 (❌)
- 클라이언트 컴포넌트: 가능 (✅)
- 상태와 생명주기 효과 사용 (Use State and Lifecycle Effects, 예: useState(), useReducer(), useEffect() 등)
- 서버 컴포넌트: 불가능 (❌)
- 클라이언트 컴포넌트: 가능 (✅)
- 브라우저 전용 API 사용 (Use browser-only APIs)
- 서버 컴포넌트: 불가능 (❌)
- 클라이언트 컴포넌트: 가능 (✅)
- 상태, 효과, 브라우저 전용 API에 의존하는 커스텀 훅 사용 (Use custom hooks that depend on state, effects, or browser-only APIs)
- 서버 컴포넌트: 불가능 (❌)
- 클라이언트 컴포넌트: 가능 (✅)
- React 클래스 컴포넌트 사용 (Use React Class components)
- 서버 컴포넌트: 불가능 (❌)
- 클라이언트 컴포넌트: 가능 (✅)
use client
코드 예제 설명
이미지에는 두 개의 TypeScript 파일 (**app/page.tsx**와 app/gallery.tsx)의 코드가 나타나 있는데, 아래에 각각을 설명해 보겠습니다.
첫 번째 코드 (app/page.tsx)
- import { Carousel } from 'acme-carousel';
- Carousel 컴포넌트를 가져옵니다. 이 컴포넌트는 클라이언트에서 렌더링해야 하는 UI 요소입니다.
- 함수 컴포넌트 Page 정의
- 이 컴포넌트는 서버 컴포넌트로 사용되며, 상태 관리 로직이 사용되지 않았습니다.
- 여기서 중요한 점은 서버 컴포넌트는 React의 상태나 생명주기 훅을 사용할 수 없다는 것입니다. 예를 들어 useState 같은 훅을 사용할 경우 오류가 발생하게 됩니다.
- 따라서 클라이언트 전용 상호작용이 필요한 컴포넌트 (Carousel 같은)를 서버 컴포넌트에서 직접 사용하려고 하면 오류가 발생합니다.
- export default function Page() { return ( <div> <p>View pictures</p> {/* 오류: useState는 서버 컴포넌트 내에서 사용될 수 없음 */} <Carousel /> </div> ); }
두 번째 코드 (app/gallery.tsx)
- 'use client' 지시문 추가
- 파일의 최상단에 **'use client'**를 추가하여 이 컴포넌트가 클라이언트 컴포넌트로 동작하도록 명시합니다.
- 이를 통해 클라이언트 측에서만 실행되어야 하는 훅(useState)을 사용할 수 있습니다.
- 'use client';
- 클라이언트 전용 컴포넌트 구현
- useState 사용: useState(false)를 사용하여 상태(isOpen)를 관리합니다. 이 상태는 버튼 클릭에 따라 변화합니다.
- <button onClick={() => setIsOpen(true)}>View pictures</button>: 버튼 클릭 시 상태가 변경되어 **isOpen**이 **true**로 설정됩니다.
- 조건부 렌더링: 상태에 따라 <Carousel /> 컴포넌트가 렌더링됩니다.
- 'use client' 지시문이 있기 때문에 **useState**와 같은 훅을 사용할 수 있고, 사용자와의 상호작용도 클라이언트 측에서 처리할 수 있습니다.
- import { useState } from 'react'; import { Carousel } from 'acme-carousel'; export default function Gallery() { let [isOpen, setIsOpen] = useState(false); return ( <div> <button onClick={() => setIsOpen(true)}>View pictures</button> {/* 클라이언트 컴포넌트에서 Carousel 사용 가능 */} {isOpen && <Carousel />} </div> ); }
결론
- 서버 컴포넌트는 데이터를 가져오거나 서버와 관련된 처리를 담당할 수 있지만, 클라이언트 측 상태 관리나 브라우저 전용 API를 사용할 수 없습니다.
- 클라이언트 컴포넌트로 명시하려면 최상단에 'use client' 지시문을 추가해야 합니다. 이를 통해 React의 상태와 같은 클라이언트 측에서만 필요한 기능들을 사용할 수 있습니다.
- 클라이언트 컴포넌트는 브라우저와의 상호작용이 필요한 경우, 상태 관리 훅이나 이벤트 핸들러 등을 자유롭게 사용할 수 있습니다.
'NextJS' 카테고리의 다른 글
NextJS Hook정리 (1) | 2024.11.30 |
---|