suhyeon57 님의 상세페이지[6팀 김수현] Chapter 4-1 성능 최적화

과제 체크포인트

배포 링크

https://suhyeon57.github.io/front_6th_chapter4-1/react/ https://suhyeon57.github.io/front_6th_chapter4-1/vanilla/

기본과제 (Vanilla SSR & SSG)

Express SSR 서버

  • Express 미들웨어 기반 서버 구현
  • 개발/프로덕션 환경 분기 처리
  • HTML 템플릿 치환 (<!--app-html-->, <!--app-head-->)

서버 사이드 렌더링

  • 서버에서 동작하는 Router 구현
  • 서버 데이터 프리페칭 (상품 목록, 상품 상세)
  • 서버 상태관리 초기화

클라이언트 Hydration

  • window.__INITIAL_DATA__ 스크립트 주입
  • 클라이언트 상태 복원
  • 서버-클라이언트 데이터 일치

Static Site Generation

  • 동적 라우트 SSG (상품 상세 페이지들)
  • 빌드 타임 페이지 생성
  • 파일 시스템 기반 배포

심화과제 (React SSR & SSG)

React SSR

  • renderToString 서버 렌더링
  • TypeScript SSR 모듈 빌드
  • Universal React Router (서버/클라이언트 분기)
  • React 상태관리 서버 초기화

React Hydration

  • Hydration 불일치 방지
  • 클라이언트 상태 복원

Static Site Generation

  • 동적 라우트 SSG (상품 상세 페이지들)
  • 빌드 타임 페이지 생성
  • 파일 시스템 기반 배포

구현 과정 돌아보기

가장 어려웠던 부분과 해결 과정

  1. 하이드레이션 불일치 문제 문제 : 서버와 클라이언트에서 렌더링되는 HTML이 달라 깜빡임 현상 발생 -->제가 생각한 SSR은 랜더링이 보이지 않아 사용자가 빠르게 화면을 볼 수 있다는 점이 큰 장점이라고 생각했습니다. 하지만 SSR 구현 시 확인 결과 랜더링이 보이는 문제점을 발견하였습니다.

해결 :

onMount: () => {
      if (typeof window === "undefined") {
        return;
      }
      if (window.__INITIAL_DATA__?.products?.length > 0) {
        const [products, categories, totalCount] = [
          window.__INITIAL_DATA__.products,
          window.__INITIAL_DATA__.categories,
          window.__INITIAL_DATA__.totalCount,
        ];
        productStore.dispatch({
          type: PRODUCT_ACTIONS.SETUP,
          payload: {
            products,
            categories,
            totalCount,
            loading: false,
            status: "done",
          },
        });
        return;
      }
      loadProductsAndCategories();
    },

이렇게 onMount를 처리하면서 랜더링이 보이지 않도록 구현했습니다.

첫 화면을 서버에서 미리 렌더링해서 보내주기 때문에, 사용자가 페이지를 열었을 때 로딩된 느낌이 더 빠른 느낌 이 코드를 진행하면서 SSR에 대한 효능을 정확하게 알게되었습니다.

구현하면서 새롭게 알게 된 개념

이번 프로젝트는 **Server-Side Rendering(SSR)**을 직접 구현하며 모던 웹 개발의 핵심 개념들을 깊이 있게 학습하는 과정이었습니다. React와 Vanilla JavaScript 두 가지 환경에서 SSR을 구현하고, 나아가 Static Site Generation(SSG)까지 다뤄보는 종합적인 경험이었습니다.

  1. SSR vs CSR vs SSG 비교
방식렌더링 시점장점단점
CSR브라우저 실시간상호작용 빠름초기 로딩 느림, SEO 불리
SSR서버 요청시마다SEO 좋음, 초기 로딩 빠름서버 부하, 복잡성
SSG빌드 시점매우 빠름, SEO 최고동적 콘텐츠 제한
  1. 하이드레이션의 중요성
  • 서버 렌더링 HTML과 클라이언트 렌더링 결과가 일치해야 함
  • 초기 데이터 동기화가 핵심
  • 사용자 경험을 해치지 않는 부드러운 전환

성능 최적화 관점에서의 인사이트

학습 갈무리

Q1. 현재 구현한 SSR/SSG 아키텍처에서 확장성을 고려할 때 어떤 부분을 개선하시겠습니까?

const getBaseUrl = () => {
  if (typeof window !== "undefined") {
    return ""; 
  }
  return prod ? "http://localhost:4174" : "http://localhost:5174";
};

이렇게 처리된 API 계층을 개선할 필요가 있다고 생각합니다.

Q2. Express 서버 대신 다른 런타임(Cloudflare Workers, Vercel Edge Functions 등)을 사용한다면 어떤 점을 수정해야 할까요?

Q3. 현재 구현에서 성능 병목이 될 수 있는 지점은 어디이고, 어떻게 개선하시겠습니까?

Q4. 1000개 이상의 상품 페이지를 SSG로 생성할 때 고려해야 할 사항은 무엇입니까?

Q5. Hydration 과정에서 사용자가 느낄 수 있는 UX 이슈는 무엇이고, 어떻게 개선할 수 있을까요?

초기 인터랙션 지연되어 클릭이나 입력이 되지 않을 수 있습니다. 부분적 Hydration / Progressive Hydration 전체 페이지를 한 번에 hydrate하지 않고, 중요한 영역부터 우선적으로 JS 바인딩하는 방법이 있다고 합니다.

Q6. 이번 과제에서 학습한 내용을 실제 프로덕션 환경에 적용할 때 추가로 고려해야 할 사항은?

Q7. Next.js 같은 프레임워크 대신 직접 구현한 SSR/SSG의 장단점은 무엇인가요?

Q8. Next.js 를 이용하여 SSG 방식으로 배포하려면 어떻게 해야 좋을까요?

코드 품질 향상

자랑하고 싶은 구현

자랑하고 싶은 코드는 없어요 .. ㅠㅠ

개선하고 싶은 부분

리팩토링 계획

프로젝트를 진행하면서 동일한 구조의 스토어 디스패치 코드가 반복되는 문제를 발견했습니다. 성공과 실패 상태 처리에서 거의 동일한 코드가 계속 반복되고 있었습니다.

 productStore.dispatch({
          type: PRODUCT_ACTIONS.SETUP,
          payload: {
            products: [],
            totalCount: 0,
            categories: {},
            currentProduct: product,
            relatedProducts: relatedProducts,
            loading: false,
            error: null,
            status: "done",
          },

이 코드를 함수로 만들며 리팩토링을 진행하고 싶습니다.

학습 연계

다음 학습 목표

이번 과제를 통해 SSR을 직접 다뤄보면서, Next.js를 사용했을 때 어떤 점에서 더 편리할지 감을 잡을 수 있었습니다. 앞으로는 Next.js를 활용해 SSR을 실습해보고, CSR/SSR/SSG 각각의 렌더링 방식이 어떤 상황에서 적합한지 비교·정리할 계획입니다. 또한 실제 프로젝트에서 SEO와 초기 로딩 속도를 개선하기 위해 SSR을 어떻게 적용할 수 있을지 고민해보려 합니다.

실무 적용 계획

현재 실무에서는 실시간 데이터를 보여주는 대시보드를 개발하고 있기 때문에, SSR 사용은 어려울 것 같습니다.. ㅎ

리뷰 받고 싶은 내용

아직 SSR과 SSG에 대한 이해가 부족합니다.

과제 피드백

수고했습니다. 이번 과제는 SSR과 SSG를 직접 구현해보면서 렌더링 전략의 차이점과 성능 최적화 방법을 체험하는데 목적이 있었습니다.

하이드레이션 불일치 문제를 직접 마주치고 해결하신 과정이 좋았어요. "SSR은 렌더링이 보이지 않아야 한다"고 생각했는데 실제로는 깜빡임 현상이 발생했었군요. "첫 화면을 서버에서 미리 렌더링해서 보내주기 때문에, 사용자가 페이지를 열었을 때 로딩된 느낌이 더 빠른 느낌 이 코드를 진행하면서 SSR에 대한 효능을 정확하게 알게되었습니다." 직접 구현을 통해서 SSR의 동작원리를 정확히 이해하게 된 계기가 된 것 같아서 좋네요.

"이번 과제를 통해 SSR을 직접 다뤄보면서, Next.js를 사용했을 때 어떤 점에서 더 편리할지 감을 잡을 수 있었습니다. 앞으로는 Next.js를 활용해 SSR을 실습해보고, CSR/SSR/SSG 각각의 렌더링 방식이 어떤 상황에서 적합한지 비교·정리할 계획입니다." 아주 좋습니다! 지금의 학습 방법처럼 단순히 이런게 있구나를 넘어서 이게 어떻게 동작하는건지를 이해하고 등장하게 된 배경을 이해하면서 보다 더 깊이 있는 학습을 할 수 있을거에요!

다음 과제도 화이팅입니다!