왜 다시 SSR인가 01

들어가기전

프론트엔드 개발자가 아니더라도 웹 개발에 몸을 담고 있다면 한번쯤은 SPA 애플리케이션에 대해서 한번쯤 들어봤을 것이다. 요즘은 일부 회사들의 공고에도 보란듯이 SPA 애플리케이션 경험자라는 키워드가 나와있을 정도로 프론트엔드 개발자에게는 알아야하는 기본적인 소양이 되었다. 이참에 대체 SPA 애플리케이션이 무엇인지, 왜 SPA 애플리케이션이 나오게 되었는지 하나씩 알아볼 것이다. 그 전에 먼저 우리가 살펴보고자 하는 클라이언트의 구조에 대해서 한번 살펴보도록 하자.

2 티어 아키텍쳐 구조(2 Tier Architecture Structure)

과거 많은 애플리케이션은 2 Tier 형태의 아키텍쳐를 가지고 있다. 2 티어 아키텍쳐란 클라이언트와 DB가 물리적으로 분리되어있는 구조 안에서, 클라이언트에는 UI와 비지니스 로직(Business logic)이 함께 있는 구조이다.

/images/theory/mpa01.png

👍 2 티어 아키텍쳐의 구조를 가져가게 될시 다음과 같은 장점이 가진다.

  1. 쉽게 빠르게 개발할 수 있으며 시스템 구축이 어렵지 않다.
  2. 애플리케이션의 구조가 단순하다.
  3. 개발 비용이 비교적 저렴하다.

보통 초기의 스타트업와 같이 적은 인원으로 시스템을 빠르게 구축할 때 이와 같은 구조를 많이 가져간다.

👎 하지만 이러한 구조에는 장점에 비해 부각되는 단점들이 있다.

  1. 클라이언트에서 DB에 직접 붙기 때문에 안정성에도 문제가 있다.
  2. UI와 비지니스 로직을 클라이언트에서 모두 관리하기 때문에, 클라이언트에 부하가 걸리기 쉽다.
  3. 재사용이 어렵다.
  4. 비지니스가 점점 더 복잡해지거나 비대해지면 관리하기가 어려워진다.

이러한 단점은 스타트업의 성장통이라 하여 급격하게 성장하는 회사들이 결국에는 애플리케이션을 다시 만들게 되는 이유가 되기도 한다. 이러한 단점을 개선하고자 3 Tier 혹은 그 이상의 N Tier 아키텍쳐로 설계를 한다.

3 티어 아키텍쳐 구조(3 Tier Architecture Structure)

2 티어 아키텍쳐의 구조와 큰 차이점은 클라이언트 안에 존재하는 UI와 비지니스 로직(Business logic)을 분리된다는 점이다.

/images/theory/mpa02.png

각각의 용어는 다른 단어로도 표현되는데 클라이언트를 프레젠테이션 티어, 비지니스 계층은 애플리케이션 티어라고 불르기도 한다. 이러한 구조를 가지게 된 경우 클라이언트 로직은 Frontend 개발자가, 비지니스 로직은 Backend 개발자가 담당하게 된다. 이렇게 분리하면 장점은 무엇보다 재사용이 쉽다라는 점이 있다. 요즘 많은 엔터프라이즈급 회사에서 지향하고 있는 MSA 구조 역시 이와 같이 프레젠테이션 티어와 비지니스 티어가 분리되어야 비로서 가져갈 수 있는 구조 중 하나이다.

👍 3 티어 아키텍쳐는 이러한 장점을 가진다.

  1. 클라이언트가 직접 DB 붙는 것이 아닌 Business 계층을 통해 붙기 때문에 보안에 용이하다.
  2. 재사용이 쉬우며, 확장에 용이하다.
  3. 비지니스 로직과 UI를 분리할 수 있다.

이러한 구조의 제일 큰 장점으로는 UI와 비지니스 로직이 분리되어 있어 애플리케이션을 배포할 때에도 UI나 비지니스 로직을 각각 배포할 수 있다. (당연히 비지니스 로직이나 DB 관련 코드가 포함되어 있으면 안된다.)

🎉 굉장히 멀리 돌아왔지만 드디어 우리가 살펴보고자 하는 클라이언트 혹은 프레젠테이션 티어라고 부르는 UI가 등장하였다.

MPA 애플리케이션

MPA 애플리케이션은 Multiple Page Application의 약자로서, 전통적인 웹 애플리케이션 방식이다. MPA 애플리케이션의 가장 큰 단점으로는 프론트엔드와 백엔드가 강하게 결합되어 있다는 점이 있다. 이러한 점은 우리가 앞에서 살펴본 2 Tier 아키텍쳐의 단점과 같다는 것을 쉽게 유추할 수 있다. 이러한 구조는 우리가 편하게 웹서버라고 불리우는 형태의 애플리케이션이다. 아마 모두들 한번쯤은 jsp 혹은 php 등과 같은 템플릿 언어의 코드로 작성된 UI 로직을 수정해본 경험이 있을 것이다. 이렇게 작성된 애플리케이션에서 다른 페이지를 이동할 때 이동하려는 웹페이지에 대한 서버로 요청을 날리는 후 페이지를 새롭게 렌더링한다는 것을 알 수 있다. 조금더 자세하게 설명한다면 사용자가 “A”라는 페이지를 요청한다면 다음과 같은 과정을 거칠 것이다.

  1. “A”에 대한 페이지 정보를 서버에 요청한다.
  2. “A”에 대한 요청을 받은 서버는 해당하는 UI와 필요한 데이터(예를 들어 게시판이라고 한다면 게시글 데이터를 의미한다)를 이용하여 HTML 데이터로 파싱한다.
  3. 브라우저는 전달받은 HTML 데이터를 지정된 인코딩으로 변환하여 사용자에게 보여준다.

브라우저는 이러한 과정을 거치면서 페이지를 갱신하게 되며 사용자는 페이지가 이동될때마다 새로고침되는 것을 볼 수 있다. 이러한 새로고침은 로딩 시간을 늘어질 뿐만 아니라 사용자의 경험 역시 좋지 않을 수 밖에 없다. 이러한 단점을 AJAX 라는 기술이 어느정도 해결해줄 수 있었다. 과거에는 폼을 작성한 후 웹 서버에 제출(Submit)하게 되면 이러한 요청을 처리하며 브라우저가 새로고침되는 것을 볼 수 있었지만 요즘에는 거진 대부분 페이지 이동없이 화면을 전환하고 있다. 이러한 요청을 통해 웹 서버의 처리량 역시 과거보다는 많이 줄어들었다. 하지만 이러한 근본적으로 페이지 이동시 새로고침된다는 문제를 해결하기엔 역부족이었다.

SPA 애플리케이션

MPA 애플리케이션의 사용자 경험에 대한 단점을 개선해줄 수 있는 것이 바로 SPA 애플리케이션이다. SPA 애플리케이션은 Single Page Application의 약자로서 다른 말로는 CSR(Client Side Rendering)이라고 표현하기도 한다. 이러한 SPA 애플리케이션은 하나의 HTML 파일만 있으면 나머지는 Javascript를 이용해서 동적으로 화면을 구성할 수 있다. 서버는 어떠한 요청을 받던 무조건 동일한 HTML 파일은 내려준다. 그 후 사용자는 하나의 HTML 파일에서 Javascript를 이용해 동적으로 구성되는 UI 화면 속에서 마치 페이지가 이동되는 것처럼 보여지는 느낌을 받는다. 이렇게 URL을 조작해 마지 이동되는 것처럼 보여지게 하는 것은 해쉬 방식 혹은 HTML5의 히스토리 API를 통해 가능하다.

SPA의 가장 큰 장점으로는 변경된 부분만 효율적으로 변경한다는 점이다.

/images/theory/spa01.png

이러한 애플리케이션 내에서 사용자에게 제공하는 모든 페이지는 Javascript 안에 포함되어져 있으며, Javascript를 이용하여 동적으로 화면이 갱신되어지는 것처럼 보여지게 하는 것이다. 이러한 점은 좋은 사용자 경험을 제공해줄 수 있다는 장점을 가진다. 하지만 그렇다고 장점만 있는 것은 아니다. 앞에서 설명했든 애플리케이션의 모든 페이지들이 Javascript 안에 포함되어져 있기 때문에 애플리케이션에서 사용하는 Javascript 파일은 점점 더 비대해지며 이러한 이유로 인해 애플리케이션의 초기 랜더링 속도가 느리다. 뿐만 아니라, Javascript를 이용하여 화면을 동적으로 그리기 때문에 SEO에 굉장히 취약하다는 단점을 가지고 있다. 물론 애플리케이션의 초기 랜더링 속도를 개선하기 위해 써드파티 라이브러리들을 Vendor 단위로 나눈 후 CommonChunking으로 별도로 청킹 처리를 해주거나 Dynamic Loading을 이용하여 Javascript 파일의 리소스를 최대한 줄이는 등의 전략을 세우고 있다. 하지만 이렇게 아무리 노력한다고 해도 SSR보다는 초기 랜더링 속도가 늦을 뿐만 아니라 근본적인 문제인 SEO를 해결할 수 없다는 단점을 가지고 있다. 이 다음에는 SPA의 이러한 단점을 해결하기 위한 방법에 대해서 살펴보도록 하겠다.

현재 이커머스회사에서 frontend 개발자로 업무를 진행하고 있는 Martin 입니다. 글을 읽으시고 궁금한 점은 댓글 혹은 메일(hoons0131@gmail.com)로 연락해주시면 빠른 회신 드리도록 하겠습니다. 이 외에도 네트워킹에 대해서는 언제나 환영입니다.:Martin(https://github.com/martinYounghoonKim
Naver Tech Concert 리뷰
Typescript의 기본 유틸 타입