hYhY1234 2021. 5. 19. 23:15
728x90

https://github.com/hayoung0Lee/complete-intro-to-react/tree/ssr

 

hayoung0Lee/complete-intro-to-react

Contribute to hayoung0Lee/complete-intro-to-react development by creating an account on GitHub.

github.com

ssr을 이번에 다시 한번 복습을 했는데, 왜 Next.js가 인기가 많은지 다시한번 알게 되는 시간이었다.

 

Server - renderToString

위의 예시는 express server를 통해서 server에서 이미 렌더링이 된 파일을 먼저 내려보내준다. 이때 App을 렌더링해야하는데, App 컴포넌트내에서 browserRouter(window 객체 참조)를 쓰고있는데, server에서는 window객체가 없으므로 StaticRouter로 감싸준다. 

import express from "express";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
import fs from "fs";
import App from "../src/App";

const PORT = process.env.PORT || 3000;

const html = fs.readFileSync("dist/index.html").toString();

const parts = html.split("not rendered");

const app = express();

app.use("/dist", express.static("dist"));
app.use((req, res) => {
  const staticContext = {};
  const reactMarkup = (
    <StaticRouter url={req.url} context={staticContext}>
      <App />
    </StaticRouter>
  );

  res.status(staticContext.statusCode || 200);
  res.send(`${parts[0]}${renderToString(reactMarkup)}${parts[1]}`);
  res.end();
});

console.log(`listening on http://localhost:${PORT}`);
app.listen(PORT);

 

RenderToString  는 React에서 제공하는데, 컴포넌트를 넘겨주면, html string을 뽑아준다. 이때 이렇게 컴포넌트를 변환한다음, index.html의 root부분에 끼워준다. 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Adopt me</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div id="modal"></div>
    <!-- React가 render하는 곳 -->
    <div id="root">not rendered</div>  <!-- 여기 renderToString한거 끼워줌 -->
    <script src="ClientApp.js"></script>
  </body>
</html>

 

 

ClientApp.js - hydrate

이러고 나서는 response로 갈텐데 위의 파일을 보면 알겠지만 html파일 자체에서는 ClientApp.js를 부르고 있다. 

import { hydrate } from "react-dom";
import { BrowserRouter, BrowserRouter as Router } from "react-router-dom";
import App from "./App";

hydrate(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);

ClientApp.js에서는 hydrate를 하고 있다. 이건 html 이 이미 renderToString같은 것으로 이미 렌더링 된 경우에 hydrate하기 위해서 사용된다. React가 이미 존재하는 마크업에 이벤트 리스너를 달아서 react컴포넌트화 하는 과정이다. 

 

react는 server와 client의 컨텐츠가 동일할것을 기대한다. 어느정도 미스매칭은 커버를 해주는 것 같은데, warning이 뜰수도 있긴한가보다. 

 

 

드디어 말귀를 이해한 좋은 글

 

https://simsimjae.tistory.com/389

 

리액트의 hydration이란?

hydration = 수화 수화란 우리 몸에 수분을 보충하는 행위를 뜻한다. 리액트에서 왜 hydration이라는 용어를 사용하는건지는 아래 내용을 살펴보고 다시 한번 생각해보자. 리액트는 DOM에 리액트 컴포

simsimjae.tistory.com

hydration이 매번 이해가 안되서 이글을 여러번봤었는데 드디어 좀 이해가 된다.

 

 

여튼 SSR을 하는 경우에는 성능이 더 좋아진게 맞는지 측정을 제대로 하는 것이 필요하다고 한다. 왜냐하면 server에서 렌더링 하는 시간 + html 파일도 보내줘야하고 + 기존처럼 js파일도 다 보내기때문.