렌더링이란?
쉽게 말해서 우리가 평소에 핸드폰으로 유튜브를 보거나 컴퓨터를 통해서 쇼핑몰 사이트에서 쇼핑을 하듯이 화면에 출력이 되는걸 렌더링이라고 표현을 해!
프코 : 인제 렌더링이 무엇인지 바로 느낌이 오지??
자 그럼 렌더링 방식은 무엇이냐?
- 먼저 초창기에는 MPA(Multi-Page-Application)라는 SSR방식으로 화면을 렌더링 했었어.
- 여러 개의 정적 페이지를 미리 만들어 놓은 후 각 페이지별로 서버에 요청을 해서 HTML 문서를 서버에서 받아오는 방식
- 이러한 MPA의 방식은 미리 만들어 놓은 페이지를 다른 페이지로 이동 시 전체 페이지를 새로 로드하므로, 깜빡거리는 느낌이 사용자 경험이 떨어질 수 있고, 오래 걸리는 게 단점이었어!
- MPA 방식의 단점을 보완하고자 SPA(Single-Page-Application) 기반의 CSR(Client-Side-Rendering) 렌더링 방법이 탄생했어~!!
- 메타(구 페이스북)에서 개발한 JavaScript기반 라이브러리로, React 라이브러리를 활용해서 CSR을 구현하는 방식으로 발전했어!!
- 자 그래서 React는 무엇이고? CSR은 뭔데..? SPA는 또 뭐야...?
- React 란? CSR을 구현하기 위한 대표적인 도구라고 생각하면 될 거야!
- CSR이란? 브라우저가 특정 주소를 요청하면 서버는 특정 주소에 해당하는 id="root"인 텅 빈 HTML 파일을 브라우저에 전송해. 이 파일을 하나의 HTML 파일을 의미해서 SPA라는 의미를 뜻 해!
- 브라우저는 서버에서 넘겨준 빈 HTML파일을 먼저 브라우저가 읽을 수 있게 파싱을 거친 후 화면에 렌더링을 시작해 그 과정에서 파일에 script태그를 읽어 들인 후 다시 서버에 script태그가 담긴 자바스크립트 파일을 요청을 하면 서버는 요청에 맞는 모든 script태그가 담긴 파일을 다시 브라우저에 전송을 해
- 요약하자면 클라이언트는 먼저 빈 HTML을 파일을 파싱 후 하면에 렌더링을 한 후 그 이후에 자바스크립트 코드가 담긴 파일을 재요청해서 받은 후 자바스크립트 파일을 파싱 후 DOM을 동적으로 조작해 화면에 렌더링을 시작해!
- SPA(하나의 페이지)방식을 사용함으로써 페이지 이동시 전체 페이지를 로드하는 방식이 아닌 컴포넌트 단위인 자바스크립트 파일이 변경되는 부분만 실제 DOM과 가상 DOM의 차이를 인식 후 차이나는 부분만 리렌더링 한 후 리페인팅 과정을 거쳐 전체 화면이 깜빡이는 현상의 단점을 개선하고 부드럽게 변화하는 UI를 시전함으로써 사용자 경험(UX)이 크게 향상되는 장점이야!
- 즉 초기에 최초 한번 서버에 요청을 한 뒤에는 페이지 이동 시에 변화되는 곳을 인식 후 DOM을 조작 후 렌더링을 해주는데 이는 서버에 통신을 주고받는 방식이 아니라 클라이언트에서 처리함으로 페이지 이동시 빠른 로딩이 큰 장점이야!
- 오 그럼 MPA방식의 단점도 개선했고 사용자 경험도 증가했으니 완벽한 거 아니야?
- 그렇다고 하고 싶지만... 여기서 또 단점이 존재해... 많이 어렵지....? 그래도 한번 끝까지 읽어주길 바래!
- 브라우저는 초기에 빈 HTML을 파싱 후 화면에 렌더링 하잖아? 근데 이 과정에서 빈화면을 렌더링 하니 아무런 정보가 담겨 있지 않겠지..?
- 이 과정에서 검색엔진 SEO(Search-Engine-Optimization)에 불리해... ㅠㅠ
- SEO란 : 웹사이트가 유기적인(무료) 검색 방식을 통해 검색 엔진에서 상위에 노출될 수 있도록 최적화하는 과정이라고 생각하면 돼!
- 서비스를 제공하는 사업자 입장에서는 최대한 자기 사이트를 노출시켜 접촉을 시켜야 하는데? 아주 큰 단점이 되는 거네....?
- 그렇다고 하고 싶지만... 여기서 또 단점이 존재해... 많이 어렵지....? 그래도 한번 끝까지 읽어주길 바래!
3. 여기서 CSR의 가장 큰 단점 중 하나인 SEO 검색엔진의 불리함으로 인해 이를 개선하기 위해 다시 SSR 방식의 렌더링 방식을 다시 사용해!
- 자 여기서 SSR(Server-Side-Rendering)방식이 무엇이냐?
- 여기서 인제 Next.js 라는 프레임워크가 등장해!
- Next.js 프레임 워크란 : page router & app router 2가지 버전이 존재하며 SSR방식을 지원해주고 있어
- page router와 app router의 차이점은 데이터 패칭 부분에서 다른점이라고 생각하면 될거야!
- 브라우저가 페이지 이동 시 한 번만 서버에 요청하는 게 아닌 매번 요청하는 방식을 뜻 해!
- 서버는 매번 HTML 페이지를 동적으로 생성하여 브라우저에게 전달하는 방식이야!
- 어..? 그럼 MPA 방식의 단점이 다시 생기는 게 아니야...?
- 여기서 인제 Next.js 라는 프레임워크가 등장해!
4. 자 이러한 CSR 방식과 SSR 방식의 단점을 보완하고자 나온 게 SSG(Static-Site-Generation) 방식의 렌더링 기법이 탄생했어!!
- SSG란?
- 브라우저가 특정 주소로 서버에게 요청하는 과정에서 서버는 빌드 시점에 모든 정적 페이지가 미리 생성해 놔
- 그 후 브라우저가 특정 url을 요청하면, 서버는 이미 미리 생성된 정적 HTML 파일을 전달해
- SSR과의 차이점이 바로 이거야! SSR방식은 요청을 받은 후에 동적으로 HTML파일을 생성하고 SSG방식은 요청 전 빌드 시점에 정적 페이지를 만들어 놓은 후 미리 생성된 정적 HTML 파일을 건네주는 게 SSR과 SSG의 차이점이야!
- 그럼 CSR과 SSR의 단점의 두 마리 토끼를 다잡았으니 더 이상... 또 다른 단점이 존재하진 않겠지....?
- 미안... SSG 방식도 단점이 존재하고 있어....
- 위 표에 보면 데이터가 업데이트되면 재배포가 필요한 단점이 있어...!
5. SSG의 단점을 극복하고자 나온 방식이 ISR(Incremental-Static-Regeneration)이야 !
- ISR이란 SSG의 단점을 보완하면서도 동적 콘테츠를 처리할 수 있는 유연한 방법을 제공하는 렌더링 기법이야!
- revalidate 옵션을 사용해 일정 시간마다 데이터를 최신으로 받아온 후 업데이트 하여 재생성되도록 하는 옵션!!
CSR, SSR 방식의 lighthouse - 퍼포먼스 성능 차이 비교
자 먼저 Next.js 기준 CSR 방식의 코드를 보여줄게!
"use client";
import React, { useEffect, useState } from "react";
import Card from "./Card";
import { Article } from "../types/article";
export default function CSRPage() {
const [fetchData, setFetchData] = useState<Article[]>([]);
console.log("fetchData :", fetchData);
useEffect(() => {
const fetchData = async () => {
const res = await fetch(`https://newsapi.org/v2/everything?q=bitcoin&apiKey=${process.env.NEXT_PUBLIC_NEWS_API_KEY}`);
const { articles } = await res.json();
console.log("data :", articles);
setFetchData(articles);
};
fetchData();
}, []);
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 relative h-[800px] gap-6 p-20">
{fetchData.map((el, idx) => (
<Card key={idx}>
<Card.Title>{el.title}</Card.Title>
<Card.Author>{el.author}</Card.Author>
<Card.Content>{el.content}</Card.Content>
</Card>
))}
</div>
);
}
SSR기반 코드를 보여줄게!
import Card from "./Card";
import { Article } from "../types/article";
async function fetchData() {
const res = await fetch(`https://newsapi.org/v2/everything?q=bitcoin&apiKey=${process.env.NEXT_PUBLIC_NEWS_API_KEY}`);
const { articles } = await res.json();
return articles;
}
export default async function SSRPage() {
const data: Article[] = await fetchData();
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 relative h-[800px] gap-6 p-20">
{data.map((el, idx) => (
<Card key={idx}>
<Card.Title>{el.title}</Card.Title>
<Card.Author>{el.author}</Card.Author>
<Card.Content>{el.content}</Card.Content>
</Card>
))}
</div>
);
}
- 참고로 Next.js App Router버전은 모든 환경이 Server Component에서 동작되고 있어!
- 위 테스트 과정은 배포된 상황에서 테스트 수치가 아닌 개발모드에서 테스트된 수치야!
느낀 점
- CSR을 활용할 때 SEO문제점을 해결하려면 SSR 혹은 SSG 방식을 사용하여 초기 완성된 페이지를 전달하여 검색엔진이 정보를 확인할 수 있게 하는 게 좋다고 생각한다.
- SSR이 필요한 프로젝트의 요구사항은 SEO가 중요한 프로젝트에서 SSR이 적합하다고 생각한다.
- SSG와 CSR의 주요 차이점은 SSG는 빌드 시점에 미리 모든 정적 페이지를 만들어 놓고 요청이 들어오면 미리 만들어 놓은 페이지를 전달하는 방식이라면 CSR은 먼저 빈 HTML화면을 파일을 브라우저에 렌더링 후 이후에 자바스크립트 파일을 사용해 DOM을 조작해 화면을 또 렌더링 한다는 과정에서 초기 로딩속도가 느리고 검색엔진에 불리하다는 게 내 생각이다.
내가 공부하고 느낀 점을 적는 블로그 형식이라 틀린 내용이 있을 수 있어.
위 블로그 내용을 보고 내용이 이상하다 싶으면 언제든 피드백은 환영이야!
나는 소통을 좋아하는 사람이니깐 주저 말고 착한? 피드백만 해줘...!
그럼 다음 블로그 때 보자! 안녕👍
'frontend' 카테고리의 다른 글
[Next.js] - 코드잇(단기 심화) 프로젝트 성능 최적화 (0) | 2025.04.18 |
---|---|
[Next.js] 최적화(데이터 패칭) 및 성능 비교 (4) | 2025.01.31 |
[REACT] 재사용성 컴포넌트 (2) | 2025.01.20 |