React와 Next의 렌더링 방식에 대해 더 알고 싶으시면, 이전 포스트를 먼저 읽어보시길 권장드립니다. React의 클라이언트 사이드 렌더링(CSR)과 Next의 사전 렌더링(Pre-Rendering)
서버 사이드 렌더링(SSR: Server-Side Rendering)은 사용자가 웹 페이지를 요청할 때 서버에서 HTML을 미리 렌더링하여 빠른 로딩 속도와 SEO 최적화를 제공합니다. 서버 사이드 렌더링의 전반적인 과정은 다음과 같습니다.
1. 사용자의 접속 요청
2. 서버에서 JavaScript 실행 후 HTML 반환: 서버는 요청을 처리하면서 최신 데이터를 반영해 HTML을 생성합니다. 이 HTML은 서버에서 완성된 상태로 클라이언트에 전송되며, 브라우저는 이를 받아 첫 번째 콘텐츠를 화면에 표시합니다. 이 시점은 FCP(First Contentful Paint)
로, 사용자가 첫 번째 콘텐츠를 볼 수 있는 시점입니다.
3. 서버에서 JavaScript 번들 파일 전송: HTML이 클라이언트로 전송된 후, 서버는 JavaScript 번들 파일도 함께 보내게 됩니다. 이 파일은 브라우저에서 실행되어 클라이언트 사이드에서 필요한 동적 작업을 처리합니다.
4. 브라우저에서 JavaScript 실행하여 기존 HTML과 연결: 브라우저는 JavaScript 번들 파일을 실행하여 기존 HTML 콘텐츠와 연결하고, 페이지의 인터랙티브한 기능을 활성화하는데 이 과정을 Hydration(수화) 라고 명명합니다. 이 시점이 TTI(Time to Interactive)
로, 페이지가 완전히 로드되어 사용자와의 상호작용이 가능한 상태가 됩니다.
import React, { useEffect, useState } from 'react';
const HomePage = () => {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch('/api/data');
const result = await response.json();
setData(result);
};
fetchData();
}, []); // 빈 배열을 넣으면 컴포넌트가 마운트될 때 한 번만 실행됩니다.
return (
<div>
<h1>Client-Side Rendering Example</h1>
{data ? (
<p>Data from API: {data}</p> // 데이터가 로드되면 출력
) : (
<p>Loading data...</p> // 데이터가 로딩 중일 때
)}
</div>
);
};
export default HomePage;
useState
와 useEffect
를 활용해 상태 관리와 사이드 이펙트를 처리합니다. import React from 'react';
const HomePage = ({ data }) => {
return (
<div>
<h1>Server-Side Rendering Example</h1>
<p>Data from server: {data}</p>
</div>
);
};
// getServerSideProps는 페이지를 요청할 때마다 실행되며, 서버에서 데이터를 가져와 페이지에 전달합니다.
export async function getServerSideProps() {
const response = await axios.get('https://your-domain.com/api/data');
const data = response.data;
return {
props: {
data, // 데이터를 컴포넌트로 전달
},
};
}
export default HomePage;
getServerSideProps()
가 실행됩니다. 이 함수는 페이지 요청 시 서버에서 데이터를 미리 가져와서 컴포넌트의 props로 전달합니다. 그리고 해당 값이 포함된 html 파일이 생성되어 클라이언트에게 보내집니다. <!DOCTYPE html>
<html lang="en">
``` 중략 ```
<div id="__next">
<h1>Server-Side Rendering Example</h1>
<p>Data from server: This data was fetched from the server!</p>
</div>
``` 중략 ```
<!-- 클라이언트에서 필요한 JavaScript 파일들 -->
<script src="/_next/static/chunks/main.js"></script>
<script src="/_next/static/chunks/framework.js"></script>
<script src="/_next/static/chunks/1.js"></script>
<script src="/_next/static/chunks/pages/index.js"></script>
</body>
</html>
getServerSideProps()
가 실행되어 클라이언트에게 해당 데이터가 fetching된 상태의 html로 반환됨을 확인할 수 있습니다. 위 html에는 클라이언트에서 React 앱을 Hydration할 수 있도록 필요한 JavaScript 파일들이 포함되어 있습니다. import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.hydrate(<App />, document.getElementById('root'));
하지만 초기 접속 이후에는 모두 CSR방식으로 동작됨을 명심하여야 합니다. 이 CSR방식을 개선하기 위해 프리페칭이라는 기능이 있으니 참고하세요.
서버 사이드 렌더링(SSR)은 서버에서 HTML을 미리 렌더링해 클라이언트에 전달하는 방식으로, 빠른 초기 로딩과 SEO 최적화에 유리합니다. Next.js에서는 getServerSideProps()
를 사용해 서버에서 데이터를 가져오고 페이지를 렌더링한 후, 클라이언트에서 JavaScript가 로드되어 페이지의 동적 기능을 활성화합니다. 서버 사이드 렌더링(SSR)은 FCP
가 빠르고, TTI
가 짧아 사용자 경험을 개선합니다.
서버 사이드 렌더링(SSR)은 특히 SEO가 중요한 사이트나 초기 로딩 속도가 중요한 애플리케이션에 매우 유리한 방법입니다.