SPA와 SSG, 그리고 SSR
요즘 프론트엔드(front-end) 개발을 하다 보면 SPA, SSG, SSR이라는 상당히 비슷해서 헷갈리는 약어를 심심치 않게 들을 수 있는데요. 이번 포스팅에서는 모던 웹 개발의 트랜드를 주도하고 있는 이 3가지 랜더링(rendering) 기법에 대해서 이야기해보려고 합니다.
SPA: Single Page Application
SPA(Single Page Application)는 직역하면 단일 웹페이지로 돌아가는 애플리케이션을 의미하는데요. 이를 곧이곧대로 받아드리면 정말로 페이지 하나로 이루어진 정말 간단한 웹사이트로 오해할 소지가 있는 것 같습니다.
사실 SPA는 오히려 이와 정반대로 전형적인 웹사이트 모델로는 구현이 어려운 섬세하고 역동적인 웹 애플리케이션인 경우가 많은데요. 쉽게 말해, “와! 이런 서비스를 어떻게 웹으로 구현했지?”라는 인상을 받았다면 SPA일 확률이 매우 높습니다.
SPA는 브라우저에서 자바스크립트를 이용하여 단일 웹페이지 상의 HTML 요소를 동적으로 생성하고 조작합니다. 따라서 서버 측에서는 텅빈 HTML 문서 하나와 자바스크립트 코드만 내려주고 그 이후에 모든 일들은 클라이언트 측에서 브라우저가 비동기로 처리하게 됩니다. 예를 들어, 유저가 어떤 버튼을 클릭하였을 때, 원격 API를 호출해서 데이터를 가져온 후, HTML 문서로 랜더링하는 일련의 과정이 모두 자바스크립트를 통해 브라우저에서 일어나게 됩니다.
그래서 SPA는 브라우저에서 페이지 소스 보기를 하면 다음과 같이 <body>
요소 아래에 <div>
요소 하나가 허전하게 있는 경우가 많습니다. 😅
<body>
<div id="root"></div>
</body>
모든 랜더링이 클라이언트 측에서 일어난다고해서 이러한 랜더링 방식을 CSR(Client-Side Rendering)이라고도 합니다. 뒤에서 소개해드릴 SSR(Server-Side Rendering)과 반대되는 개념이라고 볼 수 있겠습니다.
SPA는 React, Svelte, Vue.js와 같이 요즘 잘 나가는 대부분의 자바스크립트 라이브러리(library)로 개발이 가능합니다. 이러한 라이브러리로 개발된 SPA는 마치 운영체제에 설치해서 사용하는 네이티브(native) 애플리케이션과 같은 사용자 경험을 줄 수 있는데요. 클라이언트에서 최초에 한 번 자바스크립트 코드를 내려받으면 그 이후로는 서버와 네트워크 통신을 할 필요가 없으므로 일반적인 웹사이트처럼 페이지 별로 끊어지는 느낌이 없다는 장점이 있습니다. 우리가 웹에서 자주 사용하는 구글맵과 같은 지도 애플리케이션을 생각하면 이해가 쉬울 것 같습니다.
SPA가 UX(사용자 경험) 측면에서는 확실히 강점이 있지만, 지나치게 자바스크립트에 의존한다는 것이 치명적인 약점으로 작용하기도 합니다. 우선, SPA는 자바스크립트가 돌아가지 않는 브라우징 환경에서 완전히 먹통이 될 수 있습니다. 또한 SPA는 클라이언트에서 내려받아야하는 자바스크립트의 코드의 양이 적지 않기 때문에 네트워크 품질에 따라서 웹사이트가 최초로 로딩되는데 시간이 오래 걸릴 수 있습니다.
마지막으로 SPA는 검색 엔진 최적화(SEO) 측면에서도 상당히 불리한 것으로 알려져 있습니다.
왜냐하면 검색엔진 크롤러(crawler)가 웹페이지에서 읽어갈 수 있는 내용이 달랑 <div>
요소 밖에 없기 때문입니다.
구글에서는 SPA 웹페이지도 일반 웹페이지처럼 크롤링이 가능하다고 얘기하지만 모든 검색 엔진이 구글 수준의 크롤링 기술을 갖추었을지는 의문입니다.
따라서 HTML과 CSS, 그리고 약간의 JavaScript로 만들 수 있는 단순한 웹페이지를 SPA로 개발하는 것은 득보다 실이 큰 소위 오버 엔지니어링(over engineering)이 될 수 있습니다. 사용자와 상호작용이 많치 않은 단순한 웹페이지를 만들 때는 다음 섹션에 소개해드릴 SSG를 사용하는 편이 훨씬 더 나은 경우가 많습니다.
SSG: Static Site Generator
정적 사이트 생성기로 번역할 수 있는 SSG(Static Site Generator)는 누가 접속하든 항상 동일한 내용을 보여주는 웹사이트를 만드는데 최적화된 방법입니다. 그래서 제품 카탈로그나 개인 블로그처럼 컨텐츠의 변경이 자주 일어나지 않는 비교적 소규모 웹사이트를 제작할 때 매우 유용한데요. 대표적인 정적 사이트 생성 도구로는 Gatsby, Hugo, Jekyll, Hexo 등을 뽑을 수 있습니다.
SSG로 생성되는 웹사이트는 모든 웹페이지를 미리 싸그리 만들어놓고 요청이 들어오면 만들어 놓은 웹페이지를 그대로 응답만 해줍니다. 따라서 서버와 클라이언트 측 모두 랜더링을 위해서 할 일이 별로 없기 때문에 SSG로 생성된 웹사이트는 속도가 엄청 빠르다는 이점이 있습니다. 게다가 CDN(Content Delivery Network)을 활용하면 미리 만들어 놓은 웹페이지를 실사용자와 지리적으로 최대한 가까운 곳에 캐싱(catching)해놓을 수도 있지요.
SSG는 요즘 웹에이전트 쪽에서 선호되는 Headless CMS(Content Management System)와 궁합이 잘 맞는데요. 마케팅 또는 컨텐츠 관리자가 Headless CMS에 저장해놓은 모든 컨텐츠를 빌드(build) 시점에 REST API나 GraphQL을 통해 몽땅 읽어와서 웹페이지로 만들어낼 수 있습니다.
SSG로 생성된 웹사이트는 하나의 웹페이지에서 돌아가는 SPA와 달리, 미리 만들어놓은 수 많은 웹페이지로 이루어졌기 때문에 검색 엔진이 크롤링하기 매우 적합한 구조를 가지게 됩니다. 따라서 검색 엔진 최적화(SEO)가 중요한 마케팅 웹사이트를 제작할 때는 SSG가 매우 보편적으로 사용되고 있습니다.
SSG의 가장 큰 단점은 아무래도 빌드 시점에 웹사이트 전체를 매번 다시 만들어 내다 보니 컨텐츠가 자주 업데이트되는 웹사이트에서는 비효율이 발생할 수 있다는 것인데요. 보통 웹사이트의 규모가 커지면 자연스럽게 빌드(build) 시간이 길어지는데, 이러면 변경된 컨텐츠가 웹사이트에 반영되는데 시간이 점점 오래 걸리기 마련입니다.
요즘에는 이러한 약점을 극복하기 위해서 정적 사이트 생성기가 전체 웹사이트를 재생성 하는 대신에 변경이 필요한 웹페이지만 골라서 업데이트 해주는 똑똑한 기능을 제공하기도 합니다.
SSR: Server-Side Rendering
SSR(Server-Side Rendering)은 말 그대로 서버 측에서 웹페이지를 랜더링하는 기술을 뜻합니다. SSG와 가장 큰 차이점은 빌드 타임에 웹사이트 전체를 미리 만들어 놓는 것이 아니라, 클라이언트로 부터 요청이 들어올 때마다 실시간으로 해당 웹페이지를 만들어낸다는 것입니다.
SSR은 사용하면 애플리케이션에서는 변경된 데이터가 즉시 웹페이지에 반영이 되고 유저마다 다른 경험을 제공하기도 용이해집니다. 따라서 데이터가 수시로 업데이트되고, 개인화된 경험을 제공해야하는 전자 상거래(E-commerce) 플랫폼이나 소셜 네트워크 서비스(SNS)에 매우 적합한 랜더링 전략이라고 할 수 있겠습니다.
웹 서버만 있으면 쉽게 호스팅이 가능한 SPA나 SSG와 달리, SSR을 사용하려면 서버 측에서 웹페이지를 랜더링하기 위해서 애플리케이션 서버가 추가로 필요합니다. 그리고 SSR를 사용하는 서비스에서는 원격 API나 Headless CMS를 사용하는 대신에 자체 데이터베이스(DB) 서버나 클라우드(Cloud) 플랫폼에 데이터를 저장해놓는 경우가 많습니다. 따라서 이러한 인프라를 구축하고 운영할 수 있는 여건이 되는 중대형 서비스에서 SSR이 많이 사용되고 있습니다.
SSR을 사용하는 웹사이트는 SPA나 SSG 대비 느리고 무거운 경향을 보이는데요. 아무래도 요청이 들어온 순간 서버에서 웹페이지를 만들어내고 이를 네트워크를 통해 클라이언트에 전송하려면 시간이 더 소모될 수 밖에 없기 때문입니다.
위에서 소개해드린 SPA 개발에 사용되는 유명한 자바스크립트 라이브러리는 대부분 SSR이 가능하도록 메타 프레임워크(meta framework)도 함께 제공하고 있습니다. 예를 들어, React 기반으로 된 Next.js와 Remix, Svelte 기반인 SvelteKit, Vue.js 기반인 Nuxt.js를 들 수 있겠습니다.
이러 종류의 프레임워크를 메타 프레임워크라고도 많이 부르는데요. 관련 내용이 궁금하시다면 관련 포스팅을 참고 바라겠습니다.
당신은 선택은?
그럼 여러분의 프로젝트는 SPA, SSG, SSR 중에 어떤 방식으로 개발을 해야 할까요? 각 랜더링 방식의 장단점이 명확하기 때문에 개발하려는 애플리케이션의 성격을 고려하는 것이 가장 중요할 것입니다.
섬세한 상호 작용을 필요로 하고 역동적인 사용자 경험이 중요한 애플리케이션이라면 당연히 SPA로 개발하는 것이 좋겠죠. 하지만 갱신이 잦지 않은 정적인 웹사이트라면 SSG를 사용하는 편이 성능과 SEO 측면에서 유리할테고요. 데이터가 변경이 잦고 개인화된 사용자 경험이 필요한 서비스라면 SSR이 중장기적으로 현명한 선택이 될 것입니다.
최근에는 하이브리드(hybrid) 랜더링을 지원하는 프레임워크도 속속들이 등장하고 있는데요. 대표적 예로 Next.js는 기본적으로 SSR로 동작하지만 웹사이트의 일부를 SSG로 미리 생성해주는 기능을 지원하기 시작했습니다. 이 기능을 잘 활용하면 개인화가 필요하지 않고 갱신이 잦지 않은 웹페이지를 부분적으로나마 좀 더 빠르게 서비스할 수 있을 것입니다.
마치면서
PHP, ASP, JSP와 같은 기술로 웹 개발을 하던 시절에는 서버 단에서 웹페이지를 랜더링하는 것, 즉 SSR이 매우 당연한 일이 었습니다. 그러다가 AngularJS, React, Vue.js와 같은 모던 자바스크립트 라이브러리가 등장하면서 클라이언트 단에서 웹페이지를 랜더링하는 SPA로 개발하는 것이 한동안 대세였죠. 최근에 다시 SSR이 주목받는 것을 보면서 웹 개발에서도 유행이 참 돌고 돈다는 생각이 들지 않으신가요? 😄
그래도 크게 달라진 부분은 한 가지 방식의 랜더링을 고수했어야하는 예전과 다르게 요즘에는 개발 도구가 좋아져서 유연한 접근이 가능하다는 건데요. 그래서 전략적으로 비지니스 초창기에는 개발 생산성이 좋은 SSG로 가다가 나중에 사용자가 늘어남에 따라 지원해야 할 기능이 많아지면 SPA나 SSR로 전환하는 사례가 늘고 있습니다. 물론 메타 프레임워크를 통해서 이 두 가지 방식을 적절히 섞어 쓰는 것도 충분히 가능하고요!
이렇게 옵션이 다행해진 게 개인적으로는 반갑지만 프론트엔드 개발 조직에게는 양날의 검이 될 수도 있을 것 같아요. 그만큼 기술 리더가 옮바른 의사 결정을 내리기 위해서 고려해야 할 사항이 늘어났다는 뜻도 되기 때문입니다.
본 포스팅이 SPA, SSG, SSR에 대한 웹 개발자분들의 이해도를 높이는 데 작은 도움이 되기를 바라며, 그럼 이만 줄이겠습니다.