goongoguma's blog

Server-Side Rendering vs. Static Site Generation (번역)

이 분야에서는 많은 유행어를 보게됩니다. 그 중에는 Static Site Generation (SSG)과 Server Side Rendering (SSR)이 있습니다.

[Server-Side Rendering vs. Static Site Generation_1.jpg]

이 글에서 저는 SSR과 SSG에 대해 자세히 설명하고 어떤 상황에서 도움이 될 수 있는지 배워보도록 하겠습니다. 먼저 두 개념의 간단한 역사부터 시작한 후, Next.js와 Gatsby와 같은 기술에서 실제로 어떻게 사용되는지 보겠습니다.

In the Beginning…

처음에는 정적인(static) 웹 페이지만 존재했습니다. 동적인 부분은 하나 없었죠. 순수하게 정적인 HTML 문서를 클라이언트에서 받는 형식이었습니다.

웹 사이트에 접속했을때, 간단한 HTTP 리퀘스트를 클라이언트에서 서버로 요청(request)하고 서버는 브라우저가 화면에 보여줄 HTML로 반응(response)하는 형식이었습니다. 간단하죠?

그러다가 PHP와 같은 동적 랜더링과 템플릿 엔진이 만들어졌습니다.

이 서버사이드 기술들은 클라이언트에서 동적인 HTML을 받을 수 있게 해줍니다. 클라이언트에서 보내는 모든 HTTP 요청들은 응용 서버(application 서버)를 통과하는데요, 이때 유저의 이름이나 오늘 날짜 그리고 DB에 있는 데이터와 같이 작은 동적인 조각들이 추가되게 됩니다.

이것이 전통적인 방식의 서버사이드 랜더링입니다. 클라이언트(브라우저)에서 실제로 보여질 HTML만 서버에서 가져올뿐이죠.

AJAX and the Beginning of the Front-End Chaos

AJAX의 등장과 함께, 클라이언트에서는 페이지를 새로고침 할 필요없이 데이터를 비동기적으로 가져올 수 있게되었고 사용자 경험에 있어서 큰 발전을 이루었습니다 - 걸리적 거리는 화면 깜빡임 현상이 사라졌거든요. 그런데 잠깐 생각해봐야할것이 있습니다.

비동기 데이터, 새로운 데이터, 새로운 페이지, 새로운 프론트엔드 컴포넌트들. 이제 프론트엔드는 화면을 랜더해주기 위해 HTML을 생성 해야하는 책임을 지게 된겁니다! 안녕, 클라이언트 사이드 랜더링!

클라이언트 사이드에서 비주얼 마크업(visual markup)을 랜더해야하는 필요성에 따라 다양한 라이브러리와 프레임워크들이 등장하기 시작했습니다. 그 중 잘 알려진 것이 바로 jQuery입니다. 요즘에는 리액트나 뷰, 앵귤러와 같은 기술들을 주로 사용합니다.

새로운 라이브러리와 프레임워크들이 등장함에 따라 소위 말하는 프론트엔드 피로(front-end fatigue)가 발생하기 시작했습니다. 다행스럽게도, 리액트와 뷰와 같이 몇몇 라이브러리들이 제일 인기가 많습니다.

Single Page Applications and Some Problems

클라이언트 사이드에서 비주얼 마크업(visual markup)을 생성하는 일을 맡게되자 예전처럼 서버에서 랜더해주던 방식을 기피하기 시작했습니다.

모든 HTML은 클라이언트 사이드에서 생성되기 시작했죠. 서버에서는 브라우저에게 빈 HTML과 AJAX를 이용한 JSON과 XML같은 데이터를 보내주었고, 선호하는 라이브러리/프레임워크를 이용해 태그들과 스타일로 페이지를 생성했습니다. 이것은 물론 클라이언트 사이드 자바스크립트이기에 가능했던 일이었습니다.

오로지 클라이언트 사이드에서 랜더가 되고 AJAX를 이용해 데이터 받는 일을 제외하곤 서버와의 통신이 필요없는 Single Page Applications(SPAs)이 등장하기 했습니다.

하지만 불행하게도, 클라이언트 사이드 페이지 전체를 랜더하는 방법은 서버사이드와 다른 문제를 야기했습니다. 바로 SEO(search engine optimization)문제입니다.

구글의 웹 크롤러가 웹사이트들을 읽고 색인(indexed)을 하는데(그래서 여러분의 웹사이트가 구글에서 검색이 가능한겁니다) 이 ‘로봇’이 아직 랜더 되지않은 HTML을 발견하지 못할 수 있기 때문이죠. 구글이나 다른 검색 엔진들이 자바스크립트를 이용해 나중에 컨텐츠를 랜더하게될 루트 HTML태그만 찾을 수 있을 것이라는 걱정이 있었습니다. 근본적으로 크롤러가 빈 페이지만 발견할 수 있다는 거죠.

지금은 상황이 조금 나아졌습니다. 대부분의 웹 크롤러나 인덱서들이 클라이언트 사이드에서 필요한 자바스크립트를 실행하고 있거든요.

두번째 문제는 성능(performance)입니다. 페이지를 랜더하기 위해서는 (아주 많은 양의)자바스크립트 실행이 필요한데요, 이런 이유로 속도가 느려질 수 있습니다. 낮은 성능의 CPU가 장착되어있는 핸드폰에서 웹서핑을 할 때 많이 발생하는 현상입니다.

그래서 다시한번 서버사이드 랜더링을 생각했습니다.

Back to Our Origins

서버사이드 랜더링이 다시 유행하기 시작했습니다.

그런데 이제는 템플릿 엔진이나 서버사이드 프로그래밍 언어를 사용해 마크업을 하지 않습니다. 리액트와 같은 자바스크립트 라이브러리나 프레임 워크를 사용하고있죠. 위 두개 방법의 차이점은 클라이언트가 아닌 서버에서 마크업이 생성된다는 점입니다.

이 방법은 속도가 좀 더 빠르기도 하지만 SEO 문제 해결에 초점을 맞췄습니다. 웹 크롤러가 웹 페이지를 요청했다면, 페이지 전체가 랜더된 채로 가져올겁니다. 더 이상 클라이언트 사이드에서 페이지를 랜더하기 위해 자바스크립트의 실행이 필요없다는거죠. 서버에 페이지를 요청할 때 마다 모든 것을 다 해줍니다.

위에서 서버사이드 렌더링를 이야기 했을때, 이미 이야기했던 내용들입니다. 웹 페이지 생성, 서버 사이드, 모던 자바스크립트 라이브러리와 프레임 워크를 이용한 모든 네트워크 요청들말이죠.

Server Side Rendering (SSR)

UI의 서버사이드 랜더링을 이해하기 위해서는 서버에 대해 알고있어야 합니다.

서버사이드 랜더링은 SPA와 같은 클라이언트 사이드 랜더링이 필요하지 않습니다. 클라이언트 사이드 프로젝트들은 캐시(cached)되고 CDNs (Content Delivery Networks)에 쉽게 저장이 됩니다. 클라이언트 사이드 프로젝트를 호스팅하기 위해 가상머신이나 쿠버네티스 팟(pods)을 사용해서는 안되죠. 이때는 SSR이 필요합니다.

서버의 비용이 비싸진다는건 서버사이드 랜더링에 있어서 잠재적인 단점입니다.

SSR이 어떻게 동작하는지 다시 한번 복습해볼까요?

  1. 유저 에이전트(브라우저)가 페이지를 요청합니다.
  2. 서버가 HTML페이지를 생성 후 브라우저에 보내줍니다.
  3. 브라우저는 받은 HTML을 랜더합니다.

여기서 중요한 질문이 하나 있습니다. 만약에 서버에서 보내주는 HTML이 항상 같다면 왜 매 요청마다 새로운 페이지를 생성해야하죠?

좋은 질문입니다! 이 부분이 바로 서버사이드 랜더링과 정적 사이트 생성(Static Site Generation)과의 차이점입니다.

Dynamic Content in SSR

만약에 생성이 된 페이지가 유저와 관련된 컨텐츠들을 담고있는 부분이라면, 서버사이드 랜더링을 사용하고 각각의 유저(각각의 요청)에 맞게 페이지를 새로 생성하는게 맞겠죠.

하지만 만약 화면에 보여지는 결과가 항상 같다면(예시로 About페이지를 생각해보세요), 페이지를 항상 다시 생성하는건 말이 안되죠. 같은 결과값들은 CDN과 같이 어디엔가 저장(이라 쓰고 chached라 읽는다)된 정적인 리소스로서 세계 어디에서는 빠르게 보여질 수 있습니다.

Static Websites

다시 처음으로 돌아왔네요!

정적인 웹 페이지 제공은 웹 세계에서 제일 처음 사용한 방법입니다. 말 그대로 서버에 저장해놓았다가 클라이언트가 원할때 보여주는 방식입니다.

해당 방식은 정적 사이트 생성(Static Site Generation)에도 똑같이 적용됩니다. 그러나 일반적인 방식의 HTML과 CSS를 사용하는것 대신, HTML, JSX, CSS, 자바스크립트, 트랜스파일러, 번들러를 사용해 정적인 결과를 만들어 내는 리액트나 뷰, 앵귤러와 같은 도구를 사용합니다.

동적인 부분이 많이 없고 유저마다 데이터를 다르게 보여주기 위해서 정적 사이트 생성 방법을 추천합니다.

아래는 정적인 웹 페이지 세팅방법입니다.

  1. Next.js나 Gatsby와 같이 가장 선호하는 프론트엔드 라이브러리에서 정적인 빌드의 결과를 얻는습니다. 여기에는 모든 정적인 assets들을 가지고있습니다.
  2. CDN에 올리세요(Host it on a CDN)(비싼 서버 필요없음)
  3. 빠르고 유연한 프론트엔드가 완성되었습니다.

위의 예시로 레스토랑 웹페이지나 블로그와 같은 포트폴리오를 생각하시면 됩니다.

그냥 블로그로 예시를 들어보죠. 블로그를 한다면 글을 올려야겠죠? 그런데 동적으로 작동하네요, 그렇죠? 서버사이드 랜더링을 사용해야겠네요.

여기서 잠깐 멈춰봅시다.

현재 기술로는 정적인 웹페이지는 무엇인가 변화가 있었을때 쉽게 다시 빌드되고 재배포 될 수 있습니다. 이게 바로 정적 사이트 생성의 핵심 원칙입니다.

Modern static sites

현재 최신의 기술을 사용함으로써 우리가 만든 정적인 사이트들은 실제로 정적인건 아닙니다. 동적인 측면도 가지고 있습니다.

이 기술의 선구자 역할을 하는 회사는 Next.js, Nuxt.js, Netlify, Gatsby, Jekyll 그리고 Hugo를 만든 Vercel(과거의 이름은 Zeit)이 있죠.

Next.js나 Gatsby와 같은 프레임 워크들을 사용함으로써, 리액트에서 빌드되는 시간 에 웹사이트에서 필요한 모든 데이터를 가져오는 웹앱을 만들 수 있습니다.

이 점을 강조하고 싶습니다: 여러 소스로부터 어떤 데이터라도 가져올 수 있다.(e커머스 웹사이트나 블로그 포스트에서 필요한 상품들을 가져올 수 있는것처럼요.) 하지만 이런 데이터들은 오직 빌드타임에만 가져올 수 있다. (예시로 CDN에 웹을 배포나 호스팅 할때)

그 결과로써 정적인 사이트에서 유저에게 보여주는 데이터들은 앱이 배포/빌드 되었을때 가져왔던 데이터라는거죠. 유저에게 보여줄 정보가 수정되거나 변경이 되었다면(예를 들어 블로그에 새로운 글을 올렸을때) 반드시 프로젝트를 다시 빌드해야 합니다.

복잡해보일 수 있으나 사실 그렇지는 않아요. 현재 나오는 기술들이 이 과정을 굉장히 쉽게 만들어주거든요.

The Jamstack

기술 발전을 말해주는 유행어가 여기 또 있네요.

jamstack의 jam은 자바스크립트, API 그리고 마크업의 줄임말입니다.

말하자면, 이 유행은 사람들이 서버를 아예 사용하지않고, 호스팅 비용을 줄이며 어플리케이션이 더욱 빠르고 유연해 지도록 정적인 웹 사이트를 사용을 권장합니다. 빌드타임에 데이터를 가져와 페이지를 랜더하는것이 이 Jamstack 사이트의 필수적인 특징이라고 할 수 있지요.

이 Jamstack이 실현 가능하도록 해주는 좋은 기술들이 몇몇 존재합니다.

Headless CMS는 최근 들어 많은 인기를 얻고있습니다. 이런 컨텐츠 매니지먼트 시스템은 데이터를 빌드타임에 저장하고 가져오는것을 도와줍니다. Netlify CMS와 Contentful를 예시로 들 수 있습니다.

예를 들어, 새로운 블로그 글을 headless CMS를 이용해 올린다고 했을 때, headless CMS는 해당 프로젝트를 새롭게 빌드하죠. 끝내주죠! 서버 비용도 안들고 앱에서 데이터들을 거의 동적으로 보여줍니다.

정적인 웹사이트를 호스팅 할 수 있고 Netlify와 Vercel과 같은 Jamstack은 여러분이 만든 정적인 웹사이트와 headless CMS를 아무 문제없이 통합해줍니다.

블로그에 글을 추가하려면 ‘추가하기’ 버튼만 눌러보세요. 그럼 짜잔! 그러면 여러분의 블로그(정적인 사이트)가 다시 생성되고 새로운 컨텐츠에 접근할 수 있습니다. 그리고 CDN을 이용해 엄청 빠르기까지 합니다.

Server Side Rendering vs. Static Site Generation

꽤 많은 양의 정보였죠!

그래서, 언제 SSR을 써야하고 SSG를 써야 할까요? 장점과 단점을 한번 살펴봅시다.

  • Server-side rendering 장점:
  • 보여주는 모든 데이터는 항상 최신
  • 계속해서 업데이트 되는 유저의 특정 데이터나 동적인 데이터를 보여줄 수 있음 반대:
  • 서버에서 계속 랜더링을 해야함 - 서버 비용이 많이 발생
  • 앱이 빠르게 로드되도록 도와주는 CDN을 사용할 수 없음(SSR앱에서 캐싱을 설정하면 되지만 오래된 데이터를 보여줄 수 있는 위험이 있음)

  • Static site generation 장점:
    • 매우 빠른 웹사이트를 만들 수 있음 (CDN으로 배포되면)
    • 서버사이드에서 로직을 기다릴 필요 없음
    • 서버가 다운되도 문제 없음 (서버가 필요없으니까)

반대:

  • 만약 컨텐츠가 굉장히 동적이거나 특정 유저만을 위한것이면 적당하지 않음
  • 데이터가 새롭거나 변화된다면 다시 빌드해야함

Apples to apples comparison?

SSR과 SSG가 서로 라이벌 관계가 아닌것을 알아두셔야 합니다. 상황에 따라 어떤 때에는 SSR이 또 어떤 때에는 SSG를 사용하는게 더 적당합니다.

개인 웹사이트나 블로그가 있는 회사의 웹사이트이고 거의 변화가 없는 데이터를 보여준다? 그러면 정적 사이트 생성 방법을 선택하는게 좋습니다.

유저 개인에 맞는 데이터, 예를들어 게시판을 만들어야 한다? 서버사이드 랜더링이 더 나은 선택이라고 할 수 있겠네요.

A Hybrid Approach

규모가 있는 프로젝트를 만들다 보면 종종 어떤 페이지에서는 정적 랜더링이 다른곳에서는 서버사이드 랜더링이 필요할 때가 있습니다.

괜찮습니다 - Next.js와 이와 비슷한 프레임워크들은 자동적으로 빌드되는 시점에 가져온 데이터로 정적 랜더링을 하고(데이터를 아예 안가져 올 수도 있습니다) 서버사이드 랜더가 필요한 페이지에서는 서버에 요청을 보낼때 마다 페이지를 랜더하거든요.

물론 이 두가지 접근법과 함게, client-side data fetching도 가능합니다.

간단한 AJAX 요청을 이용해 잠재적으로 업데이트가 되지 않는 데이터들을 다시 가져오게 할 수도 있습니다.

여러분의 재량에 맞게 사용하시면 됩니다.

In Closing

이 글을 끝까지 읽어주셔서 감사드립니다.

좋은 정보를 얻어가셨으면 좋겠네요!

Stay creative!

원문: Server-Side Rendering vs. Static Site Generation by Adam Kiss