2차 공부/TIL

24.07.30 SSR , CSR의 차이 / hydration

공대탈출 2024. 7. 30. 17:20

SSR : Server Side Rendering

CSR : Client Side Rendering

말 그대로 SSR은 서버측에서 렌더링을 하는 것이고, CSR은 클라이언트(사용자)측에서 렌더링을 하는 것이다.

 

CSR / SSR

  CSR : Client Side Rendering SSR : Server Side Rendering
1 사용자가 웹 사이트를 요청함 유저가 웹 사이트를 요청함
2 CDN이 HTML파일과 JS접근링크를 보내줌 서버가 렌더가 준비된 HTML파일을 생성함
3 브라우저가 HTML을 다운로드하고, JS를 다운로드함
단, 이때 사용자는 사이트를 볼 수 없음(빈 화면)
브라우저가 HTML을 빠르게 렌더링하지만
사이트는 아직 상호작용이 불가함
4 브라우저가 JS를 다운로드함 브라우저가 JS를 다운로드함
5 JS가 실행되고 data를 위한 api요청들이 시작됨
이때 유저들은 placeholders를 볼 수 있음
이제 유저가 컨텐츠들을 볼 수 있으며
상호작용이 "기록"
6 서버가 요청된 api에 대해 데이터를 보내줌 브라우저가 JS프레임워크를 실행함
7 데이터가 placeholders의 자리에 채워지고
이제 페이지가 상호작용이 가능해짐
기록된 상호작용들이 실행되고
이제 페이지가 상호작용이 가능해짐 

 

결론은 렌더링의 부담을 누가 질 것이냐는 것이다.

서버에서 렌더링을 해서 유저에게 준다면, 유저는 빠르게 사이트에 접근이 가능해지는 것이고, 유저측에서 렌더링을 하게 된다면 사이트 접근은 느리지만, 서버에 부하가 줄어드는 것이다.

 

CSR VS SSR

  1. 페이지 로딩 시간
    • 처음 페이지 로딩시간
      CSR의 경우, HTML과 CSS, JS를 한번에 불러온다. 반면 SSR은 필요한 부분의 HTML과 스크립트만 불러온다.
      ==> SSR이 처음 페이지 로딩시간이 더 빠르다.
    • 나머지 로딩시간
      첫 페이지를 로딩한 후, 사이트의 다른 곳으로 이동하는 동작을 진행할 때 CSR은 이미 처음 로딩때 나머지 부분의 코드도 받아왔기 때문에 이동이 빠르지만, SSR은 필요한 부분의 코드만 받아왔기 때문에 처음 로딩과정을 다시 실행한다.
      ==> CSR이 나머지 로딩시간이 더 빠르다.

  2. 검색엔진 최적화(SEO)
    크롤러가 웹 사이트를 읽을 때 CSR은 자바스크립트를 실행시켜 동적으로 컨텐츠가 생성되기 때문에 실행되어야 metadata가 바뀌었다. 하지만 SSR은 애초에 서버 사이드에서 컴파일 되어 클라이언트로 넘어오기 때문에 크롤러에 대응하기 편리하다.

  3. 서버 자원 사용
    SSR이 더 많이 사용한다. 매번 서버에 컴파일 요청을 하기 때문이다. CSR은 클라이언트에서 처리를 하므로 서버에 부하가 상대적으로 적다.

 

NextJs로 생성한 프로젝트
CRA로 생성한 프로젝트

 


Hydration

대부분의 페이지에서 hydration을 뼈대만 있는 HTML에 수분을 공급하는 것이라고 말한다. 그리고 그것이 정답이라고 느껴졌다.

기본적인 csr의 리액트에서는 개발자가 느끼지 못했겠지만 뼈대 HTML에 hydration을 하는 즉, js를 입히는 작업이 완료된 뒤 페이지가 로드된다.

하지만 ssr은 hydration이 이뤄지기 전에 사용자에게 미리 뼈대 HTML을 보여준다.

 

개발자 도구에서 자바스크립트 사용중지를 설정하고, 새로고침을 해도 뼈대가 출력되는 것을 볼 수 있다.

하지만 hydration이 진행되지 않은 상태이기 때문에 상호작용은 불가하다.

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";

export default function Navigation() {
    const path = usePathname();
    const [count, setCount] = useState(0);
    console.log(path);
    return (
        <nav>
            <ul>
                <li>
                    <Link href="/">Home</Link> {path === "/" ? "🔥" : ""}
                </li>
                <li>
                    <Link href="/about-us">About-us</Link> {path === "/about-us" ? "🔥" : ""}
                </li>
                <li onClick={() => setCount(count + 1)}>
                    <button>{count}</button>
                </li>
            </ul>
        </nav>
    );
}

useState로 생성한 count값을 올려주는 버튼을 마구마구 클릭하더라도 onClick함수가 작동하지 않는다.

그 이유는 아까 말했듯이 hydration이 일어나지 않았기 때문이다.

또한 Link 태그도 hydration작업을 통해 a태그처럼 새로고침이 되지 않도록 작업이 이뤄져야하는데, 해당 작업이 일어나지 않아 a태그처럼 새로고침 후 페이지 이동이 된다.

 

추가적으로 useState도 react에서 가져와서 사용한 훅인데, count 초기값인 0은 어떻게 보여주는거야?

이것은 nextjs가 production버전에 빌드를 진행하면 snapshot을 찍어놓는다.

그때 미리 저장되어있던 초기값이 사용자에게 보여지는 것이다.

자바스크립트 사용중지를 풀면 hydration이 일어나 상호작용이 정상적으로 작동하게 된다.