CSR vs SSR

Jvito
11 min readSep 3, 2022

--

1. SSR (Server Side Rendring)

서버로 부터 완전하게 만들어진 html파일을 받아와 페이지 전체를 렌더링 하는 방식이다.

1.1 과정

  • 유저가 웹사이트에 요청을 보낸다.
  • 서버는 필요하다면 데이터베이스에서 데이터를 가지고 오고, 페이지를 렌더링하는데 필요한 작업을 수행한 HTML 파일을 만든다.
  • 유저는 이제 서버가 렌더링 해준 HTML을 이용하여 콘텐츠를 볼 수 있다. (Time to view)
  • 하지만 아직 페이지에서 상호작용을 할 수 있는 JS파일이 존재하지 않기 때문에 페이지에서 클릭했을 때 반응이 일어나지 않는 부분이 존재한다.
  • 브라우저에서 필요한 상호작용에 필요한 JS 파일을 서버로 부터 받는다.
  • JS 파일을 브라우저에서 컴파일 후 인터랙티브한 페이지가 완성되었다. (Time To Interact)

1.2 장점

  • HTML 컨텐츠가 이미 담겨져 있기에 SEO(Search Engine Optimizaion)에 좋다.
  • 사용자에게 첫 콘텐츠를 빨리 보여줄 수 있는 장점이 존재한다.

1.3 단점

  • 매번 페이지를 요청할 때마다 새로고침 되는 치명적인 단점이 존재한다.
  • TTV(Time To View)와 TTI(Time To Interact)의 공백이 발생한다.
  • 페이지를 구성하는 모든 리소스를 서버에서 처리하므로 요청이 많아질 때 서버 부담이 증가한다.

중요한 부분은 렌더링 주체가 ‘서버’ 라는 점이다.

2. CSR (Client Side rendring)

CSR은 페이지를 브라우저에서 서버로 부터 받은 JS 파일을 이용하여 직접 렌더링 하는 것을 의미한다.

2.1 과정

  • 유저가 웹사이트에 요청을 보낸다.
  • 브라우저는 링크를 이용하여 화면을 그리는데 필요한 HTML, JS 파일을 다운받는다.
  • 브라우저는 JS 코드를 실행하여 리액트를 구동한다.
  • 이 때 API를 통해 데이터베이스에 존재하는 데이터를 사용할 경우 API를 호출한다.
  • 서버에서 데이터베이스에서 조회한 데이터를 응답한다.
  • API로 부터 받은 데이터를 채워준 뒤 리액트가 VirtualDOM에 콘텐츠를 렌더링 한다.
  • VirtualDOM이 구성이 완료되면 이를 브라우저 DOM 붙힌다.

2.2 장점

  • 렌더링이 필요한 부분만 바꾸기 때문에 페이지 새로고침이 발생하지 않는다.
  • 렌더링 주체가 브라우저 이므로 서버에 부하를 줄일 수 있다.

2.3 단점

  • JS 파일을 번들링해서 한번에 받기 때문에 초기 유저가 콘텐츠를 보기까지의 속도가 느리다.
  • 기본 HTML이 비어있어 SEO(Search Engine Optimizaion)에 최적화 되어 있지 않다.

중요한 부분은 렌더링 주체가 ‘브라우저’ 라는 점이다.

3. 실습

리액트로 구성된 CSR을 사용하는 프로젝트 페이지에서의 네트워크 탭을 통하여 파일을 어떻게 로드하고 있는지 살펴보자.

처음으로 HTML 파일을 로드 하는 부분이다.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<title>Chatting</title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
</body>
</html>
  • 실제 네트워크 탭에서 받은 응답이다.
  • 위에서 보는것과 같이 HTML에 파일에 ‘root’태그를 제외한 페이지를 구성하는 어떠한 태그들이 존재하지 않는 것을 볼 수 있다.

그 후 리액트 관련 JS파일과 UI를 구현하고 상호작용에 필요한 JS파일을 다운받아 오는 것을 볼 수 있다.

mainJS 파일은 Minfy, Uglify 되어 알아볼 수 없는 코드로 구성되어 있는 것을 확인할 수 있다.

/*! For license information please see main.37b3cf38.js.LICENSE.txt */
function(){var e={892:function(e){e.exports=function(){"use strict";var e=1e3,t=6e4,n=36e5,r="millisecond",o="second",i="minute",a="hour",u="day",l="week",c="month",s="quarter",f="year",d="date",p="Invalid Date",h=/^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[Tt\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/,v=/\\[([^\\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/
...

JS 코드를 이용하여 페이지에 필요한 콘텐츠를 동적으로 구성한다.

그 후 탭을 눌러 페이지를 이동하여도 필요한 데이터가 없다면 더 이상 서버에 HTML 파일을 요청하지 않는 것을 확인하였다.

그럼 이제 node + Express로 구성된 SSR을 사용하는 프로젝트 페이지를 살펴보자.

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="/codemirror/theme/midnight.css">
<script src="/codemirror/lib/codemirror.js"></script>
<script src="/codemirror/mode/javascript/javascript.js"></script>
<script src="/codemirror/addon/edit/matchbrackets.js"></script>
<script src="/codemirror/addon/edit/closebrackets.js"></script>
<script src="/codemirror/addon/hint/show-hint.js"></script>
<script src="/codemirror/addon/hint/javascript-hint.js"></script>
<script src="/codemirror/addon/selection/active-line.js""></script>
<title>CodeWars</title>
</head>
<body>
<h2>피보나치 수열</h2>
<h4>정답자: 15명</h4>
<h4>난이도: Level 1</h4>
<div>설명: 피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.</div>
<form action="/problems/627904cdd626d53e513898aa" method="post">
<textarea id="code" name="code"></textarea>
<button type="submit" class="submitButton">submit</button>
</form>
<script >
CodeMirror.fromTextArea(document.getElementById("code"), {
lint: true,
lineNumbers: true,
tabSize: 2,
styleActiveLine: true,
mode: "text/javascript",
matchBrackets: true,
autofocus: true,
autoCloseBrackets: true,
theme: "midnight",
}).setValue("function solution(arg) {\\n // here!\\n}");
</script>
</body>
</html>
  • CSR 방식과 다르게 이미 데이터베이스를 조회를 이용하여 구성한 정보를 포함하여 페이지 콘텐츠를 포함하고 있는 HTML 인것을 볼 수 있다.
  • 이 경우 CSR 방식보다는 SEO에 장점을 가질 것이라는 예상을 할 수 있다. (페이지 콘텐츠가 많아 시맨틱 태그를 포함하고 있다면 더욱 그럴것이다.)

그 후 필요한 JS 파일을 다운받는다.

  • 위에서 빨간줄을 이용해 표현한 구간이 SSR의 단점 TTV(Time to view), TTI (Time to Interact) 간극에 포함된다. (HTML 파싱하여 DOM 트리를 구성하는 시간까지 고려하면 더 정확한 시간을 구할 수 있다.)
  • HTML을 서버쪽에서 렌더링하여 보내주어 빠르게 유저가 해당 페이지를 볼 수 있지만, 유저의 이벤트에 따른 상호작용에 필요한 JS 파일을 다운받고 실행시키는데 까지 잠깐의 시간이지만 공백이 발생한다.

그리고 마지막으로 CSR과 SSR의 로드한 파일의 크기를 비교해보자.

  • 위에 CSR 방식의 JS 파일은 크기의 단의가 KB이고, 아래 SSR 방식은 Byte단위 크기이다.
  • 정확한 비교를 위해서는 같은 페이지를 렌더링해야 하지만, 다른 페이지라고 하여도 한번에 불러오는 파일의 크기가 명확하게 차이가 나는 것을 볼 수 있다.
  • 이는 CSR의 경우 한번에 요청으로 번들된 파일을 다운받아 오기 때문이다.
  • 그리고 이것은 초기 진입속도가 SSR 비해 느려지는 이유중의 하나이다. (CSR의 단점)

4. 정리

CSR과 SSR의 기본 개념과 각각의 장단점을 살펴보았다.

조사하고 느낀점은 어떤 방식이 더 우월하다는 것이 없다라고 느꼈다.

페이지 이동이 많고 유저와 상호작용이 많은 넷플릭스의 경우 CSR을 적극적으로 활용하고, 페이지 이동이 적고 SEO를 최적하여 검색 결과 상위에 위치해야 하는 회사 홈페이지의 경우 SSR이 적절할 것이다.

서비스의 성격에 따라 적절한 방식을 채용하고, 또 필요에 따라서 두가지를 섞는 방법도 고려해야 할 것이다.

그리고 이번 주제를 조사하면서 CSR과 SSR를 적절하게 섞을 수 있는 리액트 프레임워크인 ‘NextJS’ 에도 눈길이 갔다.

다음 조사 주제로 좋은 재료인 거 같다.

4.1 참고 자료

--

--