Q) 🤵♂ SPA, CSR, SSR의 차이에 대해서 설명해주세요.
SPA, CSR, SSR은 웹 애플리케이션을 구축하는 다양한 방식으로 각기 다른 렌더링 방식으로 동작합니다.
SPA
SPA(Single Page Application)는 하나의 HTML 페이지로 애플리케이션을 실행하고 그 안에서 페이지가 동적으로 업데이트 되는 방식입니다.
즉, 사용자가 페이지를 이동할때마다 전체 페이지를 새로고침하지 않고 필요한 데이터만 서버에 요청하고 부분적으로 업데이트합니다.
index.html

id가 root인 태그에 App 컴포넌트 렌더링

이후 페이지를 전환할때마다 #root div 태그안에 들어가는 코드들을 갈아끼우는 방식
정확히는 라우팅 처리된 컴포넌트들로 갈아끼워진다.

부가 설명
특징
1.초기 로딩이 끝난 후 페이지가 전환될때마다 서버와의 통신을 통해 데이터를 가져오고, HTML의 일부만 변경됩니다.
2.대표적인 프레임워크로 React, Vue, Angular가 있습니다.
장점
1.페이지 전환시 새로고침이 없기 때문에 빠른 페이지 전환이 가능합니다.
2.클라이언트에서 주로 처리하기 때문에 서버 부하가 적을 수 있습니다.
전통적인 웹 애플리케이션은 서버에서 HTML파일을 렌더링해서 클라이언트에 내려주는 방식을 사용합니다.
그러나 SPA 방식은 사용자가 다른 페이지로 이동할 때마다 서버에 렌더링이 완료된 HTML 파일을 요청하는 대신,
필요한 데이터(예:목록, 정보, 이미지..)만 요청하고, 클라이언트에서 이를 처리하여 화면을 동적으로 갱신합니다.
이 구조 덕분에 서버는 매번 전체 페이지를 렌더링할 필요 없이, 필요한 데이터만 보내면 되기 때문에 부하가 적습니다.
3.동적이고 직관적인 UX를 제공할 수 있습니다.
단점
1.초기에 모든 코드들이 로드되기 때문에 로딩 시간이 길 수 있습니다.
2.검색 엔진 최적화(SEO)가 어려울 수 있습니다.
궁금했던 부분들 🤔
1.초기 로딩 시 자바스크립트, HTML, CSS 파일을 한 번에 로드하면 다른 페이지로 전환하더라도 페이지를 렌더링하는데 시간이 걸리면 안되는 거 아닌가?
SPA는 초기 로딩 시 자바스크립트, HTML, CSS 파일을 한 번에 로드하긴 하지만
모든 데이터 요청을 다 처리하지 않습니다. 일반적으로 첫 번째 페이지 렌더링에 필요한 최소한의 데이터만 요청합니다.
이후 페이지 전환 시 필요한 데이터를 동적으로 요청하고 비동기적으로 처리하기 때문에, 데이터 요청이 끝날 때까지 페이지 렌더링에 시간이 걸릴 수 있습니다.
예를들어, 우리는 페이지 전환시 대략적인 페이지는 바로 나오지만 이미지같은 리소스들이 많다면 이러한 데이터들은 조금씩 조금씩 렌더링되는 것을 경험해 보았을 것입니다.
2.웹 애플리케이션이 무거우면 초기 로딩시간이 많이 길어질것같은데 어떻게 해결하지?
웹 애플리케이션이 무겁다면 초기 로딩 시간이 길어질 수 있습니다.
이는 JavaScript 코드, 이미지, CSS 파일, 기타 리소스들이 많아지면 사용자가 페이지를 처음 방문할 때 다운로드해야 하는 데이터 양이 많아지기 때문입니다.
1) 코드 분할(Code Splitting)
코드 스플리팅은 애플리케이션의 코드를 여러 개의 작은 청크로 분할해서, 필요한 부분만 먼저 로드하고, 나머지는 나중에 필요할 때 로드하는 기법입니다.
예를 들어, 처음에 기본적인 페이지와 필요한 라이브러리만 로드하고, 나머지 페이지나 기능에 필요한 코드들은 사용자가 해당 페이지를 방문할 때 로드할 수 있습니다.
React에서는 React.lazy()와 Suspense를 사용하여 동적으로 컴포넌트를 로드할 수 있습니다.
// 예시: React에서 lazy loading
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const Login = lazy(() => import('./routes/Login'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/login" component={Login} />
</Switch>
</Suspense>
</Router>
);
2) 지연 로딩(Lazy Loading)
이미지, 비디오, 기타 미디어 파일들을 지연 로딩하는 기법입니다.
초기 로딩 시 화면에 보이지 않는 콘텐츠는 사용자가 스크롤하거나 해당 요소가 화면에 들어올 때 로드하도록 합니다.
HTML의 loading="lazy" 속성이나, JavaScript 라이브러리를 사용해 미디어 파일을 지연 로딩할 수 있습니다.
<img src="image.jpg" loading="lazy" alt="lazy loaded image" />
참고자료

3) Preloading & Prefetching
주요 리소스를 브라우저가 미리 다운로드하도록 설정하여 사용자 경험을 개선합니다.
<link rel="preload" href="/styles.css" as="style" />
<link rel="prefetch" href="/next-page.js" />
참고자료

4) 브라우저 캐싱 활용
브라우저 캐싱을 활용하여 이미 로드된 리소스를 다시 다운로드하지 않도록 할 수 있습니다.
서버에서 적절한 캐시 헤더를 설정하여 자주 변경되지 않는 리소스는 브라우저가 저장하도록 하여 재방문 시 빠르게 로드할 수 있습니다.
3.SPA가 검색엔진 최적화가 어려운 이유는?
SPA가 서버에서 페이지를 동적으로 렌더링하는 방식이기 때문에 검색 엔진 크롤러가 완전한 HTML 콘텐츠를 제대로 수집하기 어렵기 때문입니다.
1) 초기 렌더링 문제

SPA는 최초에 단일 HTML 파일이 로드되고 이후 JavaScript가 필요한 데이터를 가져옵니다. 초기 HTML에는 빈 콘텐츠나 필수적인 메타데이터만 포함되어 있어서 검색 엔진 크롤러가 페이지를 처음 방문했을 때 실제 콘텐츠를 제대로 볼 수 없습니다.
예를 들어, index.html에 필요한 콘텐츠가 전혀 포함되지 않고, JavaScript로 동적으로 로드되면, 검색 엔진은 해당 콘텐츠를 제대로 인식하지 못해 검색 결과에 반영되지 않을 수 있습니다.
2) JavaScript 렌더링이 필요
SPA는 페이지 전환 시 전체 페이지를 새로 로드하지 않고, JavaScript가 동적으로 콘텐츠를 로드하고 렌더링합니다.
그러나 검색 엔진 크롤러는 JavaScript를 실행할 수 있는 능력이 제한적이기 때문에, JavaScript가 실행되어 렌더링된 콘텐츠를 인식하지 못합니다.
3) 동적 URL 변경
SPA에서는 URL이 동적으로 변경됩니다. 예를 들어, /movie, /tv와 같은 URL을 동적으로 변경하지만, 서버에는 새로운 HTML 파일을 요청하지 않습니다.
이 과정에서 검색 엔진은 URL의 변화를 추적하고, 그에 따라 페이지 콘텐츠를 분석하는 데 어려움을 겪을 수 있습니다.
왜냐하면 검색엔진은 서버에서 해당 페이지의 HTML 파일을 받고 분석을 하기 때문입니다.
해결법은...
1) 서버 사이드 렌더링(SSR)
2) 프리렌더링(Pre-rendering)
프리렌더링은 웹 페이지의 HTML을 사전에 생성해 정적 콘텐츠 형태로 제공하는 방식입니다.
빌드 시점에 HTML 파일을 생성하고 배포합니다.
주로 정적 콘텐츠가 많은 페이지에 적합하며, React에서는 Static Site Generation(SSG) 방식으로 구현합니다.
SPA를 활용한 유명 사이트들
meta, twitter, Netflix, Airbnb....
CSR
CSR(Client Side Rendering)으로 말 그대로 클라이언트 측 렌더링을 말합니다.
즉, 사용자가 웹 페이지를 요청하면 서버는 기본적으로 HTML을 제공하고 이후 JS를 사용하여 페이지의 콘텐츠와 동작을 클라이언트 측에서 처리하는 방식입니다.
이 방식은 SPA과 밀접한 관련이 있습니다.
부가 설명
CSR과 SPA의 차이
사실 CSR과 SPA는 차이라고 할 것이 없습니다.
왜냐하면 하나의 HTML 페이지에서 동적으로 콘텐츠를 변경하는 SPA는 CSR을 활용한 애플리케이션의 형태이기 때문입니다.
즉, 앞에서 말한 SPA에 관한 내용이 전부 CSR의 특징이라고 할 수 있습니다.
CSR의 동작 과정
1. 초기 요청: 사용자가 웹사이트를 방문하면 서버는 기본적인 HTML 구조와 JavaScript 파일을 응답으로 보냅니다.
2. JavaScript 실행: 브라우저는 JavaScript 파일을 실행하여 DOM을 수정하고,
데이터 요청(API 호출 등)을 통해 화면을 업데이트합니다.
3. 페이지 전환: 사용자가 다른 페이지로 이동할 때, 기존 페이지를 다시 로드하지 않고 JavaScript를 통해 필요한 데이터를 요청하여 페이지를 동적으로 갱신합니다.
4. API 호출: 클라이언트는 서버의 API를 통해 필요한 데이터를 받아오고, 이를 클라이언트 측에서 렌더링하여 화면을 갱신합니다.
SSR
SSR(Server Side Rendering)은 말 그대로 서버 측 렌더링을 말합니다.
즉, 웹 애플리케이션에서 HTML 콘텐츠를 서버에서 렌더링한 뒤, 완성된 HTML을 클라이언트에 전달하는 방식입니다. 브라우저는 전달받은 HTML을 그대로 렌더링하기 때문에, 빠른 초기 렌더링과 검색엔진 최적화(SEO)를 지원합니다.
부가설명
SSR의 동작 방식
1. 사용자가 페이지 요청
브라우저가 특정 URL로 서버에 요청을 보냅니다.
2. 서버에서 HTML 생성
서버는 JS를 실행해서 해당 페이지의 HTML을 완성한 후 클라이언트로 전송합니다.
3. 브라우저에서 렌더링
브라우저는 서버에서 받은 HTML을 렌더링합니다.
클라이언트 측에서 어떤 동작을 하면 때 클라이언트 측에서 API 요청을 통해 페이지가 동적으로 동작합니다.
SSR의 장점
1. SEO 최적화
• 크롤러가 완성된 HTML을 바로 읽을 수 있어 검색엔진 친화적입니다.
2. 빠른 초기 렌더링
• 사용자는 완성된 HTML을 바로 받으므로 콘텐츠를 즉시 볼 수 있습니다.
3. 실시간 데이터 제공
• 사용자의 요청에 따라 실시간 데이터를 서버에서 처리하고 렌더링할 수 있습니다.
• 즉, 서버에서 HTML을 생성할 때, 백엔드와 연결된 데이터베이스나 API로부터 최신 데이터를 가져와 페이지에 반영합니다.
SSR의 단점
1. 서버 부하 증가
• 각 요청마다 서버에서 HTML을 생성해야 하므로, 높은 트래픽을 처리하기 위해 강력한 서버 환경이 필요합니다.
2. 느린 페이지 전환
• 새로운 페이지 요청마다 서버와의 통신이 필요하므로 SPA보다 페이지 전환 속도가 느릴 수 있습니다.
3. 복잡한 설정
• SSR을 구현하려면 서버를 설정하거나 프레임워크(예: Next.js, Nuxt.js)를 사용해야 하므로 CSR보다 복잡합니다.
단점을 보완할 수 있는 방법
Next.js의 SSR과 SSG 혼합 사용
Next.js는 SSR을 간단히 구현할 수 있는 프레임워크입니다.
또한 Next.js는 정적인 페이지는 SSG(Static Site Generation)로,
동적인 페이지는 SSR로 렌더링하는 하이브리드 방식을 사용할 수 있습니다.
SSG 사용: 페이지가 변하지 않거나 변화가 적은 부분에 대해서는 SSR 대신 SSG를 사용하여 서버 부하를 줄이고, 클라이언트의 로딩 시간을 최소화할 수 있습니다.
export async function getStaticProps() {
// 정적 페이지 생성
}
export async function getServerSideProps() {
// 서버에서 동적 렌더링
}
CSR vs SSR
단계 | CSR | SSR |
초기 요청 | HTML 껍데기와 JavaScript를 받아옴 | 서버에서 HTML 생성 후 클라이언트로 전달 |
초기 렌더링 | 브라우저가 JavaScript를 실행하여 화면 렌더링 | 브라우저가 서버에서 받은 HTML을 즉시 렌더링 |
데이터 요청 | 클라이언트에서 API 요청을 통해 데이터 로드 | 서버에서 데이터 처리 후 HTML에 포함 |
SEO | JavaScript 실행 후 콘텐츠 로딩되므로 SEO에 부적합 | 완성된 HTML 제공으로 SEO에 유리 |