들어가는 말
Next.js의 13 버전부터 등장한 app router에서는 기존의 서버 사이드 렌더링과는 다르게 리액트 서버 컴포넌트라는 친구를 사용해요. 언뜻 보기에는 단순히 서버 사이드 렌더링의 대체제로 나온 것이 리액트 서버 컴포넌트처럼 보이는데요. 이 둘은 과연 어떤 차이가 있길래 리액트 측에서 이런 새로운 것을 만든 것일까요?
서버 사이드 렌더링 (특히 리액트를 이용한)
사용자가 기다리는 시간을 심심하지 않게
서버 사이드 렌더링의 핵심은 '페이지 첫 로드'입니다. 기존에 리액트를 이용한 싱글 페이지 어플리케이션에서는 자바스크립트를 다운로드 받기 전까지 사용자는 빈 화면을 볼 수밖에 없었는데요. 서버 사이드 렌더링을 도입하면 일단 서버에서 빠르게 한 번 돌려서 렌더링 결과물인 HTML을 클라이언트에게 전달합니다. 이러면 사용자는 자바스크립트를 다운로드 받기 전까지 첫 렌더링 결과물을 볼 수 있죠.
그래도 기다려야 한다
물론 사용자가 보고 있는 건 그냥 HTML일 뿐이므로, 뭔갈 더 하려면 자바스크립트 번들 다운로드를 기다려야 합니다.
비효율적인 기다림
하지만 리액트를 사용한 서버 사이드 렌더링에는 함정이 있습니다. 바로 그 번들이 전부 상호작용만을 위한 것은 아니라는 거예요.
리액트로 만들었으니 서버에서 받아온 번들을 이용해 HTML을 살려서 상호작용성을 부여하는 작업을 해야 합니다. 이걸 'hydrate'라고 불러요. 리액트에서는 hydrateRoot()
를 사용해 이 작업을 진행합니다. 하지만 hydrateRoot()
의 특성 상 페이지를 살리기 위해서는 실제로 리액트의 상태나 각종 상호작용을 위한 자바스크립트가 필요 없는 정적인 내용을 그리는 컴포넌트의 코드까지 전부 필요합니다. 정적인 내용을 만들 때 파싱이라던가 하는 이유로 다른 라이브러리를 사용한다면 해당 코드까지 전부요.
어떻게 보면 당연합니다. 리액트는 싱글 페이지 어플리케이션이고, 그 단점이 번들 크기가 크다는 것이니까요. 서버 사이드 렌더링에서 초기 HTML을 그리는 데 정적인 코드를 이미 사용했고, 사실 클라이언트 쪽에서 해당 코드가 돌아갈 일은 없지만 hydrate를 위해 다운로드 받아야 한다는 건 비효율적이라고 볼 수 있겠죠.
리액트 서버 컴포넌트
HTML과는 관련 없음
리액트 서버 컴포넌트는 HTML과는 아무런 관련이 없습니다. 서버 컴포넌트는 페이지가 아니라 '컴포넌트'니까요. 이 친구들은 JSON처럼 직렬화가 가능한 자료형으로 바뀌어 클라이언트에 도착합니다. 이러면 리액트는 그 자료에 나와 있는 렌더링 결과물, 해당 컴포넌트의 자바스크립트 위치, 해당 컴포넌트의 실제 위치 등을 바탕으로 클라이언트의 화면에 컴포넌트를 그리죠.
참고) Next.js는 서버 컴포넌트를 활용하더라도 자체적으로 서버에서 렌더링해보고 첫 결과를 HTML을 묶어서 보내주는데요. 이건 Next.js에서 제공하는 일종의 편의성이지 실제 리액트 서버 컴포넌트의 개념과는 관계가 없어요.
나눠서 기다리기
리액트 서버 컴포넌트를 사용하면 전체 번들을 다운로드 받는 것이 아니라 본인의 상호작용을 위한 코드만 받습니다. 따라서 Suspense
와 같은 기법들을 사용한다면 이미 처리가 다 끝난 컴포넌트는 사용자에게 먼저 보여주고, 먼저 상호작용이 되게끔 할 수 있죠.
내부적으로 리액트 상태같은 걸 아예 사용하지 않는 정적인 컴포넌트라면 자바스크립트를 다운받지도 않습니다. 화면 렌더링할 때 외부 라이브러리를 써서 문자열을 파싱해야 한다고요? 그건 서버에서 이미 처리했습니다. 클라이언트는 파싱된 문자열만 받지 그 파싱을 위해 얼마나 위대한 라이브러리가 사용되었는지는 더 이상 클라이언트의 관심사가 아닙니다.
상태의 유지
서버 사이드 렌더링은 새로운 HTML을 주고, 거기에서 새로운 자바스크립트 코드를 다운받습니다. 하지만 리액트 서버 컴포넌트가 받는 건 JSON과 같은 일반 자료에 불과합니다. 그리고 그걸 처리해서 실제 DOM에 붙여주는 건 이미 클라이언트에서 돌아가고 있는 리액트고요. 그렇기 때문에 옆집 다른 컴포넌트에 들어있는 리액트 상태나, input focus와 같은 클라이언트 측의 상태를 유지할 수 있습니다.
결론
- 서버 사이드 렌더링은 페이지의 첫 로딩에 이미 만들어진 HTML을 보여주는 것입니다.
- 리액트 서버 컴포넌트는 컴포넌트의 렌더링 함수를 서버에서 실행하는 것입니다.
이외에도 RFC를 읽어 보면 여러 문제 상황에 대한 해결책으로 리액트 서버 컴포넌트를 만들었다고 쓰여 있는데요. 일단 서버 사이드 렌더링과 비교해서 설명하기에 괜찮다고 생각되는 내용을 뽑아왔습니다.
참고자료 & 읽어볼 만한 글들
(추천)RFC: React Server Components
The Difference Between React Server Components and Server Side Rendering (SSR)
What is the difference between RSC and SSR?
(추천)Data Fetching with React Server Components
(추천)Hacker News의 댓글
Next.js의 렌더링 과정(Hydrate) 알아보기
RSC Parser (RSC payload가 어떻게 생겼는지 궁금하다면 구경가보세요)
'호기심 천국' 카테고리의 다른 글
CSS) border vs outline (0) | 2024.02.23 |
---|---|
React.ReactNode vs JSX.Element (1) | 2024.02.09 |
타입스크립트는 자바스크립트의 상위집합(superset)일까? (4) | 2023.09.30 |
React) useState는 클로저로 동작할까? (4) | 2023.09.11 |
React) 아무 함수나 커스텀 훅이 될 수 있을까? (0) | 2023.05.07 |