Yuyeol 님의 상세페이지[8팀 정유열] Chapter 4-1 성능 최적화

과제 체크포인트

배포 링크

기본 https://yuyeol.github.io/front_6th_chapter4-1/vanilla/ 심화 https://yuyeol.github.io/front_6th_chapter4-1/react/

기본과제 (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 (상품 상세 페이지들)
  • 빌드 타임 페이지 생성
  • 파일 시스템 기반 배포

학습 갈무리

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

  • 기존: 동시에 들어온 요청들이 전역 라우터 상태를 같이 건드려 충돌·레이스가 생기는 것을 막기 위해 render lock을 구현
  • 변경: render 함수 내부에서 매 요청마다 새로운 라우터를 생성해 사용하도록 개선하면 전역 상태 공유가 사라져 성능과 확장성 측면에서 더 안전하고 효율적인 구조가 될 것 같습니다.

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

  1. 서버 진입점
  • Express: app.get("/", (req, res) => { … }) 처럼 라우트를 등록
  • Workers/Edge: “fetch 이벤트”를 직접 다룸
  1. Node 전용 기능 부재 처리
  • fs.readFile, path.join 같이 파일 시스템에 접근하는 함수는 Edge 환경에서 사용할 수 없음.
    • 빌드 단계에서 HTML 템플릿을 문자열로 import 하거나
    • KV(Storage)에 파일을 올려서 fetch()로 읽음
  1. 빌드 옵션 변경
  • Vite/webpack 설정에서 “Node 대상” 대신 “webworker” 또는 “edge” 타깃으로 빌드

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

  1. SSG 빌드 시간
  • 병목: React SSG 스크립트가 각 상품을 순차적 await 으로 렌더.
  • 개선: Promise.allSettled로 병렬화.

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

  • Promise.allSettled로 병렬화
  • 모든 상품을 매번 다시 빌드하지 말고, 가격·재고가 변경된 상품만 재생성하도록 해시 비교
  • 모든 페이지를 로컬에서 빌드하면 시간이 오래 걸리므로, 개발 모드에서는 제한된 샘플만 SSG 하도록 처리

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

  1. 첫 입력 지연
  • 이슈: JS 번들이 로드 · 실행되기 전까지 클릭·스크롤이 무시되거나 지연됨.
  • 개선: 번들을 code-splitting으로 작게 나누고, critical JS 만 우선 로딩(Preload)한다.
  1. 대용량 JSON 주입으로 TTI 지연
  • 이슈: window.INITIAL_DATA 파싱 시간이 길어짐.
  • 개선: 데이터 chunking + gzip, 필요한 부분만 CSR fetch.

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

  • Sentry, New Relic 같은 APM 을 붙여 서버 렌더 오류, TTFB, FCP 등을 실시간 수집-알림
  • Accept-Language 에 따라 번역된 HTML 을 SSR 하거나, 빌드 시 로케일별로 별도 SSG 경로를 생성

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

  • 장점
    • 필요한 기능만 도입해 러닝타임/번들 최소화
    • 렌더링/캐시/라우팅을 커스텀할 수 있고, 병목/장애 원인 파악 용이
  • 단점
    • 자유도가 높은 만큼 유지보수를 위한 리소스가 많이 필요함
    • Next.js와 같은 프레임워크에서 제공하는 기능들(ISR, 이미지 최적화, 폰트, Turbo/Router, RSC/Server Actions 등)을 구현하기 위해 학습 및 개발 비용이 소요됨

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

  • Page Router: getStaticProps/getStaticPaths 작성 → output:'export' 설정 → next build && next export → out/ 폴더를 호스팅 → SSG 배포
  • App Router: dynamic = 'force-static' 과 generateStaticParams 가 getStaticProps/Paths 역할을 대신하며, 나머지 배포 흐름은 기존 SSG와 동일합니다.

이번주 과제나 PR에 많은 시간을 할애하지 못하여 과제 완성 + 학습갈무리만 작성하였습니다. 다움주 더 힘내보겠습니다!!

과제 피드백

고생하셨습니다 유열님 기본 과제, 심화 과제 모두 잘 정리해주셨네요. 회고도 가볍게 정리해주신것 같은데, 내용을 좀 더 채워서 구체적이게 적어봐도 큰 도움이 될 것 같습니다! 결국 이 내용을 기반으로 저희가 앱 설계단계에서 선택하는 거니까요 ㅎㅎ

고생하셨고 마지막 주차도 화이팅입니다!