May 05, 2021
기본적으로 웹은 Client와 Server로 나뉘어진다.
웹의 성능이 계속 좋아지고 내려줘야 하는 정보의 양도 늘어나고 JavaScript 등장 이후로 사용자와의 인터랙션도 늘어나게 되면서 요청을 보내고 응답을 받는 과정이 계속해서 많아지게 된다. (static한 정보만을 보여주는 웹의 초기 역할을 넘어서게 됨.)
→ 서버 입장에서도 수많은 요청을 처리해야하게 된다.
→ Client 입장에서도 계속해서 페이지 깜빡임이 발생하게 된다. 서버에서 html을 새로 받아서 그리기 때문.
구글에서도 AJAX를 이용해서 Gmail, Google Maps과 같은 웹 어플리케이션을 만들기 시작.
→ SPA (Single Page Application)
기존에는 Server에서 받은 html을 바탕으로 Client가 화면을 그렸지만, CSR 방식은 서버에서 받는 게 아니라 Client에서 알아서 화면을 그리는 방식이다.
React나 Vue 같은 라이브러리/프레임워크는 SPA를 만드는 것을 지원하고 CSR 방식으로 동작한다
CSR 방식으로 만들어진 사이트 url에 접근을 하면 서버로부터 body
태그 안에 <div id="root"></div>
와 application에서 필요한 js 파일 링크만 들어 있는 형태의 html 파일을 응답 받는다.
링크된 js 파일을 서버로부터 다운로드 받는다.
이 js 파일에는 우리 어플리케이션에 필요한 로직들 뿐만 아니라 어플리케이션을 구동하는 프레임워크와 라이브러리(ex. react, vue, angular)의 소스코드들도 다 포함이 되어 있기 때문에 사이즈가 굉장히 커서 다운로드 받는데 시간이 소요될 수 있다.
개발자도구 Networks 탭에 가보면 서버에서 받은 html은 내용이 비어 있는데 개발자도구 Elements 탭에 가보면 <div id="root"></div>
태그 안에 다른 태그들이 들어가 있다. 이 태그들은 번들링된 js 파일을 통해 만들어진다.
리액트는 build를 할 때 프로젝트 내의 모든 리액트 코드를 하나의 자바스크립트 파일로 만들어 준다. (babel로 transpiling, webpack으로 bundling)
대형 프로젝트일 경우 코드가 많아지면 번들링된 하나의 자바스크립트 파일의 크기가 커진다. 이 파일의 크기가 커질 수록 처음에 파일을 로드하는 시간이 오래 걸린다. 즉, 사용자가 첫 화면을 보기까지가 오래 걸린다.
SEO (검색 엔진 최적화) 대응이 힘들다.
CSR의 문제점들 때문에 1990년 중반에 사용했던 Static Sites에서 영감을 받은 SSR이 도입되게 된다.
SSR은 Client에서 모든 것을 처리하는 방식과는 다르게,
웹 사이트에 접속하면 서버에서 필요한 데이터를 모두 가져와서 html 파일을 만들고 이렇게 만들어진 html 파일이 동적으로 제어할 수 있는 소스코드와 함께 Client에 보내준다.
Static Sites에서 발생했던 깜빡임 이슈
사용자가 링크를 클릭하게 되면 전체 페이지를 다시 서버로부터 받아오는 것과 동일하기 때문에 좋지 않은 사용자 경험을 준다.
서버에 과부하가 걸리기 쉽다.
특히 사용자가 많은 사이트일수록 사용자가 클릭을 할 때마다 서버에 요청해서 서버에서 html을 만들어야 하기 때문
즉, 사용자가 웹 사이트를 볼 수 있음(TTV)과 동시에 클릭을 하거나 인터랙션(TTI)이 가능하게 된다.
즉, SSR은 사용자가 화면을 볼 수 있는 시간과 실제로 인터랙션을 할 수 있는 시간 사이 공백 기간이 꽤 긴 편이다. (웹 사이트의 성능을 분석할 때 TTV와 TTI도 중요한 요소로 사용된다.)
사용자가 처음 들어왔을 때의 페이지는 서버에서 받아 렌더링하고(SSR) 그 뒤에 발생하는 라우팅은 CSR로 하면 어떨까?
여기에서 첫 페이지를 서버에서 받는다는 것은 CSR처럼 비어 있는 html을 받는다는 게 아니라 내용이 모두 채워져 있는 html을 받는다는 것이다.
그러면 Client에서는 서버로부터 받은 html을 DOM에 그대로 그리기만 한다. (이후 인터랙션이 가능한 js파일은 따로 load)
html에 내용이 모두 채워진 상태로 받기 때문에 SEO 대응이 가능해진다.
Code Splitting을 안했을 때의 CSR 방식보다 사용자가 화면을 보는 시간도 빨라진다.
그리고 첫 진입 이후에는 CSR 방식으로 동작하도록 하면 사용자가 url을 이용해도 페이지 깜빡임 없이 사용할 수 있게 된다.
root url 로 들어왔을 때 next.js는 index.js 라는 이름을 가진 파일을 찾는다.
그리고 해당 파일의 js 코드를 html로 변환해준다.
사이트 처음 진입시 next 서버가 내용이 모두 채워진 html을 내려준다.
예를 들어, domain.com url을 입력해서 진입을 하면 해당 페이지 내용이 모두 채워진 html을 서버로부터 응답 받고 domain.com/about url을 입력해서 진입을 하면 해당 페이지 내용이 모두 채워진 html을 서버로부터 응답받는다.
즉, SSR이 잘 동작한다.
이제 내부적으로 CSR을 어떻게 동작시키는지 알아보자.
next.js 기본 내장 기능인 next/link
나 next/router
를 활용하면 된다.
import React from 'react';
import Link from 'next/link';
export default function index() {
return (
<Link href={"/about"}>
About 페이지로 이동하기
</Link>
)
}
이런식으로 next/link를 이용해서 만들어준 Link 태그를 화면에서 클릭하게 되면 about 페이지로 이동되지만 서버로부터 새로운 html 파일을 받지 않는다.
즉, CSR 방식으로 동작하게 되는데, Link 태그를 화면에서 클릭하게 되면 js 파일이 실행되서 이동한 페이지 내용에 맞는 DOM의 내용으로 변경된다. (갈아끼워지는 형태)
next/router
도 CSR 방식으로 동작한다.
Next.js 의 export 기능으로 Static Site Generator 로 사용할 수 있다.