Don’t worry about failures

리액트 서버 컴포넌트 본문

React

리액트 서버 컴포넌트

허흥 2024. 4. 4. 14:19
728x90

리액트 팀은 사용자의 경험을 증진시키기 위해 많은 연구를 한다. 이전 글에서 살펴보았던 동시성 모드, 서버 컴포넌트 등을 볼 수 있다. 해당 글에서는 리액트 서버 컴포넌트에 대해 알아볼 예정이다. 

 

리액트 서버 컴포넌트를 살펴보기에 앞서 간단하게 렌더링에 대한 간단한 히스토리를 살펴보자.

흐름에 따라 가다보면 리액트 서버 컴포넌트가 나오게 된 배경을 알게되고 이해하는 데에 도움이 되어 먼저 살펴보려한 것이다.

 

1세대 웹

1세대 웹에서는 정말 정적인 웹페이지만 구현이 되었었다. 자바스크립트 없이 서버에서 HTML을 응답하여 브라우저는 그대로 뿌려주기만 한 시대였다. 이 때문에 사용자간의 상호작용이 별도로 존재하지 않았다.  진정한 서버사이드 렌더링이다. 

 

2세대 웹

자바스크립트가 등장하면서 웹은 더욱 발전했다. 사용자간의 상호작용을 할 수가 있게 되어 동적인 웹의 모습을 띄게 됐다. 

 

이를 기점으로 자바스크립트는 점차 발전되고, 프런트 서버가 별도로 분리되는 등 클라이언트의 발전이 이루어지게 된다. 이렇게 발전하면서 기존의 서버사이드 렌더링, 즉 HTML을 모두 서버에서 생성해서 클라이언트에 제공을 함에 따라 서버의 부하가 커지고, HTML 생성에 있어 오래걸린다고하면 웹 브라이저는 단순히 하얀 페이지만 노출이 되게된다. 

 

클라이언트 사이드 렌더링

이러한 문제를 해결하고자 클라이언트 사이드 렌더링이 나오게 됐다.

클라이언트 사이드 렌더링의 경우 빈 HTML에 자바스크립트를 통해 필요한 데이터를 서버에게 요청하면서 그려나가는 방식이다. 이렇게 함으로써 매번 서버가 만들었던 HTML을 클라이언트가 작업하여 렌더링을 시켜준다. 이러한 작업을 더 효율적이고 최적화하여 렌더링에 도움을 주는 라이브러리가 리액트인것이다. 

 

하지만 클라이언트 사이드 렌더링에 있어서 단점이 존재했다. 클라이언트에서 그려주다보니 SEO에 좋지 않고, 첫 페이지 렌더링 시 자바스크립트가 다 그릴 때 동안 하얀화면을 봐야한다는 것이다. 저사양 디바이스의 경우 단점이 더 크게 나타날 것이다. 이에 환경 취약하여 서버사이드 렌더링을 권장하기도 한다.

 

서버 사이드 렌더링

이러한 단점을 해결하고자 다시 나온 것이 서버사이드 렌더링이다. 대표적인 프레임워크가 Next.js이다. 1세대 웹에서의 서버 사이드렌더링과의 약간의 차이가 있다고 하면, 서버 사이드 렌더링이지만, 클라이언트가 관리하며, Next.js 내부 서버를 통해 구현이 된다.

Next.js의 getserversideprops를 통해 서버 사이드렌더링을 표현할 수 있고, 이를 통해 HTML을 서버에서 만들어 응답을 해준다. 이와 같은 프레임워크와 리액트를 통해 서버사이드 렌더링을 활용하며, 리액트를 통해 유저 인터렉션을 컨트롤하게 된다. 

 

하지만 서버사이드 렌더링에 있어 단점이 통 HTML로 내려보내주고, 이후에 hydration이 이루어지게 된다. 이 동안 유저와의 상호작용이 이루어지지 않는다는 것이다. hydration은 HTML이 내려왔을 때 HTML을 보고 리액트는 메모리상에 컴포넌트(가상돔)를 렌더링하여 리액트화 시키고, 이벤트 등을 붙이는 과정이다. 화면은 보이지만 아무런 작업을 할 수가 없는 것이다. 이를 UX를 개선하고자 리액트에서는 <Suspanse>를 제공하여 컴포넌트별로 hydration 로딩 과정을 표현할 수 있고,  또한 우선순위를 적용하여 더 필요한 곳이 더 먼저 hydration이 이루어질 수 있도록 개선했다. 

 

 

 

 

리액트 서버 컴포넌트

리액트 서버 컴포넌트는 서버 사이드에서 부족했던 부분을 보완하고자 나오게 되었다. 리액트 서버 컴포넌트는 서버 사이드 렌더링과 유사하게 서버에서 리소스를 렌더링하여 클라이언트에게 전달하고 더 빠르게 사용자에게 리소스를 노출 시켜준다. 하지만 해결하고자 하는 문제점이 다르다.

이 둘의 차이를 보면,

- 서버 컴포넌트의 코드는 클라이언트로 전달되지 않는다. 반면 서버 사이드렌더링의 모든 컴포넌트의 코드는 자바스크립트 번들에 포함되어 클라이언트에 전송된다.

=> 해당 부분은 서버 컴포넌트의 장점이다. 흔이 검색해서 나오는 제로 번들 사이즈의 개념이다. 서버에서 렌더링이 다뤄지고 있기 때문에 굳이 클라이언트에게 리소스를 전달하지 않아 번들사이즈를 줄여줄 수 있다. 

 

- 서버 컴포넌트는 모든 컴포넌트에서 서버에 접근 가능하다. next.js 13 이후 버전에서 서버 컴포넌트는 디폴트가 되었다. 즉, 모든 컴포넌트가 기본적으로 서버 컴포넌트이다. 클라이언트 컴포넌트를 사용하고자 하면 상단에 'use client'를 기입한다. 

또 하나의 특징으로는 클라이언트의 컴포넌트에서 import 된 컴포넌트는 모두 클라이언트 컴포넌트로 간주된다. 

예) A,B 모두 별도로 use client를 기입 안해도 클라이언트 컴포넌트로 간주된다. 

'use client'

import A from './A.tsx'
import B from './B.txs'

const C = () => {
	return <>
    	<A/>
        <B/>
    </>
}

export default C;

주의할 점은 자식이라고 해서 모두 위의 케이스에 해당되지 않는다는 것이다.

 

아래의 예시는 위의 예시에 연장선이라고 해보자. C는 클라이언트 컴포넌트로 자식을 받도록하고, 이 자식들로 A,B의 컴포넌트 주입시키자.

이렇게 되면 A,B는 클라이언트 컴포넌트일까? 아니다. 비록 자식이지만 클라이언트 컴포넌트로 간주되지 않는다.

즉, client Boundary에선 부모/자식이 중요한게 아니라 import하는 컴포넌트에 집중한다는 것이다. D에서 use client를 하게되면 하위에 있는 모든 컴포넌트들이 client component가 되지만, A,B를 자식으로 둔 C라는 부모 client component 경우에는 A,B를 client component로 만들지 않는다.

import A from './A.tsx'
import B from './B.txs'

const D = () => {
	return <C>
    	<A/>
        <B/>
    <C/>
}

export default D;

 

반대로, 서버사이드 렌더링의 경우 페이지 레벨에서 getServerProps(), GetInitialProps() 인 경우에만 서버에 접근이 가능하다.

 

- 서버 컴포넌트는 클라이언트 상태를 유지하며 refetch될 수 있다. 

서버 컴포넌트는 HTML이 아닌 특별한 형태로 컴포넌트를 전달하기 때문에 필요한 경우 포커스, 인풋 입력값 같은 클라이언트 상태를 유지하며 여러 번 데이터를 가져오고 리렌더링하여 전달할 수 있다. 이는 HTML의 통으로 관리되는게 아니라 부분 부분 컴포넌트로써 관리가 되는거라 생각된다. 이 부분이 서버 컴포넌트의 큰 장점이라고 생각한다. 

출처 :&nbsp;https://tech.kakaopay.com/post/react-server-components/

반면, 서버 사이드 렌더링의 경우 HTML로 전달되기 대문에 새로운 refetch가 필요한 경우 HTML 전체를 리렌더링 해야하며, 이로 인해 클라이언트 상태를 유지할 수 없다. 

 

이와 같이 비슷한 개념은 있지만, 각자의 차이가 있고 해결하고자하는 문제가 다르다.

이를 잘 활용한다면 브라이우저에서 유저의 경험을 더 좋게할 수 있는 방법이 될 것이다.

 

 

참고자료:

https://blog.mathpresso.com/suspense-ssr-architecture-in-react-18-ec75e80eb68d

 

Suspense SSR Architecture in React 18

React 18의 Suspense가 SSR에 가져올 변화에 대해서 살펴봅니다.

blog.mathpresso.com

 

https://tech.kakaopay.com/post/react-server-components/

 

React 18: 리액트 서버 컴포넌트 준비하기 | 카카오페이 기술 블로그

공식 릴리즈 전인 리액트 서버 컴포넌트에 대해 알아보고 준비해 봅니다.

tech.kakaopay.com

https://www.yujiseok.blog/post/react-server-components#%EB%AA%A8%EB%93%A0-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EC%97%90%EC%84%9C-%ED%95%98%EC%9D%B4%EB%93%9C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EB%90%98%EA%B8%B0-%EC%A0%84%EC%97%90-%EB%B0%98%EB%93%9C%EC%8B%9C-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%EB%90%98%EC%96%B4%EC%95%BC%ED%95%9C%EB%8B%A4

 

리액트 서버 컴포넌트란 도대체 무엇일까요?

알쏭달쏭한 리액트 서버 컴포넌트를 정리합니다.

www.yujiseok.blog

 

728x90

'React' 카테고리의 다른 글

css-in-js를 떠나 보내야하나?  (0) 2024.04.22
MSW에 대해  (0) 2024.03.26
전역 상태관리에 대해  (0) 2024.03.25
Hydrate에 대해  (0) 2024.03.22
React StrictMode에 대해  (0) 2024.03.21