더북(TheBook)

20.4.5 스크립트로 스토어 초기 상태 주입하기

지금까지 작성한 코드는 API를 통해 받아 온 데이터를 렌더링하지만, 렌더링하는 과정에서 만들어진 스토어의 상태를 브라우저에서 재사용하지 못하는 상황입니다. 서버에서 만들어 준 상태를 브라우저에서 재사용하려면, 현재 스토어 상태를 문자열로 변환한 뒤 스크립트로 주입해 주어야 합니다.

index.server.js

(...)

function createPage(root, stateScript) {
  return `<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1,shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <title>React App</title>
    <link href="${manifest['main.css']}" rel="stylesheet" />
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root">
      ${root}
    </div>
    ${stateScript}
    <script src="${manifest['runtime~main.js']}"></script>
    ${chunks}
    <script src="${manifest['main.js']}"></script>
  </body>
  </html>
    `;
}
const app = express();

// 서버 사이드 렌더링을 처리할 핸들러 함수입니다.
const serverRender = async (req, res, next) => {
  (...)
  const root = ReactDOMServer.renderToString(jsx); // 렌더링을 합니다.
  // JSON 문자열로 변환하고 악성 스크립트가 실행되는 것을 방지하기 위해 < 치환 처리
  // https://redux.js.org/recipes/server-rendering#security-considerations
  const stateString = JSON.stringify(store.getState()).replace(/</g, '\\u003c');
  const stateScript = `<script>_ _PRELOADED_STATE_ _ = ${stateString}</script>`; // 리덕스 초기 상태를 스크립트로 주입합니다.

  res.send(createPage(root, stateScript)); // 결과물을 응답합니다.
};

(...)

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.