📖 Introduction
CSR? SSR? 오늘 다시 한번 그게 뭔지 파혜쳐보자.
"React는 CSR 기반의 SPA를 구축하기 위한 프레임워크다." 라는 말을 정말 많이도 들었지만, 여태까지 필자는 이것들이 뭔 차이점이 있는지를 잘 알지 못했다. CSR이랑 SPA랑 결국 한 페이지에서 렌더링 되는 거니까 같은 의미가 아닐까라고만 생각했지, 정확하게 이것들이 무슨 차이가 있는지를 근본적으로 알지 못했다.
최근 우연한 기회에 필자가 React 스터디를 주도하게 되었는데, 막상 껍질을 까고 보니 나는 정말 React를 왜 쓰는지 알고 있나 싶은 생각이 들었다. 따라서 이를 명확히 알기 위해 CSR, SSR, SPA, MPA 개념을 짚고 넘어가기로 결심하고, 위 개념들에 대한 나의 조사 결과를 정리하기로 했다.
✒️ Static Web Page
1. Static Site 란?
- 서버에서 사전에 렌더링 된 정적 리소스로 만들어진 사이트.
- 과거에는 서버에서 잘 만들어진 HTML를 클라이언트에게 전송하였음.
- 초창기 웹 사이트는 단순한 정보만을 제공하고, 많은 Interaction을 요구하지 않았기 때문.
- 이때는 거의 HTML과 CSS로만 모든 페이지를 구축하였음. JS는 나중에 나옴.
1-1. Static Web Page 의 장단점은?
- 장점
- 첫 요청에 대한 파일만 전송하면 되기에 빠르다.
- 단순한 HTML 문서만으로 웹을 구축하기에 서버의 트래픽이 상대적으로 적다.
- 단점
- 저장된 정적 페이지만을 보여주기에 단순한 서비스만 제공이 가능하다.
- 페이지 내에서 다른 링크를 클릭할 경우, HTML을 다시 받아 로딩하므로 "깜빡임" 현상이 발생한다.
- 작은 변화임에도 페이지 하나를 통째로 다시 로딩한 후 제공해야 하므로, 재사용성이 떨어진다.
HTML (Hyper Text Markup Language) 란?
- 용어의 정의
Hyper Text
는 하이퍼 링크를 사용하여 사용자가 원하는 순서에 따라 다른 문서로 접근하는 텍스트를 의미.
Markup Language
는 태그를 이용하여 문서나 데이터의 구조를 명시하는 언어를 의미.
- 이를 종합하면
HTML
은 웹 페이지의 구조 혹은 데이터 작성을 위해 쓰이는 마크업 언어이다.
- 쓰이는 이유는?
- 웹 브라우저에 내가 제작한 컨텐츠를 정확하게 보여주기 위해 마크업 언어가 쓰임.
- 다른 사용자들과의 원활한 협업을 위해 공통된 양식을 사용할 필요성이 커졌음.
- 정보를 수집하는 검색 엔진에서 자료를 수집할 수 있도록 태그를 통해 각각의 정보들을 명시해야 하기 때문.
✒️ Dynamic Web Page
1. Dynamic Web Page 란?
- 기술이 발전하면서 보다 폭넓은 서비스를 제공하기 위해서는 동적인 처리가 필요해졌다.
- 초기 렌더링 이후 서버로부터 필요한 데이터를 추가적으로 요청하여, 페이지 일부를 변경하는 기술이 등장.
- 웹 페이지에서 필요한 정보가 있을 경우, 이를 동적으로 서버에서부터 받아 일부를 변경시키는 페이지다.
2. AJAX (Asynchronous JavaScript and XML)
AJAX (Asynchronous JavaScript and XML)
가 등장하면서, 서버와 브라우저가 비동기적으로 통신하기 용이해짐.
- 이때 브라우저와 서버 간에는
JSON
, XML
, HTML
등과 같은 데이터를 비동기로 주고 받을 수 있음.
- 이제는 새로고침을 하지 않고 하나의 페이지에서 동적으로 필요한 부분만 변경이 가능해지게 됨. (SPA)
XMLHttpRequest
객체를 사용하여 Ajax 통신을 구현한 경우.
XMLHttpRequest
는 가장 초기에 서버로부터 데이터를 동적으로 바인딩하기 위해 쓰이는 객체.
var xhr = new XMLHTtpRequest();
xhr.open('GET', './time.php');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
document.querySelector('#time').innerHTML = xhr.responseText;
}
};
xhr.send();
- jQuery를 활용하여 Ajax 통신을 구현한 경우.
var serverAddress = 'https://hacker-news.firebaseio.com/v0/topstories.json';
$.ajax({
url: ,
type: 'GET',
success: function onData (data) {
console.log(data);
},
error: function onError (error) {
console.error(error);
}
});
✒️ Client, Server Side Rendering
1. Client Side Rendering (CSR)
- 기술이 발전하면서 웹 페이지에서 제공하는 서비스가 복잡해짐으로서, AJAX만으로는 모든 로직을 처리하기가 어려워짐.
- 이를 위해 React, Vue, Angular 와 같은 프레임워크가 등장하면서, 클라이언트에서 렌더링을 진행하는 경우가 많아짐.
- 이제는 서버에서 최소한의 HTML을 받고, 내부에 위치한 script 태그로 JS 파일을 받아 클라이언트에서 페이지를 렌더링하는 형식으로 변화.
- 초기에 애플리케이션 가동에 필요한 JS 파일의 크기가 크기에, 적극적인 코드 분할 (Code Splitting) 을 고려해야 함.
1-1. CSR의 동작 방식
- 사용자가 웹 페이지를 방문할 경우, 브라우저는 최소한의 HTML 파일을 다운로드한다.
- 브라우저는 script 태그를 통해 JS 번들 파일을 다운로드 하고, Ajax를 통해 동적으로 컨텐츠를 가져오며 화면을 렌더링한다.
- 이후 사용자가 페이지를 이동할 경우, 별도의 HTML을 받지 않고 사전에 받은 JS 파일만을 활용하여 렌더링을 진행한다.
1-2. CSR의 장단점
- 장점
- 초기 렌더링 이후에 진행되는 렌더링의 경우 로딩 속도가 훨씬 빠르다. 이미 페이지 로딩에 필요한 모든 자원을 받은 상태기 때문이다.
- 서버와의 통신 과정에서 페이지의 UI를 다시 그릴 필요 없이, 동적으로 일부분만 변경시킬 수 있다.
- 단점
- 초기에 구동에 필요한 파일을 전부 받아야 하기에, 그만큼의 초기 페이지 구동 속도가 느리다. (FP, FCP 느림)
- 이 경우 페이지가 온전히 로딩되기 전까지는 하얀 화면만을 봐야 하기에, 사용자 경험이 좋지 못함.
- SEO (Search Engine Optimization), 즉 검색 엔진 최적화를 진행하기 어려움. 검색 엔진이 처음 페이지를 방문할 경우 HTML이 빈 경우가 많기 때문.
- 페이지 메타 데이터의 변경을 위한 추가 작업이 필요함. 다른 페이지로의 이전을 진행할 경우 이를 인지시키기 위해 각 페이지에 대한 메타 데이터를 동적으로 렌더링 해야 하기 때문.
- 클라이언트의 PC 성능에 따라 렌더링 속도가 좌우되기 때문에, PC 성능이 좋지 못할 경우 렌더링을 빠르게 하지 못할 확률이 높음.
2. Server Side Rendering (SSR)
- 서버에서 사전에 렌더링된 파일을 클라이언트에게 전송하고, 클라이언트는 이를 즉시 렌더링하는 방식이다.
- 단, JS의 경우 정적 리소스 (HTML, CSS) 가 렌더링 된 이후 적용되기에 JS가 모두 적용되기 전에는 조작이 불가능하다.
2-1. SSR의 동작 방식
- 사용자가 웹 페이지를 방문할 경우, 서버는 이를 확인하고 브라우저에게 제공할 HTML 컨텐츠를 컴파일한다.
- 컴파일된 HTML은 브라우저에 제공되며, 브라우저는 이를 다운로드하고 렌더링하여 사용자가 이를 볼 수 있도록 한다.
- 이후 JS 파일을 다운로드 받은 후 실행하여 사용자와 페이지 간의 인터렉션을 가능하게끔 한다.
- 사용자가 다른 페이지로 이동을 진행할 경우, 1~3번의 과정을 반복한다.
2-2. SSR의 장단점
- 장점
- 초기 페이지 로딩 속도가 빠르다. (FP, FCP가 빠르다) 서버에서 사전에 렌더링 된 HTML 파일을 브라우저에서 로딩하기 때문이다.
- 서버에서 페이지 로직 및 렌더링을 사전에 실행할 경우, JS 파일을 많이 보낼 필요가 없어지므로 TTI 또한 상대적으로 빠르게 수행할 수 있다.
- 이미 사전에 렌더링 된 HTML을 크롤링 봇이 방문하므로, SEO 또한 효율적으로 적용할 수 있다.
- 서버에서 완성된 페이지를 브라우저에서 보여주기만 하면 되므로, 클라이언트의 PC 성능에 크게 영향을 받지 않는다.
- 단점
- 페이지를 이동할 때마다 매번 새로운 HTML을 받아야 하므로
TTFB
(Time To First Byte) 가 느리다.
- 서버에서 각 페이지에 대한 정적 리소스를 보내야 하기 때문에 이를 위한 서버 호스팅이 필수적이다.
- 각 페이지를 로드하는 과정이 오래 걸린다면, 되려 사용자 경험을 해칠 수 있다.
- 각 요청에 대한 HTML 파일을 그때 그때 렌더링 해야 하기 때문에, CDN을 활용한 캐싱 전략을 사용할 수 없다.
TTFB(Time to First Byte) 는 뭘까?
- TTFB는 HTTP 요청을 보낼 경우, 서버에서부터 첫번째 Byte (정보) 가 오기까지 걸리는 시간을 의미합니다.
- CSR의 경우 처음 렌더링 이후부터는 요청이 필요한 경우에만 서버에서 필요한 데이터만을 받아오기에 TTFB가 빠릅니다.
- 하지만 SSR의 경우 매 페이지 이동 시마다 페이지 렌더링에 필요한 리소스를 받아오기에 상대적으로 TTFB가 느립니다.
FP? FCP? 이것들은 또 뭔가?
- FP (First Paint) : 첫번째 픽셀 이 스크린에 Paint 되었을 때의 시간을 의미한다.
- FCP (First Contentful Paint) : DOM에 속한 컨텐츠의 일부가 스크린에 Paint 되었을 때의 시간을 의미한다.
- FP, FCP의 경우 Chrome의 timing API로 추적이 가능하며, GA 같은 도구로 리포팅이 가능하다.
- 즉 FP와 FCP의 사용 목적은 얼마나 빨리 화면이 렌더링 되는지를 측정하기 위함이다.
CDN (Content Delivery Network) 이란?
서버와 사용자 사이의 물리적인 거리를 좁혀 컨텐츠 로딩 속도를 최소화 하기 위한 전송 기법. 보통 여러 곳에 캐시 서버를 둔 후 이 중에서 사용자와 가장 가까운 서버를 찾아 요청한 컨텐츠를 제공한다.
✒️ Static Site Generator, Universal Rendering
1. SSG (Static Site Generator)
- SSR 처럼 서버로부터 렌더링된 HTML을 받아오지만, HTML의 생성 시점이 빌드 타임이라는 것이 SSR과의 차이점이다.
- SSR의 경우 요청이 들어오면 그때마다 필요한 HTML을 렌더링해야 하지만, SSG의 경우 HTML을 사전에 빌드 타임에서 생성하였으므로 이를 전송만 하면 된다.
- 정적 페이지를 제공하는 것은 아니다. 빌드 타임에 생성된 HTML 파일이 정적이라는 의미다. FCP 이후 JS 파일을 받아 인터렉션을 제공할 수도 있다.
- React로 개발된 애플리케이션을 Gatsby 라이브러리를 통해 빌드하여 정적인 사이트들로 변환시켜준다.
1-1. SSG의 동작 과정
- 사용자가 웹 페이지를 방문할 경우, 엣지 캐싱된 HTML 파일을 클라이언트로 반환해준다.
- 브라우저는 HTML을 받고 이를 띄워 사용자가 사이트를 볼 수 있도록 한다.
엣지 캐싱 (Edge Caching) 이란?
클라이언트의 컴퓨터에 최대한 가깝게 (물리적인 거리) 콘텐츠를 저장하여 대기 시간을 줄이기 위해 캐싱 서버를 사용하는 것. 주로 CDN 전략을 많이 사용함.
1-2. SSG의 장단점.
- 장점
- 빌드 타임에 각 페이지 별로 HTML 파일이 생성되기 때문에 서버에서 사전 렌더링을 하지 않아도 되므로 빠른 FP, FCP 를 제공.
- 이미 사전에 렌더링 된 HTML을 크롤링 봇이 방문하므로, SEO 또한 효율적으로 적용할 수 있다.
- 단점
- 모든 페이지 (URL) 에 대한 HTML을 생성해야 한다. 따라서 동적으로 변하는 URL 들에 대한 대응이 어렵다.
2. Universal Rendering
- SSR을 통해 초기에 빠른 FCP를 구현한 이후, 클라이언트 단위에서
hydration
기법을 통해 JS 파일을 적용하여 인터렉션을 가능하게끔 하는 방식.
- 초기 로딩 시에는 SSR처럼 작동하고, 이후에는 CSR로 작동하는 방식이며 Next.js, Nuxt.js 와 같은 프레임워크를 사용한다.
- CSR 기법을 사용하는 React의 경우, 초기 로딩 시에는 텅 빈 화면을 보여주고 렌더링 과정에서 HTML을 구축하고 번들링된 JS 코드를 적용한다.
- Universal Rendering의 경우 서버에서 사전에 필요한 HTML을 렌더링하고, 이후 클라이언트에서 번들링된 JS 코드를 적용한다.
Hydration 이란?
JS 코드 내의 "이벤트 핸들러" 함수들을 정적인 DOM 노드들에 붙여서 동적으로 상호작용이 가능하도록 바꾸어주는 기능이다.
즉, 사용자가 단순히 웹 사이트의 화면을 보는 것이 아니라 실질적인 상호작용을 가능하게끔 하는 과정이라고 생각하면 된다.
2-1. Universal Rendering의 동작 과정
- 사용자가 웹 페이지를 방문할 경우, 서버는 이를 확인하고 브라우저에게 제공할 HTML 컨텐츠를 컴파일한다.
- 컴파일된 HTML은 브라우저에 제공되며, 브라우저는 이를 다운로드하고 렌더링하여 사용자가 이를 볼 수 있도록 한다.
- 이후 JS 파일을 다운로드 받은 후 실행하여 사용자와 페이지 간의 인터렉션을 가능하게끔 한다.
- 사용자가 다른 페이지로 이동을 진행할 경우, 다운로드 받은 JS 파일을 활용하여 렌더링 (CSR) 을 진행한다.
2-2. Universal Rendering의 장단점.
- 장점
- SSR 기법을 통해 빠른 FCP를 지원하므로 TTV가 빠르다. 이는 기존의 CSR이 가진 단점을 상쇄할 수 있다.
- 초기 렌더링 이후에는 사전에 받은 JS 번들 파일을 활용하여 렌더링이 진행되므로 SSR의 단점도 상쇄할 수 있다.
- 단점
- 서버에서 초기 렌더링을 수행하므로 CSR을 기반으로 개발을 진행할 경우 여러 문제점에 부딪힐 수 있다.
- 이로 인한 러닝 커브가 존재한다. 필자의 경우 Next.js를 적용하는 과정에서 여러 Hydration 오류를 만났다..
- 결국 서버에서 렌더링을 수행해야 하므로 CSR과 달리 별도의 서버가 필요해진다.
- TTV가 빠르더라도 번들링된 JS 파일을 추가로 받아 인터렉션을 적용하는 과정이 필요하므로 TTI가 상대적으로 늦어진다.
- 이로 인해 화면은 보이지만 사용자가 상호작용 할 수 없는 기간이 존재하기에, 사용자 측면에서 효율이 떨어진다.
✒️ Single, Multiple Page Application
1. SPA (Single Page Application)
- 하나의 페이지에서 새로운 페이지를 불러오지 않고, 필요한 부분만 동적으로 변경하는 애플리케이션을 SPA 라고 함.
- 초기의 SPA 는 AJAX 통신을 활용하여 필요한 데이터를 동적으로 바인딩하는 방식이었음.
- 하지만 모든 과정을 순수 AJAX로 구현하기에는 너무나 많은 비용이 들기에, 이를 도와주는 프레임워크들이 대두되었음.
- 현재는 React, Vue, Angular 와 같은 프레임워크가 SPA 서비스를 위해 많이 쓰이고 있음.
TTV? TTL? 이것들은 또 뭔가?
- TTV (Time To View) : 사용자가 어플리케이션 화면을
"보기까지"
걸리는 시간.
- TTI (Time To Interact) : 사용자가 어플리케이션 화면과
"상호작용"
할 수 있기까지 걸리는 시간.
- 즉 TTV가 빠르면 화면이 빠르게 보이는 것이며, TTI이 빠르다면 웹을 빠르게 사용할 수 있다는 것이다.
1-1. SPA의 장단점
- 장점
- 초반 렌더링 시, 애플리케이션 가동에 필요한 정적 파일을 받아오므로 이후 새로고침을 할 필요가 없음.
- 그렇기에 기존 MPA 에서 느꼈던 딱딱 끊기는 모습이 보이지 않음, 부드럽고 자연스러운 사용자 경험을 느끼게 해줌.
- TTV와 TTI가 동시에 시작되기에, 사용자는 페이지가 로딩되자마자 곧바로 애플리케이션을 사용할 수 있음.
- 또한 이후의 동작에서 추가적인 정보가 필요한 경우에는 필요한 리소스만 요청하기에, 서버의 부담이 상대적으로 적어진다.
- 기존에는 서버에서 렌더링 된 페이지를 받았다면, SPA의 경우 최초 요청 이후 내부에서 렌더링을 하기에 서버의 부담을 분산시킨다.
- 단점
- 초기에 애플리케이션 가동에 필요한 대부분의 리소스를 받아야 하기에, 곧바로 페이지를 로딩하지 못한다.
- 즉 TTV (Time To View) 가 상대적으로 늦음. 페이지 렌더링 전까지 사용자는 텅 빈 화면만 바라보아야 함.
- 이를 해결하기 위해 많은 양의 JS 코드를 번들링 하여 분할 제공하는 Code Splitting 기법이 있으나, 근본적인 해결책은 아님.
- SEO (Search Engine Optimization), 즉 검색 엔진 최적화를 진행하기 어려움. 서버에는 초기 HTML이 비어있는 경우가 많기 때문.
- 사용자의 정보를 클라이언트 측에서 관리할 경우, 보안 이슈가 발생할 수 있음. (저장할 공간이 쿠키, 스토리지 뿐)
2. MPA (Multiple Page Application)
- 여러 개의 페이지로 이루어진 어플리케이션이며, 새로운 페이지를 요청할 때마다 서버에서 렌더링 된 정적 리소스를 전달함.
- 현재 페이지에서 다른 페이지로 이동하거나, 새로고침이 진행될 경우 서버에서 페이지를 다시 렌더링 해야 한다.
2-1. MPA의 장단점
- 장점
- 서버에서 사전에 렌더링 된 정적 리소스를 받음으로서 빠르게 애플리케이션 화면을 띄울 수 있다.
- 즉 TTV 가 SPA에 비해 월등히 빠르다. 클라이언트에서는 사전에 렌더링된 페이지를 띄우기만 하면 되기 때문이다.
- SEO (Search Engine Optimization), 즉 검색 엔진 최적화를 진행하기 쉬움, 서버에서 사전에 만들어진 HTML을 전달받기 때문.
- 단점
- 화면을 빠르게 띄울 수 있으나, 동적인 인터렉션을 담당하는 JS 파일을 적용하기까지의 텀이 있음.
- 즉 TTI (Time To Interact) 가 TTV보다 상대적으로 늦고, 그 시간 동안 사용자는 어떠한 인터렉션도 진행할 수 없음
- 페이지를 이동할 때마다 결국 서버에서 사전에 렌더링 된 파일을 받아야 하기에, 매 요청마다 깜빡임 현상이 발생함.
- 서버에서 매 요청 시에 보내야 할 데이터의 사이즈가 커짐으로서, 서버 트래픽이 상승할 가능성이 높음.
✒️ SPA, MPA, CSR, SSR?
1. SPA = CSR? 차이점은 뭘까?
- SPA와 CSR은 같은 개념이 아니다. 정확히는 SPA를 구현하기 위해 CSR 방식이 쓰이는 것이다.
SPA vs MPA
는 애플리케이션 구동을 위해 페이지를 하나만 쓰는지, 여러 개를 쓰는지에 대한 차이다.
CSR vs SSR
은 페이지의 렌더링이 클라이언트에서 일어나는지, 서버에서 일어나는지에 대한 차이다.
- 따라서 SPA는 첫 페이지만 서버에서 받아오고 이후의 변화는 동적으로 처리하기 위해 CSR 방식을 채택한다.
- 반대로 MPA의 경우 페이지가 달라질 때마다 서버에서 렌더링 된 리소스를 받아오기 위해 SSR 방식을 채택한다.
2. SPA는 CSR로, MPA는 SSR로?
- SPA는 SSR로 구현이 어렵고, MPA는 CSR로 구현이 어렵다.
- 하지만 SPA에서 첫 로딩의 경우에만 SSR을 쓰고, 이후의 요청에 대해서는 CSR 방식을 쓸 수 있다. (Next.js)
- Universal Rendering 을 사용할 경우 초기 HTML이 비어 있지 않아 SEO를 최적화 할 수 있다는 장점이 있다.