본문 바로가기

카테고리 없음

[React] React와 서버 사이드 렌더링 (SSR): 상세 가이드

반응형

오늘은 React와 서버 사이드 렌더링(SSR)에 대해 자세히 알아보겠습니다. 이 가이드는 SSR의 기본 개념부터 React에서의 실제 구현 방법, 그리고 고급 주제까지 다룰 예정입니다.

1. 서버 사이드 렌더링(SSR)이란?

서버 사이드 렌더링은 웹페이지의 초기 로드를 서버에서 처리하는 기술입니다. 전통적인 웹 개발 방식이었으나, 싱글 페이지 애플리케이션(SPA)의 등장으로 클라이언트 사이드 렌더링(CSR)이 주목받게 되었습니다. 하지만 최근 다시 SSR이 주목받고 있죠.

동작 방식:

  1. 사용자가 페이지를 요청합니다.
  2. 서버는 요청을 받아 필요한 데이터를 가져옵니다.
  3. 서버에서 React 컴포넌트를 렌더링하여 HTML을 생성합니다.
  4. 생성된 HTML을 클라이언트에 보냅니다.
  5. 클라이언트는 받은 HTML을 표시하고, React가 이어서 동작(hydration)합니다.

CSR vs SSR 비유:

  • CSR: 레스토랑에서 주문 후 요리사가 눈앞에서 요리를 만드는 것
  • SSR: 음식이 이미 준비된 상태로 테이블에 세팅되는 것

2. SSR의 장점과 단점

장점:

  1. 초기 로딩 속도 개선: 사용자는 완성된 콘텐츠를 빠르게 볼 수 있습니다.
  2. 검색 엔진 최적화(SEO): 검색 엔진 크롤러가 완전한 HTML 콘텐츠를 쉽게 읽을 수 있습니다.
  3. 소셜 미디어 공유 최적화: 페이지 미리보기가 정확하게 생성됩니다.
  4. 성능이 낮은 기기에서도 빠른 초기 렌더링: JavaScript 실행 전에도 콘텐츠를 볼 수 있습니다.

단점:

  1. 서버 부하 증가: 모든 요청마다 서버에서 렌더링하므로 서버 자원을 더 많이 사용합니다.
  2. 개발 복잡성: 서버와 클라이언트 양쪽을 고려해야 해서 개발이 더 복잡해질 수 있습니다.
  3. Time to Interactive (TTI) 지연: 초기 HTML은 빠르게 로드되지만, JavaScript가 로드되기 전까지 상호작용이 불가능할 수 있습니다.

3. React에서 SSR 구현하기

React에서 SSR을 구현하는 방법은 크게 두 가지입니다: 직접 구현하거나 Next.js 같은 프레임워크를 사용하는 것입니다.

3.1 직접 SSR 구현하기

직접 구현하는 방법은 복잡하지만, SSR의 동작 원리를 이해하는 데 도움이 됩니다.

1. 서버 설정 (Express 사용):

const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const App = require('./App');

const app = express();

app.get('/', (req, res) => {
  const html = ReactDOMServer.renderToString(<App />);
  res.send(`
    <!DOCTYPE html>
    <html>
      <head>
        <title>My SSR React App</title>
      </head>
      <body>
        <div id="root">${html}</div>
        <script src="/bundle.js"></script>
      </body>
    </html>
  `);
});

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

2. 클라이언트 측 hydration:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.hydrate(<App />, document.getElementById('root'));

3.2 Next.js 사용하기

Next.js는 React 기반의 SSR 프레임워크로, SSR 구현을 매우 간단하게 만들어줍니다.

 

1.Next.js 프로젝트 생성:

npx create-next-app my-ssr-app
cd my-ssr-app


2.SSR 페이지 생성:

// pages/index.js
export default function Home({ serverData }) {
  return <h1>서버에서 받은 데이터: {serverData}</h1>;
}

export async function getServerSideProps() {
  // 서버 측 로직 실행
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  return { props: { serverData: data.message } };
}

3.동적 라우트에서의 SSR:

// pages/posts/[id].js
export default function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

export async function getServerSideProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();
  return { props: { post } };
}

4. SSR vs CSR: 선택 기준

프로젝트의 특성에 따라 SSR과 CSR 중 적절한 방식을 선택해야 합니다.

SSR이 적합한 경우:

  • SEO가 중요한 콘텐츠 중심의 웹사이트 (블로그, 뉴스 사이트 등)
  • 초기 로딩 속도가 매우 중요한 경우
  • 소셜 미디어 공유가 빈번한 사이트

CSR이 적합한 경우:

  • 복잡한 사용자 인터랙션이 많은 웹 애플리케이션 (관리자 대시보드 등)
  • 서버 리소스가 제한적인 경우
  • SEO가 크게 중요하지 않은 경우

5. SSR의 성능 최적화

SSR을 사용할 때도 성능 최적화는 중요합니다:

1.코드 분할: 필요한 JavaScript만 로드하여 초기 로딩 시간을 줄입니다.

import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/DynamicComponent'));

2.캐싱: 서버 렌더링 결과를 캐시하여 서버 부하를 줄입니다.

export async function getServerSideProps({ req, res }) {
  res.setHeader('Cache-Control', 's-maxage=10, stale-while-revalidate');
  // ... 데이터 fetching 로직
}

3.스트리밍 SSR: 큰 페이지를 작은 청크로 나누어 점진적으로 전송합니다. (React 18 이상)

 

6. SSR의 미래: 새로운 동향

  1. 부분적 hydration: 페이지의 일부만 선택적으로 hydration하여 성능을 개선합니다.
  2. Islands Architecture: 정적 HTML 안에 동적 "섬"을 만들어 SSR과 CSR의 장점을 결합합니다.
  3. 서버 컴포넌트: React 팀에서 개발 중인 새로운 패러다임으로, 서버에서만 실행되는 컴포넌트를 만들 수 있습니다.

서버 사이드 렌더링은 React 애플리케이션의 성능과 SEO를 개선하는 강력한 도구입니다. Next.js와 같은 프레임워크의 등장으로 SSR 구현이 much 쉬워졌지만, 여전히 trade-off가 존재합니다.

SSR은 만능 해결책이 아니며, 프로젝트의 요구사항과 특성에 따라 적절히 사용해야 합니다. CSR, SSR, 그리고 둘의 하이브리드 접근 중에서 프로젝트에 가장 적합한 방식을 선택하는 것이 중요합니다.

React와 SSR을 잘 활용하여 사용자에게 더 나은 경험을 제공하는 웹 애플리케이션을 만들어보세요!

반응형