프론트엔드/Next.js

(Next.js) 주요 특징 SSR vs SSG

그린티_ 2025. 5. 12. 23:42
반응형

서론

React로 프로젝트를 하다가 Next.js를 알게 됨 "React랑 뭐가 다르지?" 싶었는데, Next.js는 프레임워크라고 함 찾아보니 SSR, SSG, ISR 같은 렌더링 방식이 있더라 특히 SSR과 SSG가 뭐가 다른지 헷갈렸음 그래서 Next.js가 뭐고, SSR과 SSG의 차이를 정리해봄

본론

Next.js가 뭐야?

Next.js는 React 기반의 풀스택 프레임워크 클라이언트 사이드만 하던 React에서 한 걸음 나아가서 서버 사이드도 처리할 수 있게 해줌

React vs Next.js

React는 클라이언트에서 모든 렌더링을 함

브라우저 → 빈 HTML 받음 → JavaScript 실행 → 화면 렌더링

Next.js는 서버에서도 렌더링할 수 있음

브라우저 → 완성된 HTML 받음 → JavaScript 실행 → 상호작용

렌더링 방식 이해하기

웹 페이지를 렌더링하는 방식은 크게 3가지

1. Client Side Rendering (CSR) - React 기본

유저가 접속 → 빈 HTML 다운로드
           → JavaScript 다운로드 및 실행
           → 브라우저에서 렌더링

장점: 개발이 간단, 상호작용이 빠름 단점: 초기 로딩이 느림, SEO가 안 좋음

2. Server Side Rendering (SSR) - Next.js 지원

유저가 접속 → 서버에서 렌더링
           → 완성된 HTML 전송
           → 브라우저에서 표시 (JavaScript 실행)

장점: 초기 로딩이 빠름, SEO가 좋음 단점: 서버 부하 증가, 동적 콘텐츠마다 렌더링 필요

3. Static Site Generation (SSG) - Next.js 지원

빌드 시점 → 서버에서 미리 렌더링
         → 정적 HTML 파일로 저장
         
유저가 접속 → 이미 만들어진 HTML 전송 (매우 빠름)

장점: 가장 빠름, SEO 좋음, 서버 부하 없음 단점: 미리 빌드해야 함, 동적 콘텐츠에 부적합

SSR (Server Side Rendering) 자세히 보기

SSR은 요청이 올 때마다 서버에서 렌더링해서 완성된 HTML을 보냄

SSR 예시

// pages/products/[id].js
export default function Product({ product }) {
  return (

{product.name}

가격: {product.price}원

설명: {product.description}

  );
}

// 서버에서 실행됨
export async function getServerSideProps(context) {
  const { id } = context.params;
  
  // 서버에서 데이터 조회
  const response = await fetch(`https://api.example.com/products/${id}`);
  const product = await response.json();
  
  return {
    props: {
      product
    },
    revalidate: 60 // 60초마다 재검증 (ISR)
  };
}

SSR의 흐름:

  1. 유저가 /products/1 접속
  2. Next.js 서버가 getServerSideProps() 실행
  3. 데이터베이스에서 상품 정보 조회
  4. 완성된 HTML 생성
  5. 브라우저에 HTML 전송
  6. 브라우저가 화면 표시

SSR 사용 시점:

  • 자주 변하는 데이터 (실시간 재고, 주가 등)
  • 유저별로 다른 콘텐츠 (마이페이지, 개인화 추천)
  • SEO가 중요한데 동적 콘텐츠가 많을 때

SSR의 문제점:

// 매 요청마다 이 함수가 실행됨
export async function getServerSideProps() {
  const data = await fetch('...'); // 매번 API 호출
  return { props: { data } };
}

1000명이 동시에 접속하면 1000번 API 호출 → 서버 부하 증가

SSG (Static Site Generation) 자세히 보기

SSG는 빌드 타임에 미리 렌더링해서 정적 HTML 파일로 저장

SSG 예시

// pages/blog/[slug].js
export default function BlogPost({ post }) {
  return (

{post.title}

{post.date}

{post.content}
  );
}

// 빌드 시점에 실행됨
export async function getStaticProps(context) {
  const { slug } = context.params;
  
  // 빌드 타임에 데이터 조회
  const response = await fetch(`https://api.example.com/posts/${slug}`);
  const post = await response.json();
  
  return {
    props: {
      post
    },
    revalidate: 3600 // 1시간마다 재생성 (ISR)
  };
}

// 어떤 경로를 미리 생성할지 정의
export async function getStaticPaths() {
  const response = await fetch('https://api.example.com/posts');
  const posts = await response.json();
  
  const paths = posts.map(post => ({
    params: { slug: post.slug }
  }));
  
  return {
    paths,
    fallback: 'blocking' // 없는 경로는 요청시 생성
  };
}

SSG의 흐름:

  1. npm run build 실행
  2. Next.js가 getStaticProps() 실행
  3. 데이터 조회해서 HTML 파일 생성 (blog/post1.html, blog/post2.html 등)
  4. 정적 HTML 파일을 서버에 배포
  5. 유저가 접속하면 이미 만들어진 HTML 전송 (매우 빠름)

SSG 사용 시점:

  • 자주 바뀌지 않는 콘텐츠 (블로그 글, 상품 카탈로그)
  • SEO가 중요한 콘텐츠
  • 빠른 로딩 속도가 중요할 때
  • 서버 부하를 줄이고 싶을 때

SSG의 장점:

// 빌드 시점에만 API 호출
// 1000명이 접속해도 API 호출 0번 → 서버 부하 없음
// CDN에 캐시되면 전 세계에서 매우 빠르게 제공

ISR (Incremental Static Regeneration)

SSR과 SSG의 장점을 합친 방식

export async function getStaticProps() {
  const data = await fetch('...');
  
  return {
    props: { data },
    revalidate: 60 // 60초마다 백그라운드에서 재생성
  };
}

처음에는 정적 HTML 제공 (빠름) 60초마다 백그라운드에서 새로 렌더링 업데이트된 콘텐츠는 다음 요청부터 제공

SSR vs SSG 비교

항목 SSR SSG

렌더링 시점 요청 시점 빌드 시점
속도 보통 (API 호출 필요) 매우 빠름
SEO 좋음 좋음
서버 부하 높음 없음
데이터 신선도 항상 최신 재빌드까지 구식
사용 사례 실시간 데이터 정적 콘텐츠
예시 SNS 피드, 마이페이지 블로그, 문서

실제로 어떻게 선택할까?

SSG 써야 할 때:

// 블로그 글, 문서, FAQ
// 자주 바뀌지 않는 상품 정보
// 변경 빈도: 하루 수 번 정도
export async function getStaticProps() {
  const posts = await getAllBlogPosts();
  return {
    props: { posts },
    revalidate: 3600 // 1시간마다 재생성
  };
}

SSR 써야 할 때:

// 실시간 주가, 주문 상태
// 유저별 개인화 콘텐츠
// 변경 빈도: 실시간
export async function getServerSideProps(context) {
  const userId = context.req.user.id;
  const userData = await getUserData(userId);
  return { props: { userData } };
}

둘 다 섞어야 할 때:

// 상품 목록: SSG (자주 안 바뀜)
// 재고 정보: SSR (자주 바뀜)
// 사용자 리뷰: SSR (실시간)

결론

Next.js는 React로 만든 웹앱을 한 단계 업그레이드할 수 있게 해줌

SSR은 매번 서버에서 렌더링 → 항상 최신 데이터, 하지만 느릴 수 있음 SSG는 빌드할 때 미리 렌더링 → 매우 빠르지만, 미리 빌드해야 함 ISR은 둘의 장점을 합쳐서 → 빠르면서도 주기적으로 업데이트

처음엔 어떤 방식을 써야 할지 헷갈리지만, 데이터의 변경 빈도를 기준으로 생각하면 쉬움 자주 안 바뀌면 SSG, 자주 바뀌면 SSR!

앞으로 Next.js로 프로젝트 할 때 이 3가지 방식을 상황에 맞게 잘 섞어서 써봐야겠음! 

반응형