프론트엔드

[Next JS] 슬기롭게 서버 컴포넌트 사용하기 1 - 서버 컴포넌트란?

CandDoIt 2025. 2. 20. 01:13

 

리액트 서버 컴포넌트(React Server Component)란?

서버 컴포넌트는 번들링 전에 클라이언트 앱이나 SSR 서버와 분리된 환경에서 미리 렌더링되는 새로운 유형의 컴포넌트입니다.

출처: https://ko.react.dev/reference/rsc/server-components

 

프론트엔드 개발자가 서버 컴포넌트를 적극적으로 사용해야 하는이유

1. 빠릅니다

리액트는 현재 프론트엔드 개발자들이 가장 많이 사용하는 라이브러리입니다.

함수형 프로그래밍 지원 및  리액트 hook 등의 다양한 기능으로 리액트는 많은 사랑을 받고있습니다.

하지만 리액트가 가진 큰 단점은 렌더링 속도 문제였습니다. 리액트 팀은 렌더링 속도 문제를 계속 고민했고, 이를 해결하기 위해 서버 컴포넌트를 출시했습니다.

 

2. Next JS

리액트 기반 프레임워크 Next JS가 현재 급 부상하면서 이제는 프론트엔드 개발자들이 필수적으로 배워야할 기술 스택이되었습니다.

Next JS는 서버사이드를 지원하는 프레임워크로 서버사이드렌더링을 기본적으로 지원합니다. Next JS에서 모든 컴포넌트들은 기본적으로 RSC 방식으로 동작하며 기존의 클라이언트 컴포넌트를 사용하려면 'use client' 지시어를 사용해야합니다. 이제 리액트는 단순히 라이브러리일뿐 현재 프론트엔드 생태계에서 가장 많이 선호되고 사용되는 Next JS를 배우는 개발자라면 RSC에대한 이해와 사용법을 알아야합니다.

 

동작 방식

1. 클라이언트 컴포넌트

사용자가 웹 페이지에 접속할 때 먼저 빈 HTML을 응답값으로 보내줍니다. 그 후, 브라우저에서 자바스크립트 번들을 다운받고 렌더링을 해줬습니다. API요청이 있을 경우 useEffect hook을 사용하여 다시한번 렌더링 해줘야 했죠.

 

2. 서버 컴포넌트

사용자가 웹 페이지에 접속할 때 서버에서 api 요청과 HTML 생성을 한번에 처리합니다. 사용자가 웹페이지에 접속했을 때 서버에서 바로 데이터까지 패칭된 완성된 HTML을 브라우저에 내려줍니다. 사용자는 자신이 사용하는 기기의 성능과 상관없이, 온전한 화면을 서버에서 바로 받아 볼 수 있습니다.

 

💡 서버에서 완성된 HTML을 내려주나, 클라이언트에서 JS 번들을 다운받나 큰 차이가 있을까요?

프론트엔드 개발자들은 저사양 PC에서도 고사양 PC와 균일한 품질의 서비스를 제공하고 싶어합니다. 모든 개발자가 그렇지 않지만 적어도 사용자의 경험을 중요하게 생각하는 개발자에게는 틀린 말은 아닙니다. 클라이언트(브라우저)에서 JS 번들을 다운받게되면 기기의 성능에따라 제공하는 서비스의 품질이 달라질 수 있습니다. 서버에서 빈 HTML을 받고 JS 번들을 다운 받는 간극이 발생합니다. 이후에 렌더링되는 시간때문에 사용자는 데이터를 빠르게 볼 수 없습니다. 심지어 api요청을 보내야 할 때 기존에는 useEffect를 사용해 렌더링 후 API 요청을 보냈습니다. 하지만 서버 컴포넌트는 api 서버에서 데이터를 불러오고 모든 데이터를 반영한 최종 HTML을 내려줍니다. 이러한 차이는 코드에서도 가장 명확히 드러나는데요. 다음과 같이 api 요청을 보내는 함수가 있다고 가정해봅시다.

function async fetchData ():Promise<APIResponse>{
  // api 요청을 보내는 로직
  return data
}

Next js 클라이언트 컴포넌트에서는 늘 그래왔던 것 처럼 당연하게 코드를 작성합니다.

'use client'
function Page(){
  const [data, setData] = useState<APIResponse|null>(null);
  useEffect(()=>{
    fetchData.then((response)=>{setData(response);})
  },[])
	
  return (
  <div>{data}<div>
  )
}

useState()와 useEffect()는 리액트의 강력한 훅입니다. 상태관리와 외부시스템과 연결(api fetching)을 쉽게 하도록 도와줍니다.

하지만, 해당 페이지에서 데이터를 조회하는 일 밖에 없는데 더 최적화할 수 있는 방법이 있을까요? 바로 서버 컴포넌트를 사용하면 됩니다!

function async Page(){
  const response = await fetchData();
	
  return (<div>{response.data}<div>)
}

같은 페이지를 렌더링하는데,서버 컴포넌트가 훨씬 간결하게 작성된 코드에 렌더링 속도도 빠른 것을 볼 수 있습니다.

 

💡 그렇다면 이제 클라이언트 컴포넌트를 사용하지 않아도 되는건가요?

아니요. 서버 컴포넌트를 렌더링하는 모든 과정은 waterfall 방식으로 진행됩니다. 서버에서 데이터 쿼리, HTML 그리기 등 모든 과정이 순차적으로 진행되고 브라우저에는 그냥 HTML을 내려줍니다. 이 말은 즉, JS 번들이 없는 HTML입니다. 그래서 서버 컴포넌트에서 CRUD 중 R인 "Read"만 가능합니다. 상호작용이 불가능하죠.

 

그렇다면 우리는 그냥 볼 수 밖에 없는 페이지로 만들어야 할까요? 아닙니다. 현대 애플리케이션에는 보다 복잡한 서비스를 제공하기 때문에 상호작용이 가능한 기능은 필수입니다. 다음 포스팅에서는 서버 컴포넌트를 보다 효율적이고 체계적으로 사용한 고민을 적어보겠습니다.

 

참조

https://ko.react.dev/reference/rsc/server-components

https://nextjs.org/learn/dashboard-app/fetching-data