이는 대부분의 컴포넌트가 서버에서 렌더링되고, 작은 인터랙티브 UI 요소만 클라이언트에서 렌더링 되는 방식입니다.
그리고 이 작은 인터랙티브 UI요소들을 클라이언트 컴포넌트라고 지칭할 수 있습니다.
클라이언트 컴포넌트는 클라이언트 측에서 렌더링되는 컴포넌트입니다.
이 컴포넌트는 사용자와의 상호작용을 담당하며, 애플리케이션의 인터랙티브한 부분을 담당합니다.
클라이언트 컴포넌트는 Next.js와 같은 프레임워크에서의 서버에서 사전 렌더링되고 클라리언트에서 Hydrate되어 초기 렌더링 성능을 개선할 수 있습니다.
(Hydrate : Server Side 단에서 렌더링 된 정적 페이지와 번들링된 JS파일을 클라이언트에게 보낸 뒤, 클라이언트 단에서 HTML 코드와 React인 JS코드를 서로 매칭 시키는 과정을 말한다)
nextjs.org
여기서 헷갈릴 수 있는 부분이 있습니다.
바로 서버 컴포넌트와 서버 사이드 렌더링(SSR)입니다.
서버 컴포넌트와 서버 사이드 렌더링은 서버에서 렌더링 되다는 유사점이 있지만 해결하고자 하는 문제점이 다릅니다.
서버 컴포넌트의 코드는 클라이언트로 전달되지 않습니다. 하지만 서버 사이드 렌더링(SSR)의 모든 컴포넌트의 코드는 자바스크립트 번들에 포함되어 클라이언트로 전송됩니다.
서버 컴포넌트는 페이지 레벨에 상관없이 모든 컴포넌트에서 서버에 접근 가능합니다. 하지만 Next.js의 경우 가장 top level의 페이지에서만 getServerProps()나 getInitialProps()로 서버에 접근 가능합니다.
서버 컴포넌트는 클라이언트 상태를 유지하며 refetch 될수 있습니다. 서버 컴포넌트는 HTML이 아닌 특별한 형태로 컴포넌트를 전달하기 때문에 필요한 경우 포커스, 인풋 입력값 같은 클라이언트 상태를 유지하며 여러 번 데이터를 가져오고 리렌더링하여 전달할 수 있다. 하지만 서버 사이드 렌더링(SSR)의 경우 HTML로 전달되기 때문에 새로운 refetch가 필요한 경우 HTML 전체를 리렌더링 해야 하며 이로 인해 클라리언트 상태를 유지할 수 없습니다.
서버 컴포넌트는 서버 사이드 렌더링(SSR) 대체가 아닌 보완의 수단으로 사용할 수 있습니다. 서버 사이드 렌더링(SSR)으로 초기 HTML 페이지를 빠르게 보여주고, 서버 컴포넌트로는 클라이언트로 전송되는 자바스크립트 번들 사이즈를 감소시킨다면 사용자에게 기존보다 훨씬 빠르게 인터렉팅한 페이지를 제공할 수 있을 것이다.
이전에는 클라이언트의 자바스크립트 번들 크기에 영향을 주었던 큰 종속성들을 완전히 서버에 유지할 수 있으므로 성능이 향상된다. 이로써 React 애플리케이션 개발은 PHP나 Ruby on Rails와 유사한 느낌을 준다. 여기에 더해 React의 강력함과 유연성, 그리고 컴포넌트 기반 UI 템플릿 모델을 함께 제공한다.
2. 초기 페이지 로드 속도 증가 및 클라이언트 측 자바스크립트 번들 크기 감소
base client-side 런타임이 cacheable해지며 크기도 예측 가능하다. 이는 애플리케이션이 규모가 커져도 증가하지 않는다.
3. Next.js로 라우트가 로드되면 초기 HTML이 서버에서 렌더링된다. 그런 다음 HTML은 브라우저에서 점진적으로 향상되어 클라이언트가 Next.js 및 React 클라이언트 측 런타임을 비동기식으로 로드하여 애플리케이션을 인계하고 상호 작용을 추가할 수 있다.
4. 서버 컴포넌트로 전환을 쉽게하기 위해 App Router 내의 모든 컴포넌트는 기본적으로 서버 컴포넌트로 지정된다.
이는 특수 파일과 함께 위치한 컴포넌트를 포함하여 자동으로 적용할 수 있게 해주며, 추가 작업 없이 탁월한 성능을 얻을 수 있게 한다.
또한 'use client' 지시문을 사용하여 필요에 따라 클라이언트 컴포넌트로 전환할 수도 있다.
서버 컴포넌트가 새로운 개념이기 때문에, `third-party packages`은 `useState`, `useEffect`, `createContext`와 같은 클라이언트 전용 기능을 사용하는 컴포넌트에 `"use client"`지시문을 추가하기 시작했습니다.
현재, 클라이언트 전용 기능을 사용하는 많은 `npm` 패키지의 컴포넌트는 아직 해당 지시문이 없다.
이러한 third-party 컴포넌트들은 자체적으로 `"use client"` 지시문이 있으므로 내부의 클라이언트 컴포넌트에서는 예상대로 작동하지만, 서버 컴포넌트 내에서는 작동하지 않을 것이다.
예를 들어보자
만약 클라이언트 컴포넌트 안에서 `<AcmeCarouse />`을 사용한다고 해보자
예상대로 잘 작동할 것이다.
'use client';
import { useState } from'react';
import { AcmeCarousel } from'acme-carousel';
exportdefaultfunctionGallery() {
let [isOpen, setIsOpen] = useState(false);
return (
<div><buttononClick={() => setIsOpen(true)}>View pictures</button>
{/* 🟢 Works, since AcmeCarousel is used within a Client Component */}
{isOpen && <AcmeCarousel />}
</div>
);
}
그러나 만약 서버 컴포넌트 내에서 직접 사용하려고 하면 오류가 발생한다.
import { AcmeCarousel } from'acme-carousel';
exportdefaultfunctionPage() {
return (
<div><p>View pictures</p>
{/* 🔴 Error: `useState` can not be used within Server Components */}
<AcmeCarousel /></div>
);
}
이는 Next.js가 <AcmeCarouse/>이 클라이언트 전용 기능을 사용한다는 것을 알지 못하기 때문이다.
이를 해결하기 위해 클라이언트 전용 기능에 의존하는 third-party 컴포넌트를 자체적인 클라리언트 컴포넌트로 감싸주면 된다.
이는 대부분의 컴포넌트가 서버에서 렌더링되고, 작은 인터랙티브 UI 요소만 클라이언트에서 렌더링 되는 방식입니다.
그리고 이 작은 인터랙티브 UI요소들을 클라이언트 컴포넌트라고 지칭할 수 있습니다.
클라이언트 컴포넌트는 클라이언트 측에서 렌더링되는 컴포넌트입니다.
이 컴포넌트는 사용자와의 상호작용을 담당하며, 애플리케이션의 인터랙티브한 부분을 담당합니다.
클라이언트 컴포넌트는 Next.js와 같은 프레임워크에서의 서버에서 사전 렌더링되고 클라리언트에서 Hydrate되어 초기 렌더링 성능을 개선할 수 있습니다.
(Hydrate : Server Side 단에서 렌더링 된 정적 페이지와 번들링된 JS파일을 클라이언트에게 보낸 뒤, 클라이언트 단에서 HTML 코드와 React인 JS코드를 서로 매칭 시키는 과정을 말한다)
nextjs.org
여기서 헷갈릴 수 있는 부분이 있습니다.
바로 서버 컴포넌트와 서버 사이드 렌더링(SSR)입니다.
서버 컴포넌트와 서버 사이드 렌더링은 서버에서 렌더링 되다는 유사점이 있지만 해결하고자 하는 문제점이 다릅니다.
서버 컴포넌트의 코드는 클라이언트로 전달되지 않습니다. 하지만 서버 사이드 렌더링(SSR)의 모든 컴포넌트의 코드는 자바스크립트 번들에 포함되어 클라이언트로 전송됩니다.
서버 컴포넌트는 페이지 레벨에 상관없이 모든 컴포넌트에서 서버에 접근 가능합니다. 하지만 Next.js의 경우 가장 top level의 페이지에서만 getServerProps()나 getInitialProps()로 서버에 접근 가능합니다.
서버 컴포넌트는 클라이언트 상태를 유지하며 refetch 될수 있습니다. 서버 컴포넌트는 HTML이 아닌 특별한 형태로 컴포넌트를 전달하기 때문에 필요한 경우 포커스, 인풋 입력값 같은 클라이언트 상태를 유지하며 여러 번 데이터를 가져오고 리렌더링하여 전달할 수 있다. 하지만 서버 사이드 렌더링(SSR)의 경우 HTML로 전달되기 때문에 새로운 refetch가 필요한 경우 HTML 전체를 리렌더링 해야 하며 이로 인해 클라리언트 상태를 유지할 수 없습니다.
서버 컴포넌트는 서버 사이드 렌더링(SSR) 대체가 아닌 보완의 수단으로 사용할 수 있습니다. 서버 사이드 렌더링(SSR)으로 초기 HTML 페이지를 빠르게 보여주고, 서버 컴포넌트로는 클라이언트로 전송되는 자바스크립트 번들 사이즈를 감소시킨다면 사용자에게 기존보다 훨씬 빠르게 인터렉팅한 페이지를 제공할 수 있을 것이다.
이전에는 클라이언트의 자바스크립트 번들 크기에 영향을 주었던 큰 종속성들을 완전히 서버에 유지할 수 있으므로 성능이 향상된다. 이로써 React 애플리케이션 개발은 PHP나 Ruby on Rails와 유사한 느낌을 준다. 여기에 더해 React의 강력함과 유연성, 그리고 컴포넌트 기반 UI 템플릿 모델을 함께 제공한다.
2. 초기 페이지 로드 속도 증가 및 클라이언트 측 자바스크립트 번들 크기 감소
base client-side 런타임이 cacheable해지며 크기도 예측 가능하다. 이는 애플리케이션이 규모가 커져도 증가하지 않는다.
3. Next.js로 라우트가 로드되면 초기 HTML이 서버에서 렌더링된다. 그런 다음 HTML은 브라우저에서 점진적으로 향상되어 클라이언트가 Next.js 및 React 클라이언트 측 런타임을 비동기식으로 로드하여 애플리케이션을 인계하고 상호 작용을 추가할 수 있다.
4. 서버 컴포넌트로 전환을 쉽게하기 위해 App Router 내의 모든 컴포넌트는 기본적으로 서버 컴포넌트로 지정된다.
이는 특수 파일과 함께 위치한 컴포넌트를 포함하여 자동으로 적용할 수 있게 해주며, 추가 작업 없이 탁월한 성능을 얻을 수 있게 한다.
또한 'use client' 지시문을 사용하여 필요에 따라 클라이언트 컴포넌트로 전환할 수도 있다.