CRP 프로세스/ SPA, MPA/ 렌더링(CSR, SSR, SSG)/ SEO
Next.js 공부하기 전에 기본적인 개념정리가 필요할 것 같아서 기록하는 글.
아래에 언급될 기초적인 내용들에 대해서 예전에 블로그에 정리해둔게 있어서 링크도 첨부한다!🙂
※ 서버와 클라이언트 - https://hjinn0813.tistory.com/17
※ DOM - https://hjinn0813.tistory.com/25#DOM-1

기본적인 브라우저 렌더링 원리 (CRP 프로세스)
브라우저는 렌더링엔진을 사용해서 화면에 나타나는 요소를 렌더링한다.
브라우저가 화면을 렌더링하는 과정을 'CRP 프로세스'라고 하며, 순서는 아래와 같다.
- HTML 다운로드, 파싱, DOM트리 구축
- CSS 파싱, CSSOM트리 구축
- Javascript 발견 및 실행하느라 HTML 파싱 일시 중단
→ 만약 script 태그에 defer나 async 속성이 있으면 처리 방식이 달라지는데, 기본적으로는 위의 순서로 작동한다. - HTML 파싱 재개
- DOM과 CSSOM을 조합하여 렌더트리 구축
→ display: none 처럼 화면에서 안 보고 공간을 차지하지 않는 것은 렌더트리로 구축되지 않는다. - 뷰포트 기반으로 렌더트리의 각 노드가 가지는 정확한 위치와 크기 계산하여 Layout 만들기
- 계산한 위치/크기를 기반으로 화면에 Paint 하기
💡 CRP (Critical Rendering Path, 중요 렌더링 경로)
브라우저가 HTML, CSS, JS를 화면에 픽셀로 변화하는 일련의 단계.
Document Object Model (DOM), CSS Object Model (CSSOM), 렌더 트리, 레이아웃을 포함한다.
※ 렌더링엔진: 크롬은 블링크(Blink), 사파리는 웹킷(Webkit), 파이어폭스는 게코(Gecko)
💡 head 태그 내부에 있는 script 태그에 defer 속성을 쓰는 이유
앞서 설명한 CRP 프로세스처럼, HTML은 파싱되다가 JS를 발견하면 파싱을 중단하고 JS부터 가져온다.
이때 script 태그에 defer 속성이 없으면,
- DOM 요소 접근 불가: JS부터 로드되어 동작 가능한 상태가 되지만, 아직 HTML은 로드되기 전이라서, JS가 필요한 요소를 찾을 수 없어서 오류가 발생할 수 있다.
- 페이지 로딩 지연: JS 로드하느라 HTML 파싱이 멈추면서 화면이 늦게 렌더링되고 UX가 나빠진다.
반면에 defer 속성을 사용하면 HTML을 먼저 파싱한 뒤 스크립트를 실행하므로, HTML 구조가 완전히 로드되기 전에 스크립트가 실행되는 것을 방지할 수 있다.
싱글 페이지 어플리케이션 - SPA (Single Page Application)
최초 한번 페이지를 로딩한 이후, JS로 동적으로 데이터만 변경하여 컨텐츠를 바꾸는 방식.
- 하나의 페이지로 이루어진 홈페이지로서, 모바일 최적화를 위해 등장했다고 한다.
- 서버는 JSON 파일만 보내주고, HTML을 그리는 역할은 클라이언트에서 JS로 수행하기 때문에 CSR 방식에 적합하다.
- 데이터를 수정/조회할 때 동적으로 페이지를 구성하기 때문에, 페이지가 새로고침되지 않고 다른 페이지로 넘어가지 않는다.
- React, Vue, Angular로 만든 홈페이지가 대부분 속한다.
멀티 페이지 어플리케이션 - MPA (Multiple Page Application)
- 여러 개의 페이지로 이루어진 홈페이지로서, 데이터가 바뀔 때마다 새로고침이 발생한다.
- SSR 방식에 적합하다.
- PHP, Java로 만든 페이지가 속한다.
클라이언트 사이드 렌더링 - CSR (Client Side Rendering)
클라이언트 측에서 JavaScript를 사용하여 동적으로 콘텐츠를 생성하는 방식
CSR의 작동원리
- 유저가 브라우저로 홈페이지에 접속을 시도한다. (website 요청)
- 서버(CDN)가 클라이언트의 요청을 받아서 빈 HTML과 모든 로직이 담긴 JS를 보내준다.
- 브라우저가 JS 파일을 다운로드하는 동안, 유저는 빈 화면을 보게 된다.
- JS 다운로드가 끝나고 실행된다. 데이터를 위한 API가 호출된다.
- 클라이언트가 빈 HTML 문서에 JS로 DOM을 동적으로 생성하여 페이지 렌더링 (서버가 API 요청에 응답)
- 유저는 드디어 원하는 화면을 보게 된다. (상호작용 가능 → TTV와 TTI가 동시에 일어난다.)
CSR의 장점
- 페이지 이동 시에 렌더링이 빠르다.
사용자의 행동에 따라 JS로 동적으로 DOM을 그리니까 원하는 내용만 업데이트할 수 있기 때문이다.
ex) 링크 이동했을 때, Header와 Footer 같이 중복되는 내용은 두고 컨텐츠만 업데이트하여 로드하는 것.
→ 그러므로 SPA 형식의 어플리케이션에서 적합한 기법! - 사용자와 상호작용할 때 사용자 경험(UX)이 좋다.
페이지 이동 시에 깜빡임이 없고 바로 렌더링되니까 사용성이 좋다. - 서버의 부하가 줄어서 성능이 좋다.
서버에서는 요청할게 없고, 데이터가 필요할 때 주고 받는 일만 하기 때문이다.
또한 전체를 렌더링하는게 아니라, 중복되는 부분은 제외하고 필요한 부분만 업데이트하니까.
CSR의 단점
- 처음 페이지 열릴때 로딩 속도가 길다.
첫 로드시에 HTML, CSS와 모든 로직이 있는 JS까지 받아야해서 다운로드에 시간이 걸릴 수 있다. - 앱이 커지면서 필요한 JS의 양이 증가할 수 있다.
- SEO에 취약하다.
빈 HTML 하나만 받아와서 내부 컨텐츠만 바꿔가면서 작동하니까, 웹 크롤러가 빈 페이지를 인지하지 못한다.
수익성 측면에서 단점.
서버 사이드 렌더링 - SSR (Server Side Rendering)
서버에서 모든 콘텐츠가 준비된 HTML을 생성하여 클라이언트로 전송하는 방식
클라이언트에서 요청할 때마다 상황에 맞는 HTML 파일을 주기 때문에, 페이지가 여럿일 수 밖에 없다.
SSR의 작동원리
- 유저가 페이지에 접속한다.
- 서버는 리소스 체크하고 컴파일하여 완성된 HTML을 만든다.
- HTML이 클라이언트에 전달되면서 즉시 렌더링되지만, JS 파일을 받기 전이라서 작동은 불가능. (TTV만 일어난 상태)
- 클라이언트가 JS를 다운로드한다. 역시 유저는 볼 수는 있지만 작동은 불가능.
- 브라우저가 JS 프레임워크를 실행한다.
- JS가 컴파일되면 완성된 HTML에 JS가 연결되고, 4번에서 기억하고 있던 사용자 조작이 실행되며 상호작용이 가능해진다.
SSR의 장점
- 자바스크립트가 비활성화된 환경에서도 페이지를 볼 수 있다.
- 검색 엔진 최적화(SEO)에 유리하다.
→ 서버에서 완성한 HTML을 클라이언트에게 제공하여, 검색 엔진이 콘텐츠를 쉽게 인덱싱할 수 있기 때문 - 처음 페이지 열릴 때 렌더링이 빠르다.
→ 클라이언트가 요청한 페이지의 HTML과 JS만 다운로드하니까
(페이지 구성 속도는 느려도, 사용자에게 보여주는 콘텐츠 구성은 빠르다.)
SSR의 단점
- 화면 깜빡임 현상이 있어서 UX가 떨어진다.
→ 페이지를 요청할 때마다 새로운 HTML 파일을 서버에서부터 받아와야 하기 때문이다. - 서버의 부하가 크다.
→ 간단한 데이터 수정도 서버에 매번 요청해서 모든걸 처리하기 때문 - 페이지 이동이 느리다. (초기 진입만 빠름)
→ 첫 페이지 렌더링한 과정을 정확하게 다시 실행한다.
예를 들어, 중복되는 Header나 Footer까지 다시 렌더링해서 받아오니까 느릴 수 밖에 없다. - TTV가 먼저 일어나고 TTI가 일어난다.
→ JS보다 완성된 HTML을 먼저 받아와서, 만약 JS 다운로드가 늦어지면 화면은 확인되지만 기능이 동작하지 않을 수 있다.
💡 TTV, TTI
- TTV (Time To View): 사용자가 웹페이지나 앱을 열었을 때, 콘텐츠가 로딩되고 사용자가 시각적으로 내용을 보는 데까지 걸리는 시간. 즉, 사용자가 페이지를 본 순간부터 콘텐츠가 보이기 시작할 때까지의 시간.
- TTI (Time To Interact): 사용자가 페이지에서 실제로 클릭하거나 스크롤 같은 상호작용을 할 수 있게 되는 시간. 페이지가 완전히 로딩되고 사용자가 자유롭게 이용할 수 있는 상태가 될 때까지의 시간.
정적 사이트 생성 - SSG(Static Site Generation)
모든 유저에게 똑같이 보여져서 렌더링이 필요하지 않는 부분은 정적으로 만들고 따로 저장해서 바로 그려내는 방식
HTML이 정적이기 때문에 '정적 사이트 생성'이라고 부른다.
Next.js에서 권장하는 렌더링 방식. 이외에도 Gatsby, Nuxt.js에서 제공한다.
(Next.js는 React에서, Nuxt.js는 Vue에서 SSR 도입이 가능한 프레임워크)
SSG 방식은 데이터가 고정적이고 잘 변화하지 않는 사이트에 적합하다. (블로그, 정보성 페이지 등)
SSG의 작동원리
- 서버는 모든 가능한 요청에 대한 HTML을 미리 생성한다. (HTML 파일의 생성시점이 빌드 타임이다)
- 유저가 웹사이트에 접속하면 서버는 완성된 HTML을 보낸다.
- 브라우저는 받은 HTML을 표시한다.
- 클라이언트가 추가 페이지 요청하면, 미리 만들어둔 해당 페이지의 HTML을 보낸다.
SSG의 장점
- 렌더링 속도가 매우 빠르다.
→ 가능한 페이지를 모두 만들어뒀다가 요청이 들어오면 제공하니까 - 서버 부하가 감소된다.
→ 미리 만들어놓은 HTML만 제공하니까 - SEO가 좋다.
→ 부분적으로 업데이트하는 CSR의 장점을 유지하면서, SSR처럼 서버에서 완성된 HTML을 가져오기 때문에
SSG의 단점
- 데이터 변경이 불편하다.
→ 사이트의 데이터가 변경될 때마다 전체 사이트를 다시 빌드해야 한다. - 모든 URL에 대해 개별 HTML 파일을 생성해야 한다.
→ URL을 예측할 수 없으면 적용 불가능.
SSR, SSG는 모두 HTML을 미리 렌더링하는 방식이어서 Pre-rendering 이라고도 부른다!
검색엔진 최적화 - SEO (Search Engine Optimization)
웹사이트가 검색 엔진에서 상위 노출되어, 자연 유입되는 트래픽의 양과 질을 높일 수 있도록 최적화하는 과정
대부분의 웹 크롤러는 HTML에서만 컨텐츠를 수집하기 때문에 CSR 방식으로 개발된 페이지를 빈 페이지로 인식한다.
SSR 방식은 페이지 내용을 서버에서 전부 렌더링하니까, HTML에 모든 컨텐츠가 저장되어 있어 SEO를 사용하기 좋다.
참고자료
https://f-lab.kr/insight/comparing-ssr-and-csr
https://ajdkfl6445.gitbook.io/study/web/csr-vs-ssr-vs-ssg
https://klmhyeonwooo.tistory.com/68
https://guiyomi.tistory.com/125