IT 지식 목록
IT 지식

서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)의 조화: 하이브리드 렌더링 아키텍처

정적 사이트 생성과 서버 사이드 렌더링의 차이를 이해하고 서비스의 성격에 맞춰 적절한 렌더링 전략을 선택하는 방법을 학습합니다.

00
서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG)의 조화: 하이브리드 렌더링 아키텍처

현대 웹 개발에서 사용자 경험(UX)과 검색 엔진 최적화(SEO)는 타협할 수 없는 지표입니다. 2026년 현재, 단순히 클라이언트 사이드 렌더링(CSR)에 의존하던 시대는 지나고, 콘텐츠의 성격에 따라 렌더링 전략을 세밀하게 조정하는 하이브리드 접근법이 업계 표준으로 자리 잡았습니다.

렌더링 전략의 진화: 왜 혼합하는가

과거에는 초기 로딩 속도와 SEO를 위해 모든 것을 서버에서 만드는 SSR(Server-Side Rendering)이 주류였습니다. 이후 인터랙티브한 사용자 경험을 위해 브라우저에서 렌더링하는 CSR이 등장했죠. 하지만 CSR은 초기 로딩 시 JS 번들이 커질수록 사용자에게 흰 화면을 오래 보여주는 단점이 있습니다.

이제는 정적 페이지는 빌드 타임에 미리 만들어두는 SSG(Static Site Generation)를, 실시간 데이터가 중요한 페이지는 SSR을, 사용자 행동에 반응하는 부분은 CSR을 결합합니다. 이를 '하이브리드 렌더링'이라 부르며, Next.js나 Remix 같은 프레임워크는 페이지 단위로 이 전략을 선택할 수 있는 강력한 API를 제공합니다.

핵심 원리: 렌더링의 3단계 흐름

렌더링 전략을 이해하기 위해 '요리'에 비유해 보겠습니다.

  • SSG (미리 준비된 도시락): 손님이 주문하기 전에 이미 완성되어 진열장에 있는 상태입니다. 응답 속도가 가장 빠릅니다. (블로그, 마케팅 페이지)
  • SSR (주문 즉시 조리): 손님이 메뉴를 주문하면 주방에서 바로 요리해 서빙합니다. 항상 신선한 데이터를 보여줍니다. (대시보드, 개인화된 프로필)
  • CSR (재료만 제공 후 조리): 식당에 앉으면 재료를 갖다주고, 손님이 직접 요리하게 합니다. 초기 세팅은 빠르지만 사용자가 요리하는(JS 실행) 시간이 필요합니다. (복잡한 인터랙티브 도구)

코드 예제: 프레임워크 수준의 전략 선택

JavaScript의 차세대 프레임워크들을 기준으로, 페이지마다 어떻게 전략을 달리하는지 살펴보겠습니다.

// 예제 1: SSG (getStaticProps) - 데이터 변경이 잦지 않은 페이지
// 빌드 시점에 서버에서 데이터를 가져와 정적 HTML로 생성합니다.
export async function getStaticProps() {
  const data = await fetch('https://api.example.com/posts').then(res => res.json());
  
  return {
    props: { posts: data }, // 이 데이터는 빌드 시 고정됩니다.
    revalidate: 60 // 60초마다 정적 페이지를 다시 생성 (ISR)
  };
}

export default function BlogList({ posts }) {
  return <div>{posts.map(p => <div key={p.id}>{p.title}</div>)}</div>;
}
// 예제 2: SSR (getServerSideProps) - 실시간성이 중요한 페이지
// 매 요청(Request)마다 서버에서 함수를 실행하여 HTML을 생성합니다.
export async function getServerSideProps(context) {
  const user = await fetch(`https://api.example.com/user/${context.params.id}`);
  
  return {
    props: { user: await user.json() }
  };
}

export default function UserProfile({ user }) {
  return <h1>{user.name}의 개인 대시보드</h1>;
}

실무 적용 사례

대규모 이커머스 사이트를 예로 들면, 상품 목록 페이지는 대부분의 사용자에게 동일하므로 SSG를 사용하여 CDN에 캐싱합니다. 반면, 장바구니나 결제 내역 페이지는 사용자별로 데이터가 다르므로 SSR을 사용하여 보안과 최신성을 보장합니다. 상품 상세 페이지 내의 '리뷰 좋아요' 기능은 CSR을 사용하여 페이지 전체를 다시 로드하지 않고 반응성 있게 처리합니다. 이렇게 섞어서 사용하면 서버 부하를 줄이면서도 사용자 경험을 최적화할 수 있습니다.

자주 하는 실수와 해결법

가장 흔한 실수는 "모든 페이지에 SSR을 적용하면 실시간이라서 좋지 않을까?"라고 생각하는 것입니다. 이는 잘못된 접근입니다. SSR은 매 요청마다 서버 자원을 소모하므로, 트래픽이 몰릴 경우 서버 성능 저하로 이어집니다.

  • 실수: 모든 페이지를 SSR로 작성하여 서버 비용이 급증하고 응답 속도가 느려짐.
  • 해결책: 변하지 않는 데이터는 SSG로 돌리고, 60초 정도의 데이터 지연이 허용된다면 ISR(Incremental Static Regeneration)을 사용하세요.
  • 주의점: window나 document 같은 브라우저 전용 객체를 컴포넌트 최상단에서 바로 호출하지 마세요. SSR 과정에서는 Node.js 환경이므로 해당 객체가 존재하지 않아 에러가 발생합니다. useEffect 내부에서만 호출해야 합니다.

더 공부할 리소스 추천

  1. Next.js 공식 문서의 'Rendering' 섹션: 현시점 가장 상세한 가이드를 제공합니다.
  2. Web.dev의 'Rendering on the Web': Google에서 제공하는 렌더링 전략 비교 문서는 교과서와 같습니다.
  3. Hydration의 개념 파악: 서버에서 만든 HTML과 클라이언트의 자바스크립트가 어떻게 연결되는지, React의 Hydration 과정을 다룬 블로그 포스팅들을 탐독해보시길 권장합니다.