본문 바로가기
개발정리 (nodeJS)

[nodeJS] Node.js에서 서버사이드 렌더링(SSR) 구현하기

by 할리갈리0 2024. 8. 2.

[서버사이드 렌더링(SSR)]

웹 페이지를 서버에서 렌더링하여 클라이언트에 전달하는 방식

클라이언트는 서버에서 받은 HTML을 그대로 화면에 표시

  • 빠른 초기 로딩 시간: 서버에서 이미 렌더링된 HTML을 전달하므로 클라이언트는 즉시 콘텐츠를 볼 수 있음.
  • SEO 개선: 검색 엔진은 완전히 렌더링된 HTML을 크롤링하므로, 페이지의 가시성이 높아짐.

 

1. Node.js와 Express를 사용한 SSR 기본 설정

Node.js 프로젝트를 설정하고 필요한 패키지를 설치

mkdir ssr-example
cd ssr-example
npm init -y
npm install express react react-dom @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli

 

Express 서버를 설정하여 모든 요청을 public/index.html로 전달

// server.js
const express = require('express');
const path = require('path');
const app = express();

app.use(express.static('public'));

app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

 

2. React와 Express를 사용한 SSR 구현

SSR을 위해 Webpack을 설정하여 React 코드를 번들링

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
    ]
  }
};
// React 컴포넌트를 작성
import React from 'react';

const App = () => {
  return (
    <div>
      <h1>Hello, SSR!</h1>
      <p>This is a server-side rendered page.</p>
    </div>
  );
};

export default App;

 

React 컴포넌트를 서버에서 렌더링하고, 완전히 렌더링된 HTML을 클라이언트에 전달

// server.js (추가 부분)
const React = require('react');
const { renderToString } = require('react-dom/server');
const App = require('./src/App').default;

app.get('*', (req, res) => {
  const appString = renderToString(<App />);

  const html = `
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>SSR Example</title>
      </head>
      <body>
        <div id="root">${appString}</div>
        <script src="bundle.js"></script>
      </body>
    </html>
  `;

  res.send(html);
});

 

3. 데이터 페칭과 SSR 통합하기

SSR에서 데이터를 서버사이드에서 페칭하고, 렌더링할 때 함께 제공하기

// server.js (데이터 페칭 추가)
const fetch = require('node-fetch');

app.get('*', async (req, res) => {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();

  const appString = renderToString(<App data={data} />);

  const html = `
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>SSR Example</title>
      </head>
      <body>
        <div id="root">${appString}</div>
        <script>window.__INITIAL_DATA__ = ${JSON.stringify(data)}</script>
        <script src="bundle.js"></script>
      </body>
    </html>
  `;

  res.send(html);
});

 

React 컴포넌트에서 서버사이드에서 전달된 데이터를 사용

// src/App.js
import React from 'react';

const App = ({ data }) => {
  return (
    <div>
      <h1>Hello, SSR!</h1>
      <p>This is a server-side rendered page.</p>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default App;

 

4. 성능 최적화 및 SEO 개선 방법

성능 최적화

  • 압축: Gzip이나 Brotli와 같은 압축 방식을 사용하여 전송 데이터 줄이기
  • 캐싱: 페이지나 API 응답을 캐싱하여 성능 향상 시키기
  • 코드 스플리팅: Webpack의 코드 스플리팅을 활용하여 필요한 부분만 로드하기

SEO 개선

  • 메타 태그: 제목, 설명, 키워드 등의 메타 태그를 설정하여 검색 엔진에서 페이지를 잘 인식하도록 하기
  • 구조화된 데이터: 구조화된 데이터를 추가하여 검색 엔진이 페이지의 내용을 이해하기 쉽게 하기
  • 사이트맵: XML 사이트맵을 생성하여 검색 엔진에 사이트 구조를 제공하기

 

SSR을 통해 검색 엔진이 페이지를 쉽게 크롤링할 수 있고, 사용자가 빠르게 콘텐츠를 볼 수 있어 사용자 경험이 향상됩니다. 이를 통해 더 나은 성능과 SEO를 갖춘 웹 애플리케이션을 개발할 수 있습니다.

반응형