[Next.js] 1주차_CSR vs SSR

재선·2026년 3월 11일

Next.js

목록 보기
1/8
post-thumbnail

Next.js 스터디를 시작한다.

왜 Next.js를 시작하는가?

현재 나는 UMC라는 동아리를 통해서 10주간의 웹 스터디를 마치고 약 1달 반 가량의 시간동안 직접 프로젝트 서비스를 제작해보며, 실전 경험을 다졌다.

처음으로 팀프로젝트에 참여했으며, 처음으로 팀과의 협업 및 소통을 거쳐서 프로젝트를 완성하였다. 프로젝트를 직접 처음부터 끝까지 진행하면서 어려움도 많았고, 할 수 있을까 싶었던 순간도 많았다. 첫 프로젝트진행에 첫 팀장으로써 프로젝트를 진행함으로써 많이 힘들었다. 언제까지 이걸 끝내고 언제까지 마무리해야하는지에 대한 고민도 많았고 많이 찾아보기도 했다. 결과적으로 말하면, 성공했다. 프론트엔드 팀원모두 처음이었지만, 다들 열심히 하고 많이 찾아보고 고민해서 만들어냈다. 팀프로젝트를 처음으로 끝마치고 나니 후련함과 동시에 더 할 수 있겠는데? 라는 자신감이 생겼다. 작년 7월 처음으로 React를 접하면서, 내가 과연 이걸 할수 있을까? 라는 의문도 있었고, UMC 동아리 내에서 API연동 스터디를 진행할때도 이게 무슨말이야…라는 말도 많이 했는데, 다 지나고 보니 이제는 더 할수있겠다 라는 생각이 들었다.

서론이 길었다. 결과적으로 팀프로젝트는 성공적으로 마무리지었고, 이제는 Next.js도 배우면서, 개인프로젝트를 직접 혼자서 간단한 백엔드까지 진행해서 혼자서 프로젝트를 하나 완성해보고싶은 생각이 들어서 Next.js를 공부하기 시작한다.

최근에 간단한 회사 공고만 보더라도 프론트엔드 개발자에게 React + Next.js + TypeScript를 요구하는 공고가 많아져서 Next.js에 대한 필요성을 느끼고 있었는데, 이번 10주동안의 스터디 진행으로 Next.js를 학습하고, 이후에 개인프로젝트진행해서 완성해보는 것이 이번 1학기 목표이다!

할수있다. 하면된다.

Next.js가 무엇이냐

Next.js는 React 기반 풀스택 프레임 워크다.

처음에는 React와 Next.js의 관계에서 대해서 헷갈렸는데 쉽게 얘기하면

  • React는 UI를 만드는 라이브러리 이고
  • Next.js는 React를 사용하는 프레임워크 라고 말할 수 있다.

그니까, Next.js 내부에서도 React를 쓴다는 말이다.

Next.js 하나만으로 프론트 + 서버 + 배포 까지 가능하다.

React vs Next.js

구분React (Vite 등)Next.js
라우팅react-router파일 기반 라우팅
렌더링CSRCSR + SSR + SSG
SEO약함강함
API 서버따로 필요내부 API 가능
이미지 최적화직접자동
코드 분할직접자동
배포설정 필요매우 쉬움

Next.js에 대한 중요 개념

Next.js에 대한 기본적인 핵심 개념으로는 5가지가 있다.

  1. 파일 기반 라우팅
  2. SSR (Server Side Rendering)
  3. SSG (Static Site Generation)
  4. API Routes
  5. Server Component

더 배워보면 더 많은 개념이 나오겠지만, 일단 처음 시작하는 입장에서 보면 이 5가지는 무조건 알고가야하는 개념인것같다.

그래서 오늘 1주차에서 공부할 내용은 CSR vs SSR이다.

CSR (Client-Side Rendering)

CSR은 일단 먼저 위에 표에서 볼 수 있듯이, React/Vue 같은 SPA 프레임워크에서 주로 사용하는 랜더링 방식이다.

직역하면 브라우저에서 화면을 랜더링하는 방식이다.

CSR의 기본 원리는 브라우저가 최소한의 HTML을 받고, JS파일을 다운로드한 뒤 브라우저에서 DOM을 업데이트하면서 화면을 완성하는 것이다.

즉, 사용자가 페이지에 들어왔을때는 최소한의 HTML과 JS 파일이 오는거고, 그다음에 브라우저가 React 코드를 실행해서 화면에 나타나는 랜더링 방식이다.

여기서 랜더링이란?
화면에 보이도록 만드는것이다.

실제 브라우저한테 화면에 보이도록 설정하려면, HTML구조,들어가는 데이터, DOM이 만들어져야한다.

이 과정을 CSR에서는 브라우저가 진행하는 것이라고 이해하면 된다.

React에서 CSR

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "@/query/queryClient.ts";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </StrictMode>,
);

main.tsx에 보면 이렇게 구조가 나와있다.

실제 내가 진행했던 UMC 프로젝트 잇츠파인에서 가져온 코드이다.

여기서 보면, 서버가 App의 결과물을 HTML로 바꿔주는게 아닌, 브라우저가 이 JS파일을 실행해서 App을 랜더링 하는것을 알수있다.

즉, 랜더링에 대한 책임이 브라우저에게 있다고 보는게 CSR이라고 말할 수 있다.

CSR의 데이터 flow

Browser
↓
HTML + JS 다운로드
↓
React 실행
↓
API 호출
↓
JSON 데이터 수신
↓
화면 렌더링

CSR의 장점

  1. 페이지 전환이 부드럽다.

    처음에 JS가 한번 로드된 이후에는 필요한 화면만 바꾸면 되니까, 마치 앱처럼 자연스럽게 이동하도록 구현이 가능하다.

    모달 오픈, 드롭 다운, 필터링, 검색, 탭 전환, 상태변화 등 이러한 상호작용이 많을수록 CSR을 사용하는것이 편안하다.

  2. Interactive한 UI에 강하다.

    React 자체가 상태 기반 UI이기때문에, 브라우저에서 state를 가지고 있으면서 바로바로 반응하는것이 CSR과 잘 맞다고 볼 수 있다.

  3. 프론트와 백의 분리가 쉽다.

    보통 프론트가 React, 백엔드가 Sprint/Node, API통신은 Axios/Fetch 구조로 진행되는것이 CSR에서는 자연스럽다. 프론트는 UI담당. 백엔드는 JSON만 주기로 진행되니까, 역할 분담이 명확하다는 장점이 있다.

  4. 한번 로드 된 이후에는 UX가 좋을수 있다.

    초기에 필요한 코드가 다 로딩이 된 이후에는 다음 화면 이동이나 일부 갱신이 빠르게 느껴질 수 있다.

    차트 갱신, 필터 변경, 페이지 이동 등의 작동이 있을때는 사용자에게 좀 더 자연스럽게 진행될수있도록 할 수 있다.

CSR의 단점

  1. 처음에 화면이 느리게 보일 수 있다.

    장점에서 알수 있다싶이, CSR은 한번 로드된 이후에는 UX가 좋을수도 있다. 즉, 그 한번이 느리게 진행될수도 있다는 가능성이 있다는것이다.

    이부분이 아마 CSR의 단점중 가장 큰 부분인것같다.

    처음에 브라우저가 화면 로드할때 가장 많은 일을 진행하는거고, 다 세팅을 해놓는것으로 기초 공사를 튼튼하게 진행하는것이기 때문에, 처음에 다 해놓고, 그 이후에 필요한것만 바꾸는것으로 진행하는 방식인것이다.

    처음에 로드할때 브라우저가 해야할 일들은, HTML 받고, JS 받고/파싱, React 실행, 컴포넌트 랜더링, API 호출, 데이터 받아오고, 다시 랜더링 이기 때문에 오래걸릴 수 있다.

    이 과정을 진행하는중에 사용자에게 보여지는 화면은 스켈레톤화면이나 빈화면일것이다. 그러면 처음 등장하는 사용자 입장에서 보면 “어 여기 페이지 엄청 느린가보네?” 라는 인상이 심어질수있어서 프론트엔드 개발자로써는 최악의 상황중 하나 일수도 있다.

    즉, 초기 로딩속도(FCP)가 길어진다는 얘기이다.

  2. SEO에 불리할 수 있다.

    SEO는 검색 엔진 최적화이다. (Search Engine Optimization)

    구글 같은 검색엔진에서는 웹페이지 내용을 잘 읽어야지 검색 결과에 노출 될 수 있다. 하지만, CSR방식에서 처음에 서버가 보내주는 HTML은 실제 콘텐츠는 거의없다. JS 실행 이후에 브라우저에서 화면이 완성된다고 보면된다.

    이때 문제점은 검색엔진 크롤러가 페이지를 수집할 때 JS를 실행하지 않거나 늦게 실행하는 경우가 있을 수도 있다.

    그러면 검색엔진은 “이 페이지는 내용이 거의 없는 페이지 구나”하고 판단할수도있어서 만약에 검색 유입이 중요한 서비스인 블로그나 마케팅페이지 소개페이지에서는 CSR을 사용하는것이 불리할 수 있다.

    (이러한 문제를 해결하기 위해 등장한게 SSR, SSG 인데 뒤에서 설명하겠다!)

  3. 데이터 로딩 상태를 직접 처리해야한다.

    CSR에서는 데이터가 보통 브라우저에서 API를 호출해서 가져오는 방식으로 동작하기 때문에, 처음에 페이지가 랜더링이 되었을때는 데이터가 없는 상태로 시작하는 경우가 많다. 그렇기에 loading이나 error,success 같은 상태들을 계속 고려해 주어야한다.

    loading중일때는 스켈레톤 UI처리를 해주거나, API가 실패했을때는 에러메세지를 보여주는 등의 UI처리가 필요하다.

    즉, CSR에서는 데이터가 항상 늦게 도착하기 때문에, 상태 관리 로직을 프론트가 계속 고려해줘야한다.

자. 그러면, CSR이 안좋으니까, SSR을 써야할까?

일단 SSR이 무엇인지 부터 알아보자.

SSR (Server-Side Rendering)

SSR은 Server-Side Renging 즉, 서버에서 화면을 랜더링하는 방식이다.

CSR에서는 브라우저가 JS를 실행해서 화면을 완성했다면,
SSR에서는 서버가 먼저 HTML을 완성해서 브라우저에게 전달하는 방식이다.

즉, SSR의 flow를 보자면,

  1. 브라우저 → 서버에게 페이지 요청
  2. 서버가 React 코드 실행해서 HTML 생성
  3. 완성된 HTML을 → 브라우저에게 전달
  4. 브라우저는 받은 HTML을 바로 화면에 보여준다.

그래서, CSR과 SSR의 가장 큰 차이는

  • CSR은 브라우저가 랜더링하는것이고,
  • SSR은 서버가 랜더링하는 것이다.

CSR은 거의 비어있는 HTML을 받는것인데, SSR은 이미 콘텐츠가 들어있는 상태로 전달이 되는것이기 때문에, 브라우저 입장에서는 JS 실행을 기다릴 필요없이 HTML을 받는대로 바로 화면을 보여줄수있다.

이미 다 데이터가 들어있는 HTML을 주니까!

SSR의 데이터 flow

Browser
↓
페이지 요청
↓
서버
↓
API 호출 / DB 조회
↓
React 컴포넌트 랜더링
↓
완성된 HTML 생성
↓
Browser 전달
↓
화면 표시

이렇게 화살표로 보니까 바로 보인다.

CSR은

브라우저 → API 호출 → 화면 랜더링

흐름이라고 하면,

SSR은

서버 → 데이터 가져오기 → HTML 생성 → 브라우저 전달

흐름이라고 보면 된다.

React에서 SSR

React 자체는 기본적으로 CSR 방식으로 많이 사용이 되지만, Next.js 같은 프레임 워크를 사용하면 SSR을 쉽게 구현할수 있을것같다.

예를 들어서, Next.js에서는 서버에서 데이터를 가져와서 페이지를 랜더링 할 수 있다.

페이지 코드가 서버에서 실행되기 때문에, 서버에서 API호출하고, 데이터가져와서 HTML생성해서 브라우저에게 전달하는 흐름으로 이어지니까.

SSR의 장점

  1. 초기 로딩 속도가 빠르다.

    SSR은 서버가 이미 다 완료된 HTML을 만들어서 보내주기 때문에 브라우저 입장에서는 받은 HTML을 바로 화면에 보여줄수가 있는거다.

    원래 CSR에서는

    HTML 다운로드 → JS 다운로드 → React 실행 → API 호출 → 데이터 수신 → 랜더링

    처럼 초기 로딩이 복잡한 과정이 었지만,

    SSR에서는

    HTML 다운로드 → 바로 화면 표시

    이렇게 간단한 과정이다.

    직접 화살표로 나타내보니 정말 간결해졌네!

  2. SEO에 유리하다.

    아까, CSR에서 SEO가 불리한게 단점이라고 했지? 왜그런거였지?

    SEO가 검색 엔진이기때문에, CSR은 처음에 거의 비어있는 HTML을 주기때문에 검색엔진이 비어있거나 정보가 적은 페이지로 인식할수 있기 떄문이라고 했지.

    근데 SSR을 보면, SSR은 이미 HTML에 내용들이 다 포함되어있기 때문에 검색 엔진이 페이지 내용을 훨씬 더 편하게 읽을 수 있는것이다.

    그래서, 아까말한것처럼 검색유입이 중요한 마케팅페이지,블로그, 뉴스, 소개 페이지에서는 SSR이 많이 사용된다는 점을 알수 있는거지!

  3. 초기 로딩 속도(FCP)가 좋다.

    SSR은 초기에 바로 보여지기 때문에 초기 로딩 속도가 좋아서 사용자 입장에서는 사이트에 대한 지체없이 빠르게 파악이 가능하다는 장점이 있다.

    CSR에서는 스켈레톤/빈화면/로딩 화면이 보일 가능성이 있는데, SSR은 페이지 콘텐츠가 바로 나타나는 것이다!! 그래서 처음에 첫인장이 중요한 서비스들은 SSR을 사용하는것이 유리할 수도 있다.

그러면, 무조건 CSR보다 좋으니까 SSR을 써야겠다? 라는 생각이 드나?

아니. 장점이 있으면 단점도 있는법이지.

SSR의 단점

  1. 서버 부하가 증가할 수 있다.

    SSR에서는 사용자가 페이지를 요청할때마다 서버가 React 코드를 실행해서 HTML을 생성하는 구조이다.

    그러니까, 즉, 요청이 많아질수록 서버가 해야할 일들이 많아진다는 뜻이다

    CSR에서는 서버가 HTML + JS 파일 전달만 하면 그다음은 브라우저가 했지만,

    SSR은 서버가 그 과정을 데이터 조회/React랜덜이/HTML 생성이 과정을 매 요청마다 수행해야하기 때문에 많약에 대규모 트래픽 프로젝트라면 서버의 부담이 커지기 때문에 SSR이 적절하지 않을 수 있다.

  2. 페이지 전환 속도가 느릴수있다.

    아까 CSR에서는 한번 JS가 로드된이후에는 필요한 데이터만 갈아끼우니까 페이지 이동할때 빠르다고 했지?

    근데 SSR에서는 페이지를 이동할때마다 브라우저가 서버 요청을 하면 서버랜더링/HTML 응답 이 과정을 계속 반복하게 되기 때문에 페이지 이동 부분에서는 CSR보다 느리게 느껴질 수 있다.

  3. CSR보다 구현이 복잡하다.

    CSR은 보다시피 대부분이 브라우저에서만 동작을 하기 때문에 구현하는 구조가 단순하다고 느껴진다.

    하지만, SSR은 서버환경과 브라우저 환경 둘다 고려해야하기 때문에 기존의 CSR에서 사용하던 window/localStorage/document같은 브라우저 전용 객체를 서버에서 사용할 수 가 없다.

    그러면, 코드 작성할때 서버에서 실행되는 코드인지, 브라우저에서 실행되는 코드인지 구분해서 작성해야한다는 주의점이 발생하게 된다!!

여기서 드는 생각! 과연 SSR은 무조건 CSR보다 빠른걸까?

흠 일단 성능적인 지표를 먼저 살펴보면 짚고 넘어가야하는 개념이 있다.

  1. FCP (First Contentful Paint): 사용자가 화면에서 처음으로 콘텐츠를 보는 시점. 즉, 초기 로딩속도를 뜻한다.
  2. TTI (Time to Interactive): 사용자가 버튼을 클릭하거나 입력하는 등의 상호작용이 가능해 지는 시점

두가지 개념을 쉽게 말해서 ,

  • FCP는 눈으로 보는 시점을 말하는거고,
  • TTI는 사용자가 손으로 행동할수있는 시점을 말하는거다.

여기서 SSR은 서버가 이미지 완성된 HTML을 보내주니까, FCP가 빠르겠지? 사용자가 사이트에 접속하자마자 빠르다!!라고 느낄수가 있는것이다. 근데 자세히 보면 화면에 보여지는것만 빠르지 버튼을 눌렀을때의 반응은 느릴수도 있다. 왜냐하면 서버랜더링/HTML응답 과정이 계속 반복되기 때문에 위에서 말한것처럼 전환 속도가 느리다는 단점이 여기서 발생한다!

그러면 CSR은 반응속도가 빠르겠네? 라고 말하면 정답이다. CSR은 처음에 거의없는 HTML때문에 FCP만 느리지 일단 화면에 떴다? 하면 TTI는 빠르다. 그다음 FCP와 TTI 사이에 차이는 거의 없다고 보면된다.

결국 정리하면, SSR은 빠르게 보여지는게 중요하다는 장점이 있는반면에, 서비스를 제대로 이용하는과정에서의 시간은 더 길어질수도 있다는 트레이드 오프(Trade-off)가 존재한다.

여기서 SSR은 또 서버부하 문제도 고민을 해야하는 상황도 있다. 마냥 SSR이 더 좋다. 라고 말을 할수가 없는것이다!

하이드레이션(Hydration)

그러면 여기서 또 질문이 나오지. SSR로 받는 HTML은 어떻게 클릭이 진행되는것이지? 라고 질문을 해야지.

이 과정을 하이드레이션이라고 부른다.

이 단어를 직역하면 수분 공급이라고 하는데. 비유를 하자면

  1. 서버가 보내준 HTML은 건조한 상태이기 때문에, 형태는 완벽한데 움직일수는 없는 상태이다.
  2. 여기서 브라우저가 JS파일을 받아서 이 HTML 위에 올려주는 과정이 물을 주는과정이라고 보면 된다.
  3. 그러면 물을 받았으니까 움직일수있지? 그러면 그때부터 HTML은 우리가 흔히 아는 React 컴포넌트처럼 숨쉬고 상호작용을 할수있다. 클릭이나 입력같은거.

이러한 과정을 하이드레이션이라고 한다!

이과정이 단순히 좋다.라고 할게 아니라, 여기서도 주의해야할 점이 있다!

서버가 만든 HTML의 구조가 JS를 실행해서 만든 구조랑 다를때,

즉, 서버가 만든 구조 !== JS를 실행해서 만든 구조 일때. 위에 틀을 올려줘야하는데 구조가 안맞는 상황이 생기는거지! 그럴때는 이제 에러가 발생하고, 화면이 번쩍이거나 깨질수도있다!

이러한 과정을 하이드레이션 미스매치(Hydration Mismatch)라고 한다. 하이드레이션이 매치되지 않았다는 의미이다.

그러면, 인제 CSR과 SSR의 장단점을 알았는데, CSR을 썼을때는 이러한 단점들이 나오고, SSR을 사용했을때는 이러한 단점들이 나와서 선택하기 어렵다고 느낄 수 있다.

어떤걸 쓰라는건지 모르겠다. 두가지의 장점만 뽑아서 쓰면 좋겠다라고 생각할거다. (맞지?)

이러한 똑같은 생각을 하는 개발자들을 위해서 나온게 Next.js의 App Router와 React Server Components(RSC)다.

App Router, React Server Components(RSC)

이전에는 페이지 전체를 SSR로 할지. CSR로 할지 두가지 중에 하나로 크게 나눠서 생각해야했다면, 이제는 컴포넌트 단위로 결정할수 있다.

이게 왜 좋냐?

사실 웹페이지를 떠올려보면 모든 부분들이 다 브라우저에서 동작할 필요가 없다.

뭐, 서버에서 가져오는 리스트 데이터, 유저 프로필 정보, 게시글 내용, 상품 정보 같은건 브라우저에서 JS를 무겁게 돌려가면서 처리해야될 필요가 없잖아? 그냥 서버에서 미리 가져온다음에 HTML처럼 넘겨줘도 되는 부분들이다.

근데 이제 또 사용자와 상호작용하는 부분들있잖아. 뭐 좋아요 토글이나, 알람 토글, 모달오픈, 버튼 클릭 같은건 브라우저에서 돌아가야지.

그래서 여기서 생각해보면, 데이터 보여주는 부분이랑, 상호작용 필요한 부분이랑 두가지로 나눠서 생각해도 되지않나? 라는 생각이 드는것이다!!

그래서

  1. Server Components (기본값)

    이거는 서버에서만 실행되는 컴포넌트이다.

    브라우저까지 JS번들 보낼 필요가 없어서 그만큼 클라이언트가 받는 JS양이 줄어들고 성능적인 부분에서도 유리하다고 볼수있는거지. 그리고 가장 큰 장점으로는 서버가 바로 데이터에 접근이 가능하다는 점!!

    즉, 서버에서 API 호출하고 DB 조회하고 인증 정보 확인하는 작업들을 컴포넌트안에서 자연스럽게 처리할 수 있다.

    예전에 비하면 useEffect → fetch → loading → setstate 이 흐름을 갈 필요가 없는거다.

    그래서 데이터 보여주는 용도의 컴포넌트는 굳이 CSR처럼 브라우저에서 늦게 가져오지 않고 서버에서 미리 준비해서 보내주는게 더 효율적일 수 도 있다.

  2. Client Components (”use client”)

    이거는 이제 브라우저에서 실행되는 컴포넌트인것이다. 말그대로 클릭이나 useState, useEffect, 브라우저 API사용등이 필요할때 사용하는 컴포넌트인거지.

    그니까, 사용자와 상호작용이 필요한 부분만 따로 client 컴포넌트에 두는것이다.

    그래서 페이지 전체를 전부 클라이언트로만드는게 아니라,

    페이지 큰 틀이나 데이터 랜더링은 → Server Component
    버튼/모달/필터 UI는 → Client Component

    이렇게 나눌수가 있는것이다.

그래서 결과적으로는 필요한 부분만 브라우저로 보내고, 나머지는 서버에서 처리할수있다는 장점만 남은거다!

여기서 App Router가 왜 중요하냐? 라고 물어보면, App Router가 이런 Server Components / Client 구조를 자연스럽게 사용할 수 있게 해주는게 Next.js의 방식이기 때문이다

예전에 비해 페이지 단위로 설계한거에 비하면 컴포넌트 단위로 더 유연하게 설계할수있는 장점이 있는거다!!

그래서 이제는 “이 페이지 전체를 CSR로 할까? SSR로 할까?”라고 고민하는게 아니라,

“이 컴포넌트는 서버에서 처리하고, 이 버튼은 클라이언트로 빼자”라고 조금더 촘촘하게 설계가 가능하다는 것이다.

정리하면,

이전에는 CSR이냐, SSR이냐를 페이지 단위로 크게 선택하는 느낌이었다면,

App Router + RSC에서는 한페이지 안에서도 더 세밀하게 역할을 필요에 따라 나눠서 처리할수있다는것이다.

즉,

서버에서 하면 좋은건 서버에게 맡기고,
브라우저가 해야할 일들만 클라이언트에게 맡기는 구조

가 가능한것이다. 장점만 쏙쏙!

이게 이제 Next.js App Router의 핵심이다.

여기서 중요한건 모든것을 Server Components로 만들거나 Client Components로 만드는게 정답은 아닌것이다!

어떤 부분이 브라우저에서 상호작용이 필요한지. 어떤 부분을 서버에서 미리 처리하는게 더 효율적인지 미리 설계를 단단하게 하는게 중요하다는것이다!

Next.js를 잘 활용하는 쟁점은 서버와 클라이언트의 역할을 얼마나 적절하게 나누는가에 달려있는것같다.

profile
Just do IT

0개의 댓글