전통적인 사이트들은 하나의 index.html을 통해 다른 페이지(html)로 이동하는 방식이다. (이러한 방식을 MPA라 한다.)
하지만, 최근의 웹 사이트들은 ReactJS,VueJS,AngularJS와 같은 프레임워크/라이브러리를 사용한 SPA 방식이 주를 이룬다.
위 그림의 SPA 라이프사이클을 보면 하나의 html에서 어떠한 동작을 통해 화면을 전환한다.
MPA에서는 SSR, SPA에서는 CSR 렌더링 방식을 사용한다. (자세한건 아래에)
이번 글을 통해 SPA와 MPA의 차이를 알아보자.
a 태그를 통해 페이지를 넘어가는 작업을 해봤을 것이다.
MPA로 웹을 구성할 경우, 위의 사진처럼 각 폴더마다 index.html이 존재한다.
이러한 방식의 경우, 페이지를 이동할 때 마다 프론트 서버에서 request를 보내고 원하는 페이지의 response를 받아 온다. 즉, MPA 방식은 브라우저에서 페이지를 이동할 때 마다 아래의 동작을 계속해서 반복하는 것이다.
- 서버로부터 HTML, CSS, Javascript, Img files... 등을 응답받는다.
- HTML 파서와 CSS 파서를 통해 위 파일들을 DOM Tree, CSSOM 트리로 변환 후, 렌더 트리로 결합한다.
- 렌더트리를 기반으로 웹페이지를 표시한다.
tip) 2-1. Javascript 파싱
HTML 파서는 script 태그를 만나면 자바스크립트 코드를 실행하기 위해 DOM 생성 프로세스를 중지하고 자바스크립트 엔진으로 제어 권한을 넘긴다.(자바스크립트는 렌더링 엔진이 아닌 자바스크립트 엔진이 처리한다.) 제어 권한을 넘겨 받은 자바스크립트 엔진은 script 태그 내의 자바스크립트 코드 또는 script 태그의 src 어트리뷰트에 정의된 자바스크립트 파일을 로드하고 파싱하여 실행한다. 자바스크립트의 실행이 완료되면 다시 HTML 파서로 제어 권한을 넘겨서 브라우저가 중지했던 시점부터 DOM 생성을 재개한다.
이처럼 브라우저는 동기(Synchronous)적으로 HTML, CSS, Javascript을 처리한다. 이것은 script 태그의 위치에 따라 블로킹이 발생하여 DOM의 생성이 지연될 수 있다는 것을 의미한다. 따라서 script 태그의 위치는 중요한 의미를 갖는다.
body 요소의 가장 아래에 자바스크립트를 위치시키는 것은 좋은 아이디어이다. 그 이유는 아래와 같다.
HTML 요소들이 스크립트 로딩 지연으로 인해 렌더링에 지장 받는 일이 발생하지 않아 페이지 로딩 시간이 단축된다. DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작한다면 에러가 발생한다.
본론으로 넘어와서, 페이지 이동이 많은 웹 서비스에서 위의 1~3의 과정을 반복하는 것은 굉장히 비효율적일것이다. 이러한 과정을 효율적으로 개선하기 위해 나온 것이 SPA이다.
그렇다고 MPA가 이러한 단점만 있는 것이 아니다. 서비스의 이용 목적에 따라 SPA, MPA를 선택하여 개발하는 것이 중요하다.
MPA 장점
SEO 및 페이지 순위 지정
검색엔진 (SEO. Search Engine Optimization) 이 페이지를 크롤링 하기에 매우 적합하고 매우 직관적이라는 것이다.
HTML이 서버 측에서 완전히 형성되고 웹 크롤러가 HTML 페이지를 더 쉽게 인덱싱할 수 있기 때문이다.
초기 페이지 로드 시간이 빠르다.
서버에서 수신한 HTML을 브라우저에서 빠르게 구문 분석하여 즉시 표시할 수 있고 웹 페이지를 표시하기 위해 별도의 JS 번들을 다운로드하여 실행할 필요가 없기 때문에 초기 페이지의 로드 시간이 더 빠르다.
직관적인 작업환경
처음 웹을 접하는 개발자(또는 퍼블리셔)라면 쉽게 어느 페이지에 뭐가 있는지 파악하기 좋다.
MPA 단점
페이지 이동 시 발생하는 화면 깜빡임
로직이나 JS동작이 별로 없으면서 단순한 텍스트만 존재하는 페이지라면 큰 차이를 느끼지 못 할 수도 있다. 하지만 많은 사이트들이 이미지와 방대한 data들을 불러오기 위해 API를 사용하고, 수많은 스타일링이 들어가는 css나 html을 가지고 있기 때문에 이러한 데이터들을 불러오는 과정에서 깜빡임이 발생한다.
나쁜 사용자 경험
최근이야 기계들의 성능들이 많이 향상되어 조금 차이를 못 느낄 수 있을 수도 있으나, 현대인들의 사용자 경험(학습)도 늘었기 때문에 0.1초라도 늦으면 답답해 하는 나쁜 사용자 경험 을 무시하고 MPA을 고집할 수만은 없을 것이다.
낮은 응답성
HTML을 수신하기 위해 서버로 계속 왕복하기 때문에 인터넷 연결이 낮거나 연결되지 않은 경우 응답성이 낮다.
웹 트래픽 문제
Dynamic SSR 의 경우 서버가 모든 요청에 대해 동적으로 HTML을 생성해야 하므로 웹 트래픽이 증가하면 서버 로드가 증가한다.
SPA는 최초 한번 페이지 전체를 로딩한 이후 부터는 데이터만 변경하여 사용할 수 있는 웹 어플리케이션이다. 말그대로 Single. 딱 하나의 index.html이 존재한다.
아래의 react 프로젝트(이미지)를 보면 index.html 하나로만 구성되어 있는 것을 볼 수 있다.
하나의 index.html가 열리고 나서 페이지 이동 액션이 실행되면 MPA와 달리 프론트 서버에서 request를 보내는 것이 아니라 웹 클라이언트 자체적으로 JS에 의해 화면이 전환된다.
SPA의 경우, 처음에 하나의 빈 페이지만 Server에서 제공받고 클라이언트(Client)에서 JS를 통해 렌더링 하는 방식이다. 필요한 모든 정적 리소스를 한번에 다운로드 받고 특정 부분만 Ajax로 동적 데이터를 요청하여 받은 JSON/XML를 View(화면)에 뿌려주는 형식이다.
위의 설명과 같이, 처음에 이동가능한 모든 페이지에 대한 파일을 클라이언트에서 받아오기 때문에, 초기 페이지 로딩이 오래 걸린다.
하지만, 이후 페이지를 이동하거나 렌더링 할 경우. MPA에 비해서 빨라서 모바일 환경에서 매우 유용하다.
페이지내에서 동적으로 변해야하는 부분이 있는 경우 해당 정보만 백엔드 서버에 요청하여 응답을 받고 웹을 갱신한다.
위 그림은 왼쪽부터 SPA, MPA를 이미지화 한 것이다.
SPA 장점
빠른 로딩 시간(최초만 느리다.)
페이지가 처음에 로드 되면 서버는 더이상 HTML, CSS를 보내지 않는다. 따라서 빠른 호환성으로 인해 동일한 템플릿을 무수히 많이 사용해야 하는 페이지에 유용하다. Goolere Search 에 의하면 페이지를 로드하는데 200 milliseconds 이상이 되면 비즈니스 및 판매에 큰 영향을 미친다고 하니, 로딩시간은 충분히 큰 이점이 있다.
좋은 캐싱 능력
SPA는 하나의 요청을 보내고 서버의 모든 데이터를 저장한다. 데이터에 대한 지속적인 액세스가 있으므로 사용자는 오프라인에서도 사용할 수 있을 뿐만 아니라, 로컬데이터는 서버와 동기화가 된다.
향상된 상용자 경험
콘텐츠의 동적 로딩은 사용자에게 원활한 경험을 제공한다. (쉽게 말하면 로딩이 빨라, 긍정적인 경험을 얻는다)
특히나 모바일 환경에서는 빠른 속도로 랜더링 되기 때문에 쾌적한 환경을 제공 할 수 있다.
신속한 프론트엔드 개발
분리된 SPA 아키텍쳐이기 때문에, 프론트/백 엔드 개발 서비스를 분리해서 작업 할 수 있다. 그래서 자유로운 빌드, 테스트 및 배포를 할 수 있다.
SPA 단점
복잡한 SPA의 문제
복잡한 SPA를 빌드 할 시 크기 때문에 사용하기가 불편할 수도 있다. 페이지의 로딩시간은 복잡성으로 인해 늘어 날 수있고, 사용자 참여를 감소 시키는 요인된다.
Analytics
Analytics도구는 페이지에 단일 코드를 추가하는 것만으로 페이지 보기를 추적 할 수 있다. 하지만 SPA는 실제 페이지가 아니기 떄문에 추적을 위한 논리를 추가해야 하며 페이지를 새로 고칠 필요 없이 분석 도구가 새 페이지를 선택하도록 해야한다. 새로운 코드를 추가 하는 것이 다소 번거로울 수 있다.
tip) 검색 엔진 최적화(영어: search engine optimization, SEO)
웹 페이지 검색엔진이 자료를 수집하고 순위를 매기는 방식에 맞게 웹 페이지를 구성해서 검색 결과의 상위에 나올 수 있도록 하는 작업을 말한다.
동적인 HTML 문서를 만드는 방식으로 PHP, JSP, ASP, Node.js 등 Server-Side Script 언어 기반의 템플릿 엔진을 사용한다.
SSR는 웹 브라우저가 요청하면 브라우저는 구성요소가 이미 생성되어 있는 HTML을 받아온다. (아래의 코드 형태로)
<!DOCTYPE html>
<html>
<head>
<title> 서버 측에서 렌더링된 웹 페이지 </title>
</head>
<body>
<h1> 이것은 제목입니다 </h1>
<p> 이것은 단락입니다 </p>
<div>
<p> 이것은 양식입니다 </p>
<form>
<label for="fname"> 이름:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">성:</label><br>
< 입력 유형="텍스트" id="lname" 이름="lname">
</form>
<div>
</body>
</html>
브라우저는 HTML을 파싱하여 DOM을 생성하고 웹페이지에 보여주기만 하면 된다.
SSR는 요청 시 서버 측 렌더링은 탐색 요청을 수신하고 외부 데이터(서버 측에서)를 가져오고 HTML을 동적으로 생성하기 위해 실행 중인 웹 서버가 필요하다.
브라우저에 JS가 없어도 HTML, css가 있으면 화면에 노출이 된다.
그래서 MPA는 SSR 방식이라고 설명한다.
(SSR 장점이 MPA의 장점이랑 전체적으로 동일하다.)
CSR에서의 HTML 구성 요소는 브라우저에서 JS 코드를 실행하여 클라이언트 측에서 생성한다. 브라우저가 웹 페이지를 요청할 때, 초기 서버요청은 최소한의 HTML 파일을 반환한다
<html>
<head>
<title> CSR 앱 </title>
</head>
<body>
<div id="app"> </div>
<script src="../src/index.js"> </script>
</body>
</html>
이 경우 브라우저가 HTML DOM을 생성하기 위해 HTML을 분석할 필요가 없다. 대신 브라우저는 HTML에 링크된 JS을 완전히 다운로드한 다음 브라우저에서 JS를 실행한다. 그러면 클라이언트 측에서 웹 페이지 HTML DOM이 생성된다.
또한 앱 내의 링크를 클릭하면 서버에서 HTML을 요청하는 대신 요청된 DOM을 생성하기 위해 HTML DOM 클라이언트을 조작한다.(일반적으로 "라우터" 모듈에 의해 처리된다. React-Router, Vue-Router)
브라우저에 JS가 없을 경우 빈페이지가 표시될 수 있다.(JS가 없으면 랜더링이 되지 않음)
참고)