리액트가 서버에서만 단독으로 실행되는 리액트 서버 컴포넌트를 공개했다고 하는데, 그게 무엇인지 설명하기에 앞서 이해를 돕기 위해 서버사이드 렌더링이 무엇인지 간략하게 알아보겠다.
서버 사이드 렌더링(SSR)이란?
기본적인 리액트 애플리케이션은 아래 사진과 같이 클라이언트 사이드 렌더링(CSR)으로 동작한다.
클라이언트 사이드 렌더링을 사용하는 앱의 경우 페이지 진입 시 HTML, 자바스크립트 그리고 모든 데이터가 로드되고 컴포넌트 렌더링이 끝나기 전까지 사용자는 아무런 기능이 없는 빈 화면만 보게되는데, 이는 사용자 경험을 저하시킨다.
반면 서버사이드렌더링(SSR)은, 클라이언트 애플리케이션의 자바스크립트 파일을 서버에서 먼저 HTML로 렌더링하기 때문에 빈 화면 대신 데이터가 존재하는 HTML을 제공함으로써 번들 파일이 다운로드되는 동안 사용자에게 의미 있는 콘텐츠를 제공할 수 있다.
서버 사이드 렌더링의 가장 큰 목적은 정적인 클라이언트 컴포넌트를 최대한 빠르게 브라우저에 전달하여 초기 페이지의 FCP/LCP 속도를 향상시는 것이라고 할 수 있다.
필요한 데이터를 서버에서 받아오는 방법으로 흔히 두 가지가 있다.
- 모든 정보를 부모 컴포넌트에서 하나의 거대한 API로 호출하여 자식으로 내려준다.
- 컴포넌트에 필요한 API를 각 컴포넌트에서 호출한다.
그러나 첫번째 방법은 부모 자식 컴포넌트 간의 의존성이 높아져 유지보수가 어려워지는 문제가 있고, 두번째 방법은 클라이언트로부터 서버로의 요청이 늘어나고, 연속된 client-server API 요청과 중첩된 컴포넌트 내 API 호출 지연으로 인해 사용자 경험을 떨어뜨릴 수 있다는 문제가 있다.
이와 같이 클라이언트 컴포넌트에서의 비동기 data fetching은 성능을 저하시키는 원인이 된다.
이를 해결하는 것으로 서버 컴포넌트가 등장했다.
서버 컴포넌트(RSC)란?
서버 컴포넌트를 사용하면 컴포넌트 렌더링을 클라이언트가 아닌 서버에서 수행할 수 있다(서버에서 동작하고 렌더링). 서버 컴포넌트 도입 후 리액트 컴포넌트에서의 data-fetching은 아래와 같이 간단해진다. 컴포넌트에서 필요한 데이터만 fetching하는 방식을 유지하면서 성능을 향상시킬 수 있다.
// Note.server.js - 서버 컴포넌트의 파일 네임 컨벤션
import { fetch } from 'react-fetch';
function Note(props) {
// 아래 요청은 client-to-server가 아닌 server-to-server로 진행됩니다.
const note = fetch(`https://api.example.com/notes/${props.id}`).json();
if (note == null) {
return <div>노트가 존재하지 않습니다.</div>;
} else {
return (/* render note here... */);
}
}
장점
- 컴포넌트 내에서 서버 전용 코드를 실행할 수 있다 -> 서버 컴포넌트가 자바스크립트 번들에 포함되지 않음, 번들 사이즈 감소
- 여러 기능, 라이브러리들이 서버에서 실행될 수 있음 -> JS 번들에 너무 많은 용량이 추가될까봐 생략했던 기능들을 서버에서 실행함으로써 비용을 아낄 수 있음
- 서버 리소스에 자유롭게 접근 가능 -> 서버에서 동작하기 때문에 데이터베이스, 파일 시스템 그리고 인터널 서비스 같은 서버 사이드 데이터 소스에 직접 접근할 수 있음
// Note.server.js - 서버 컴포넌트
import fs from 'react-fs';
import db from 'db.server';
function Note(props) {
// NOTE: loads *during* render, w low-latency data access on the server
const note = db.notes.get(props.id); // 데이터베이스 접근
const noteFromFile = JSON.parse(fs.readFile(`${id}.json`)); // 파일 접근
if (note == null) {
// handle missing note
}
return (/* render note here... */);
}
이렇게 서버에서 fetching한 데이터는 클라이언트 컴포넌트에 props로 전달 가능 -> 그러나 json으로 인코딩 가능한 serializable props만 전달 가능하며 function은 전달할 수 없음
서버 컴포넌트(RSC)와 서버 사이드 렌더링(SSR)의 차이
- 서버 컴포넌트의 코드는 클라이언트로 전달되지 않으나, 서버 사이드 렌더링의 모든 컴포넌트의 코드는 자바스크립트 번들에 포함되어 클라이언트로 전송된다.
- 서버 컴포넌트는 클라이언트 상태를 유지하며 refetch 될 수 있다.(필요한 경우 포커스, 인풋 입력값 같은 클라이언트 상태를 유지하며 여러 번 데이터를 가져오고 리렌더링하여 전달)
- SSR의 경우 HTML로 전달되기 때문에 새로운 refetch가 필요한 경우 HTML 전체를 리렌더링 해야 함
'리액트 심화 스터디' 카테고리의 다른 글
[Week 6] React Profiler, React.lazy, Debounce, Throttle (2) | 2024.12.03 |
---|---|
🏄♀️ 리심스 6주차 - 리액트 성능 최적화 (2) | 2024.12.03 |
[Week 5] SSR과 RSC (2) | 2024.11.26 |
🏄♀️ 리심스 4주차 - 컴포넌트 패턴 (2) | 2024.11.19 |
[Week 4] Compound Component Pattern, HOC, React Portal (2) | 2024.11.19 |