-
웹 렌더링 방식 (SSR, CSR, SSG) 알아보기Frontend 2021. 8. 1. 00:11
초창기 웹 렌더링
초창기에는 모든 웹 페이지가 정적인 페이지였다. 대부분의 로직은 서버에서 수행되었고, 브라우저는 서버로부터 전달받은 정적인 HTML과 CSS를 단순히 렌더링하는 방식으로 동작했다. 즉, 우리가 웹 사이트에 접속하면 브라우저는 서버에 간단한 HTTP 요청을 전송하고, 서버로부터 전달 받은 HTML을 렌더링하는 방식인 것이다. 화면에 어떠한 변화를 주려고 화면을 전환하면 그 때마다 서버로부터 새로운 HTML을 전송 받아서 다시 렌더링해야 했다. 당연히 매 번 처음부터 새로 렌더링하기 때문에 성능적인 문제도 많았고 화면이 전환될 때마다 화면이 깜박이는 등의 문제가 있었다.
Ajax의 등장
그러다 1999년에 자바스크립트를 통해서 서버와 브라우저가 비동기로 데이터를 주고 받을 수 있는 Ajax가 등장하게 되었다. Ajax는 새로운 패러다임의 전환을 일으켰는데, 매 번 전체 페이지에 대한 데이터를 가져올 필요 없이 필요한 부분의 데이터만 불러와서 동적으로 웹 사이트 화면을 변경할 수 있게 된 것이다. 항상 새롭게 렌더링하지 않아도 되기 때문에 깜박임 없이 자연스러운 화면 전환이 가능해졌고, 더 나은 UX를 제공할 수 있게 되었다. 이제 서버에서만 이루어지던 다양한 로직 처리나 HTML 생성을 상당수 클라이언트에서 처리할 수 있게 되었다.
이런 과정 속에서 클라이언트 사이드에서 쉽게 화면 처리를 할 수 있도록 여러 가지 라이브러리나 프레임워크가 만들어지기 시작했다. 2006년에는 jQuery가 등장하면서 어려운 DOM 조작을 쉽게 컨트롤할 수 있게 되었다. 오늘날에는 훨씬 복잡하고 거대해진 웹 어플리케이션을 보다 쉽게 구축할 수 있도록 도와주는 Angular, React, Vue 등의 다양한 프레임워크가 활발하게 사용되고 있다.
Client Side Rendering(CSR)
React와 같은 다양한 프론트엔드 프레임워크들이 유행하면서 클라이언트 사이드에서 전적으로 웹 렌더링을 책임지는 방식이 보편화되었다. 이제 서버에서 아무 내용이 없는 빈 HTML 껍데기를 보내면 클라이언트에서 동적으로 태그들과 스타일을 생성하여 페이지를 채운다. 이렇게 되면 최초에 HTML을 받는 것 외에는 페이지 렌더링을 위해서 별도의 HTTP 통신을 할 필요가 없어진다. 따라서 서버는 오직 Ajax를 통해 필요한 데이터를 주고 받는 역할만 수행한다. 이러한 방식을 Single Page Applications(SPAs)라고 부른다. 즉, 최초에 Single Page만 서버로부터 불러와 렌더링하고 그 이후에는 모든 것을 클라이언트 사이드에서 렌더링하는 어플리케이션이다.
문제는 클라이언트 사이드 렌더링 방식 또한 여러 가지 문제점들을 야기한다는 것이다. 예를 들면 SEO(Search Engine Optimization) 문제가 있다. 구글 크롤러와 같은 여러 웹 크롤러들은 웹 사이트의 HTML을 읽어들이고 인덱싱하여 검색 엔진이 해당 페이지를 잘 찾아낼 수 있도록 한다. 그런데 클라이언트 사이드 렌더링 방식으로 만들어진 웹 사이트는 최초에 빈 HTML만 렌더링하기 때문에 크롤러들이 제대로 컨텐츠를 읽어들일 수 없다는 문제가 있다. (최근에는 대부분의 웹 크롤러들이 클라이언트 사이드에서 필요로하는 자바스크립트를 실행하고 있어 이러한 문제들이 어느 정도 해소되기는 했으나 여전히 완벽하지는 않다.)
그 외에도 페이지 렌더링을 위해 많은 양의 자바스크립트 코드가 실행되다보니 성능적인 이슈도 생겨났다. 특히 클라이언트 사이드 렌더링 방식은 첫 페이지 로딩이 느리다. 왜냐하면 최초로 서버에서 받은 빈 HTML은 페이지 로드에 필요한 자바스크립트를 참조하고 있는데, 클라이언트에서 렌더링할 때 페이지 로드에 필요한 자바스크립트 코드, 프레임워크나 라이브러리 소스 코드를 모두 불러오기 때문이다. (물론 페이지를 한 번 렌더링하고 난 이후에는 필요한 부분만 렌더링하기 때문에 비교적 효율적이다.)
이러한 문제점들이 대두되자 다시 서버 사이드 렌더링을 사용하자는 움직임이 일어났다. 물론 예전과 같은 방식으로 서버 언어를 사용하여 마크업을 생성하지는 않는다. 이제 React와 같은 모던 자바스크립트 라이브러리나 프레임워크를 사용하여 서버 사이드 렌더링을 할 수 있기 때문이다. 서버 사이드 렌더링은 마크업 생성을 클라이언트 디바이스에서 하는 것이 아니라 서버에서 한다는 점이 다르다. 이 방식은 클라이언트 사이드 렌더링보다 더 빠르고 SEO 문제를 해결해준다는 장점이 있다.
Modern Server Side Rendering(SSR)
서버 사이드 렌더링은 위에서도 언급했지만 다음 그림과 같이 진행된다. 브라우저가 서버에 페이지를 요청하면 서버가 필요한 데이터로 HTML을 구성하여 브라우저에 전송한다. 그러면 브라우저에서 응답으로 받은 HTML을 그대로 렌더링한다.
애초에 서버에서 모든 컨텐츠를 로드하여 전달하기 때문에 SEO 면에서 이점이 있다. 또한 첫 페이지 로딩이 빨라지는데, 이미 페이지 로드에 필요한 데이터를 서버에서 미리 불러왔기 때문에 클라이언트 사이드에서 별도의 자바스트립트 코드를 더 불러올 필요가 없기 때문이다.
그러나 서버 사이드 렌더링 또한 장점만 존재하는 것은 아니다. 서버에서 매 번 동적으로 계산하여 페이지를 렌더링하기 때문에 서버 부하가 생겨날 수 있으며 서버 비용도 많이 든다. 또한 서버로부터 매 번 페이지를 새로 전달받기 때문에 서버에서 페이지를 생성하는 시간이 소요된다.
사람들은 이제 이런 생각을 하기 시작했다. 유저의 데이터에 따라 다르게 보여주는 페이지의 경우는 매 번 서버에서 동적으로 생성할 필요가 있지만, 모든 유저에게 항상 같은 내용을 보여주는 페이지는 매 번 동적으로 생성할 필요가 없지 않을까? 바로 이러한 질문에서 Static Site Generation이 탄생했다.
Static Site Generation(SSG)
예를 들어 회사 소개 페이지같은 경우 모든 유저에게 항상 동일한 화면이 보이기 때문에 매 번 동적으로 생성할 필요가 없다. 즉, 한 번만 생성한 이후에 CDN으로 어딘가에 저장해두고 필요할 때마다 로드하면 되는 것이다. 웹 개발에 React와 같은 프레임워크를 사용하고 있다면 Next.js나 Gatsby.js 등의 도움을 빌려 아주 쉽게 정적 페이지를 생성할 수 있다.
SSG는 다음과 같은 과정으로 생성된다. React에 Next.js나 Gatsby.js 등의 라이브러리를 사용하여 개발한 정적 웹 페이지를 빌드한 후 산출물을 CDN으로 배포한다. 이제 필요할 때마다 CDN으로부터 전달받은 정적 페이지를 유저에게 빠르게 제공한다.
그렇다면 이러한 정적 페이지가 동적으로 매 번 새롭게 추가되는 경우에는 어떻게 될까? 예를 들어 Gatsby로 개발된 블로그에 새로운 포스트를 계속 업로드한다고 생각해보자. 새롭게 포스트가 업로드되면 그 때 마다 블로그는 다시 빌드되어야 한다. 다행히도 이러한 작업을 매 번 수동으로 직접 해 줄 필요는 없다. 현대 기술을 사용하면 정적 페이지에 무언가 변화가 생길 때마다 매우 쉽게 다시 빌드하여 배포할 수 있다.
Jamstack
SSG와 함께 Jamstack이라는 새로운 웹 아키텍쳐가 생겨났다. Jamstack에서 Jam은 JavaScript, API, Markup의 약자이다. Jamstack은 서버를 전혀 사용하지 않고 정적인 페이지를 만들어 저렴한 비용으로 호스팅하는 방식을 말한다. 즉, 모든 웹 페이지는 빌드 타임에 정적 페이지로 최적화되며 CDN으로부터 서빙되어 적은 비용으로 쉽게 관리된다. 높은 유지 비용이 필요한 서버를 사용하지 않아도 된다는 점에서 많은 이점이 있다. Jamstack 개발을 쉽게 할 수 있도록 도와주는 여러 기술들이 존재하는데 Gatsby, Hugo, Jekyll, Next.js, Netlify 등이 있다. 이런 기술들을 사용하여 배포된 정적 블로그에 새로운 글이 업로드되면 자동으로 새로운 빌드와 배포가 진행되며, 그 과정이 모두 끝나면 유저에게 새로운 컨텐츠가 보여지게 된다.
지금까지 웹을 렌더링하는 다양한 방식에 대해 살펴보았다. 웹 사이트를 개발하다보면 특정 페이지는 서버 사이드에서 렌더링하고, 특정 페이지는 정적 페이지로 렌더링하고 싶을 때가 있다. 물론 클라이언트 사이드에서 렌더링하고 싶을 수도 있다. Next.js와 같은 기술을 사용하면 페이지 별로 원하는 방식을 선택하여 개발할 수 있다. 요즘 회사에서 내가 담당한 서비스를 모두 Next.js로 마이그레이션하는 작업을 진행하고 있는데 기존의 클라이언트 사이드 렌더링 방식으로만 작업되었을 때보다 훨씬 더 빠릿해진 페이지를 보며 많은 뿌듯함을 느끼고 있다.
Reference
모던 자바스크립트 Deep Dive / 이웅모 지음
https://betterprogramming.pub/server-side-rendering-vs-static-site-generation-53a34872728c
반응형'Frontend' 카테고리의 다른 글
[Kasra Khosravi] Why you should use SWC (and not Babel) 한글 번역 (252) 2022.03.06 자바스크립트, 동기 vs 비동기 (Synchronous vs Asynchronous) (252) 2021.08.08 Integration 테스트 코드가 중요한 이유 (React Testing Library, MSW로 작성해보기) (127) 2021.07.25 [Kent C. Dodds] 어플리케이션 상태 관리 (Application State Management with React 한글 번역) (254) 2021.05.09 location.href vs location.assign vs location.replace 차이점 (254) 2021.05.09 COMMENT