과거 리액트 애플리케이션을 만들 때 CRA가 각광을 받았지만 요즘은 서버 사이트 렌더링을 지원하는 Next.js와 같은 프레임워크가 큰 인기를 끌고 있다.
서버 사이트 렌더링이란
싱글 페이지 애플리케이션(SPA)
SPA란 렌더링과 라우팅에 필요한 대부분의 기능을 서버가 아닌 JS에 의존하는 방식을 의미한다.
최초에 첫 페이지에서 데이터를 모두 불러온 후 페이지 전환을 위한 모든 작업이 JS와 브라우저의 history.pushState와 history.replaceState로 이뤄진다.
이러한 작동 방식은 최초에 로딩해야 할 JS 리소스가 커지는 단점이 있지만 첫 로딩 이후 서버를 거쳐 필요한 리소스를 받아올 일이 적어져 사용자에게 훌륭한 UI/UX를 제공한다는 장점이 있다.
전통적인 방식의 애플리케이션 vs SPA 방식
과거 서버 사이드에서 작동하던 전통적인 방식의 애플리케이션은 페이지 전환이 발생할 때마다 새롭게 페이지를 요청하고 HTML 페이지를 다운로드해 파싱하는 작업을 거친다.
이런 방식을 사용하면 어쩔수 없이 페이지 전환시 부자연스러운 모습이 발생한다.
하지만 이러한 방식을 모두 JS로 한다면 최초에 한번 모든 리로스를 다운받고 페이지 전환시 필요한 일부 영역만 다시 그리기 때문에 리소스를 다운로드 받는 작업을 스킵하며 자연스러운 페이지 전환이 가능하다
현재 SPA 애플리케이션 중 가장 완성도가 높다고 손곱히는 대표적인 페이지는 Gmail이다.
Gamil에서는 loading 화면으로 모든 리소스를 가져온 후에는 매끄럽게 페이지 전환이 되는 모습이다.
이러한 장점을 위해 많은 웹 페이지들이 SPA 방식을 채택하고 있다.
SPA 방식의 등장 배경
과거 PHP나 JSP를 기반으로 대부분이 웹 애플리케이션을 만들때는 서버 사이드가 많이 이뤄졌다. 과거에도 JS가 사용되기는 했지만 어디까지나 보조역활을 주로 담당했다.
그러나 JS가 점점 다양한 작업을 수행하게 되면서 JS의 모듈화 의견에 따라 CommonJS와 AMD(Asynchronous Module Definition)가 등장했다. 이러한 JS 모듈화, 사용자 기기의 성능 향상, 인터넷 속도 발전 등과 함께 JS에서 할 수 있는 일이 점차 다양해졌다.
이러한 과정에서 등장한 React, Vue, Angular의 수요가 증가했으며 오늘날의 웹에서는 JS 없이는 페이지를 보여주는 것이 불가능할 정도로 JS에 의존하게 되엇다.
JAM 스택
LAMP(Linux, Apache, MySQL, PHP/Python)으로 구성되어 있던 기존의 웹 개발 구조는 대부분의 처리를 서버에서 했어야 했다.
하지만 React와 같은 프레임워크의 등장으로 JAM(Javascript, API, Markup) 스택 개발 구조가 가능해졌다. 이에 따라 MEAN(MongoDB, Express.js, Angular, Node.js), MERN(MongoDB, Express.js, React, Node.js) 등 API 서버까지 JS로 구현하는 구조가 등장했다.
이제 JS 파일의 크기의 변천사를 확인해보자.
SPA으 유행과 더불어 2000년대에 비해 JS 파일의 크기가 10배 정도 늘어난 것을 확인할 수 있다. 그렇다면 웹 페이지 속도는 얼마나 개선되었을까?
기술 발전이 획기적으로 일어났음에도 로딩속도의 발전은 미비할 정도임을 확인할 수 있다. 특히 모바일에서 웹페이지 로딩은 눈에 띄일정도로 미비한것같다.
이 모든것이 SPA 탓이라는 것은 아니다. 현재의 웹 애플리케이션은 과거에 비교해 정말 많은 기능을 갖고 있다.
그럼에도 중요한 사실은 사용자의 기기와 인터넷 속도 등 웹 환경이 크게 개선됐음에도 불구하고 과거보다 개선된 사항은 거의 없다는 것이다.
위의 그래프에서 평균적으로 모바일 페이지에서 대기해야하는 시간이 10초 이상이 걸리는 것을 확인할 수 있는데, 과거보다 더 많은 작업을 처리하기 때문이라는 변경은 치사한 변명이다.
웹사이트 방문자들은 참을성이 없기에 개발자들은 서비스 환경에 대해 한 번 더 고민할 때다.
서버 사이트 렌더링이란?
SPA가 JS를 활용해 하나의 페이지에서만 렌더링을 수행한다면, SSR은 최초에 사용자에게 보여줄 페이지를 서버에서 렌더링해 빠르게 사용자에게 화면을 제공하는 방식이다.
서버 사이드 방식을 채택하면 렌더링에 필요한 작업을 모두 서버에서 수행하기 때문에 안정적인 렌더링이 가능하다.
SSR(서버 사이드 렌더링)의 장점
1. 최초 페이지 진입이 빠르다.
First Contentful Paint(최초 페이지에 접근해서 유의미한 정보가 그려지는 시간)이 빠르다. SPA의 경우 페이지에 진입하고 JS 리소스 파일들을 다운로드 하고 API 요청 등의 작업이 이뤄진 이후 화면에 렌더링이 이뤄진다.
화면 렌더링이 HTTP 요청에 의존적이거나 렌더링할 HTML 파일이 커진다면 SSR 방식이 더 빠르다. 다만 서버가 사용자에게 렌더링을 제공할 수 있을 정도의 충분한 리소스가 있는 경우에 유리하다는 점을 알아두자.
2. 검색 엔진과 SNS 공유 등 메타데이터 제공이 쉽다.
SSR은 검색 엔진 최적화에 유용하다. 검색 엔진이 사이트에서 정보를 가져가는 순서는 아래와 같다.
- 검색 엔진 로봇(머신)이 페이지에 진입
- 페이지가 HTML 정보를 로봇에게 제공하여 HTML을 다운로드(단, JS는 실행하지 않는다)
- HTML 페이지 내부의 오픈 그래프나 메타 태그 정보를 기반으로 페이지의 정보를 가져오고 검색 엔진에 저장
검색 엔진은 페이지 내부의 JS 코드를 실행하지 않는다. 이로인해 JS 코드의 실행이 렌더링과 직접적으로 연관되는 SPA은 검색 엔진에서 불리하게 작용된다.
SSR은 검색 엔진에 제공할 정보를 서버에서 가공해서 HTML 응답으로 제공할 수 있으므로 SEO에 대응하기 매우 용이하다.
3. 누적 레이아웃 이동이 적다.
누적 레이아웃 이동이란 페이지를 보여준 이후에 뒤늦게 어떤 HTML 정보가 추가되거나 삭제되어 화면이 덜컥거리는 것과 같은 부정적인 사용자 경험을 말한다. 뒤늦게 광고가 로딩되어 읽고 있던 글이 아래로 내려가는 경우와 같은 현상.
SPA의 API 응답 결과의 시간이 제작각이기 때문
반면 SSR의 경우 이러한 요청이 완전히 완료된 이후에 완성된 페이지를 제공하므로 이러한 문제에 비교적 자유롭다.
하지만 SSR을 사용한다 해도 useEffect와 같은 훅을 사용한다면 이러한 문제가 발생할 수 있다. 하지만 React 18에서 등장한 스트림으로 해결할 수 있다.(신기하다😅)
4. 사용자의 디바이스 성능에 비교적 자유롭다.
JS 리소스 실행은 사용자 디바이스에서만 실행되므로 100% 의존적이다. 하지만 SSR을 이용하면 이러한 부담을 서버에서 나눌 수 있으므로 디바이스 성능으로부터 조금 더 자유로워질 수 있다.
물론 인터넷 속도가 느리거나 서버 부담 증가와 같은 문제를 처리하지 않으면 SSR도 충분히 느려질 수 있다.
5. 보안에 좀 더 안전하다.
JAM 스택을 채택하면 애플리케이션의 모든 활동의 브라우저에 노출된다. 특히 API 호출과 인증같은 민감한 작업들도 포함되어 있어 이러한 부분을 염두하고 개발해야 한다.
정상적인 비즈니스 로직을 거치지 않은 상황에서 인증이나 API가 호출되는 것을 방지해야 한다.
반면 SSR의 경우 인증 혹은 민감한 작업을 서버에서 수행하고 그 결과만 브라우저에 제공해 이러한 보안 위협을 피할 수 있다는 장점이 있다.
서버 사이드 렌더링의 단점
1. 소스코드 작성시 서버를 고려해야 한다.
브라우저 전역 객체인 window 또는 sessionStorage와 같이 브라우저에만 있는 전역 객체 등을 실행하면 오류가 발생한다. 특히 이런 window 사용을 위해서는 이를 서버 사이드에서 실행되지 않도록 생각해야 한다는 문제가 있다.
window와 같은 전역 객체에 대한 접근을 최소화 해야 하며, 사용이 불가피 하다면 서버 사이드에서 실행되지 않도록 해야한다.
하지만 결국 이런 경우가 반복되면 SSR의 장점을 잃을 수 있다.
2. 적절한 서버의 구축
SSR은 말 그대로 사용자의 요청을 받아 렌더링을 수행할 서버가 필요하다. 또한 사용자 환경에서의 부담이 줄어드는 것은 서버의 부담이 커지는 것과도 같은 말이다.
3. 서비스 지연에 따른 문제
싱글 페이지에서 지연이 일어나면 "로딩중"과 같은 안내를 표현할 수 있지만, 서버 사이드에서 지연이 일어나면 사용자는 어떠한 정보도 받을 수 없다.
애플리케이션의 규모가 커지고 복잡해질 때 SSR은 때때로 SPA보다 더 안좋은 사용자 경험을 제공할 수 있다.
SSR은 만능이 아니다.
잘못된 서버 사이드 웹페이지는 오히려 성능을 해칠 뿐만 아니라 관리 포인트가 서버, 클라이언트로 나눠지는 역효과를 가질수도 있다.
설계와 목적, 그리고 우선순위에 따라 SPA이 더 효율적일 수 있다는 점을 염두하자.
싱글 페이지 애플리케이션 vs 서버 사이드 렌더링 애플리케이션
1. 가장 뛰어난 싱글 페이지 애플리케이션은 가장 뛰어난 멀티 페이지 애플리케이션보다 낫다.
Gmail과 같이 완성도가 높은 싱글 페이지 애플리케이션은 최초 페이지 진입시에 보여줘야할 정보를 최적화해 요청해서 렌더링하고, 이미지와 같은 중요성이 떨어지는 리소스는 게으른 로딩으로 렌더링에 방해하지 않도록 처리, 코드 분할도 잘 지켜 사용자 경험이 매우 좋다.
결국 멀티 페이지 애플리케이션이 아무리 최적화를 잘 해도 브라우저 API와 JS를 활용한 라우팅을 기반으로한 SPA를 이기기는 힘들다.
2. 평균적인 싱글 페이지 애플리케이션은 평균적인 멀티 페이지 애플리케이션보다 느리다.
일반적인 SPA는 렌더링, 라우팅에 최적화를 신경을 쓰지 않는 경우에 사용자 환경에 따라 성능이 의존된다. 이는 멀티페이지 애플리케이션보다 성능적으로 아쉬운 경우가 많다. 또한 최근 멀티 페이지 애플리케이션에서 발생하는 라우팅 문제를 해결하기 위해 다양한 API가 브라우저에 추가되고 있다.
- Paint Holding: 같은 출처에서 라우팅이 일어나는 경우 화면을 하얗게 띄우는 대신 이전 화면을 보여주는 기법
- back forward cache: 브라우저 앞으로 가기, 뒤로가기 실행 시 캐시된 페이지를 보여주는 기법
- Shared Element Transition: 페이지 라우팅이 일어났을때 동일 요소가 있다면 이를 유지하는 기법
SPA와 MPA가 상황에 따라 유효한 방법이란 것을 이해하자. 두 방법 모두 장단점이 있다.
SPA가 제공하는 보일러플레이트나 라이브러리가 점차 완벽해지면서 잠재적인 위험을 제거할 수도 있다.
MPA가 브라우저 API의 도움을 받아 SPA와 같은 끊김 없는 UX를 제공할 수도 있다.
현대의 SSR
현대의 SSR은 과거의 LAMP 방식과는 조금 다르다. 요즘 SSR은 싱글 페이지 렌더링과 서버 사이드 렌더링의 장점을 모두 취한 방식으로 작동한다.
최초 웹사이트 진입시 서버에서 완성된 HTML을 제공 받고, 라우팅에서는 서버에서 내려받은 JS를 바탕으로 SPA처럼 작동한다.
Next.js와 Remix등의 SSR 프레임워크는 이러한 방식으로 작동한다.
따라서 프론트엔드 개발자는 서버에서의 렌더링, 그리고 클라이언트에서의 렌더링을 모두 이해해야 두 가지 장점을 완벽하게 취하는 제대로된 웹서비스를 구축할 수 있다.
'React > 모던 리액트 Deep Dive' 카테고리의 다른 글
[React Deep Dive] Next.js (1) | 2025.06.06 |
---|---|
리액트와 서버사이드 (0) | 2025.06.03 |
사용자 정의 훅과 고차 컴포넌트 (0) | 2025.04.28 |
useContext와 useReducer, useImperativeHandler, useLayoutEffect, useDebugValue (0) | 2025.04.22 |
useMemo, useCallback와 useRef (0) | 2025.04.09 |