왜 갈수록 개발자들이 서버 사이드 렌더링에 집중하게 되는 것일까요?
첫 번째로 전통적인 react application 의 브라우저 내에서 동작 방식에 대해서 먼저 살펴보도록 하겠습니다. 제가 말하는 전통적인 react application 이란, 서버 사이드에서 렌더링 되지 않고, 오직 브라우저 내에서만 렌더링 되는 어플리케이션을 의미합니다.
우선 리액트 앱의 특정 life-cycle 을 집중적으로 살펴볼건데요,
유저가 특정 페이지에 처음 들어왔을때부터, 해당 페이지의 컨텐츠가 눈에 보여지기까지의 특정 시간에 대해서 알아보겠습니다.
위의 프로젝트는 아무것도 손대지 않은 바닐라 리액트 프로젝트입니다. 해당 앱에 처음 접속했을때 먼저 브라우저는 localhost:3000 에 요청을 하게 됩니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<!--
Notice the use of in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.Unlike "/favicon.ico" or "favicon.ico", "/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script></body>
</html>
localhost 는 위와 같이 생겼습니다. <div /> 태그에는 그 어떠한 코드도 쓰여져 있지 않음을 볼 수 있고, 그 밑에 <script /> 태그에서 /static/js/bundle.js 파일을 읽고 있음을 볼 수 있습니다.
bundle.js 파일을 보시면 그곳에는 리액트 프로젝트에서 개발자가 코딩한 javascript 코드들이 실행되어지는 것을 확인 가능합니다.
유저가 처음 페이지에 들어와서 화면이 보여지는데에는 위와 같은 과정이 필요하게 되는겁니다.
만약에 해당 페이지에서 backend 서버에 어떤 데이터를 불러오는 작업까지 있어야 한다고 하면 과정이 더 생기게 될겁니다.
리액트를 이용하여서 어플리케이션을 인터랙티브한 SPA 를 만들기에 아주 최적화가 되어있지만, 위와 같은 문제점들이 존재하기 때문에 실제 프로덕트를 배포하는 환경에서는 치명적인 약점이 될 수 있습니다.
뿐만 아니라, 가능한 노출이 쉽게 되어져야 좋은 웹 페이지의 특성상 검색엔진에 검색이 제대로 안되어질수도 있으므로 리액트로 프로젝트를 만들게 된다면 아주 치명적인 단점을 두개나 끌어안고 가게되는 것이죠.
개발자들은 이를 해결하기 위해서 서버 사이드 렌더링이라는 방법을 고안해내었습니다. 그렇다면 서버 사이드 렌더링은 어떠한 방식으로 작동되는 것일까요?
SSR Overview
- User navigates to application
- Server receives request
- Server loads up react app in memory
- Server fetches any required data
- Server renders the react app
- Server takes the generated HTML, send it to user
- User receives generated html page
이 단계까지 진행이 되어진다면 유저들은 완전히 작성된 html 페이지를 받아볼 수 있게됩니다. 하지만 여기서 프로세스는 끝이 나지 않습니다. 현재 유저가 받아보고 있는 페이지는 순수 HTML 로 작성된 페이지이기 때문에 React application 처럼 인터랙티브한 페이지를 유저에게 제공해줄수가 없습니다. 그렇기 때문에 다음의 프로세스까지 모두 마쳐야 제대로 된 SSR 프로젝트라고 부를 수 있게 됩니다.
- HTML file says browser needs bundle.js
- Go get bundle.js file
- Get bundle.js. React app boots up
- React app makes followup requests for data
다음의 프로세스까지 온전히 마치게 된다면 유저들은 처음 어플리케이션에 접근했을때 화면을 구성해주는 html 파일을 받게 되고, 그 이후에 browser 에서 bundle.js 파일을 모두 읽어들이게 되면, 완전한 React 앱을 이용할 수 있게 되는 것입니다.
여기서 우리가 집중해야 할 부분은, User 가 페이지에 처음 접근하였을때, 가능 한 빠르게 유저에게 로딩된 페이지를 보여줌과 동시에, React 어플리케이션의 강점을 하나도 포기하지 않는 것 입니다.