Skip to content

[5주차] Team Hi-Five 권오진 & 박유민 과제 제출합니다.#5

Closed
waldls wants to merge 104 commits intoCEOS-Developers:masterfrom
Hi-Five-Official:master
Closed

[5주차] Team Hi-Five 권오진 & 박유민 과제 제출합니다.#5
waldls wants to merge 104 commits intoCEOS-Developers:masterfrom
Hi-Five-Official:master

Conversation

@waldls
Copy link
Copy Markdown

@waldls waldls commented May 2, 2026

과제 관련 링크

우선 개발 편의를 위해 배경을 회색으로 세팅해두었습니다. 최종 6주차 과제 제출 시에는 검은 색으로 바꿔서 제출하겠습니다!


Research Questions

느낀 점 및 배운 점

오진

협업

  • 협업이 처음이라 경험이 많은 유민님 주도 하에 기술 스택 및 컨벤션을 지정하게 되었습니다. 특히 프레임워크와 패키지 매니저는 처음 사용하는 Next.jspnpm으로 진행하게 되어 또 다른 지식과 협업 방식 경험을 얻을 수 있었습니다.
  • 또한 컨벤션을 지정하며 기존 혼자 과제 제출 시에는 Commit convention만 유의하여 작성하였다면 현재는 폴더 구조 및 브랜치 등 지정한 컨벤션에 모두 신경써서 작성한다는 점이 어려웠습니다. 특히 협업 초기에는 Issue 생성 및 Issue 번호를 사용하여 커밋하는 부분들이 어려웠지만, 그 과정에서 다양한 깃허브 기능에 대해 알아갈 수 있었습니다.
  • 본격적인 팀 프로젝트 이전 협업 과제를 하며 다양한 경험 및 지식을 얻을 수 있도록 여러 의견과 역할 부여를 해주신 유민님께 감사를 드립니다.

Next.js

  • Next.js를 사용하며 가장 편리했던 점은 파일 기반 라우팅을 통해 파일 시스템 구조가 곧 웹사이트의 주소가 된다는 점에서 코드 작성 중 유용하였으며, 개발 편의성을 위해 타입스크립트 지원과 자동 새로고침 등 여러 기능이 개발 중 유용하게 사용되었습니다.
  • Next.js를 사용하여 코드를 작성할 때, “use client”를 필요한 부분에만 사용하도록 고려하며 작성하였습니다. 모든 파일이 아니라 경계가 되는 파일에만 사용하며 또한 부모 파일에서 이미 사용하였다면 import한 자식 컴포넌트는 붙이지 않아도 동작한다는 점에 유의하였습니다.

API

  • 데이터 fetch 위치에 대해 고민하였습니다. 처음에는 page.tsx에 여러 API를 한 번에 호출하여 각 섹션에 데이터를 전달하는 구조로 구현했습니다. 팀 내 코드 리뷰를 통해 각 섹션 서버 컴포넌트가 데이터를 직접 가져오게 하며 page.tsx는 레이아웃만 잡는 방식으로 수정하였습니다.

기타

  • 랜딩페이지 구현 중, Lottie 애니메이션과 MP3 파일이 동시에 시작되도록 구현하려고 했습니다. 페이지에 들어가면 애니메이션만 작동되었습니다. 브라우저에서는 사용자 상호작용 없이 오디오 자동재생을 제한하고 있다는 점을 알게 되었습니다. 이 과정을 통해 기능 구현과 더불어 웹 환경 자체에 대한 이해가 필요하다고 느꼈습니다.

유민

협업

  • 기술적인 구현만큼이나 중요하게 생각한 것은 함께 일하기 좋은 환경을 만드는 것이었습니다. 짧은 기간 내에 파트너인 오진님이 편하게 개발하실 수 있도록 상세한 노션 문서화와 가이드 작성에 많은 공을 들인 것 같습니다. 첫 프로젝트라 낯선 부분도 많으셨을텐데 제가 제안하는 다양한 방식들에 귀 기울여 주시고 의견 많이 공유해준 오진 오빠에게 다시 한 번 고맙습니다 👍🏻
  • 초기 세팅의 미흡함이 추후 개발 생산성을 저해하는 리소스 낭비로 이어진다는 점을 잘 알고 있기에, 프로젝트 시작 전 환경 설정을 매우 세밀하게 검토했습니다. 덕분에 개발 과정 전반의 안정성을 확보하고, 검수 과정의 효율 또한 높일 수 있었습니다. 또한 PR 리뷰를 통해 서로의 코드를 Approve하며 보이지 않던 문제를 발견하고, 더 나은 구조를 함께 논의했던 과정이 코드 퀄리티를 많이 높여준 것 같습니다.

렌더링 메커니즘

  • 공식 문서를 기반으로 Next.js의 렌더링 메커니즘을 심도 있게 학습하며 과제를 진행했습니다. 최우선 목표는 의미 없는 클라이언트 컴포넌트화를 지양하는 것이었습니다. 페이지 수준에서는 서버 컴포넌트의 이점을 유지하고, 인터랙션이 꼭 필요한 부분에만 책임을 위임하여 "use client"를 선언하는 방식으로 설계했습니다. 이러한 과정을 통해 컴포넌트 간의 계층 구조와 데이터 흐름을 더 정교하게 제어하는 방법을 깊이 있게 이해할 수 있었습니다. 이론적으로만 접하던 내용을 직접 구현해보며 빠르게 감을 잡을 수 있었던 것 같습니다.

데이터 페칭 전략 및 에러 핸들링

  • 자주 사용하던 Axios 대신 Next.js와 시너지가 좋은 내장 fetch를 적극 도입했습니다. 익숙한 방식을 벗어나 새로운 라이브러리 활용법을 고민해 볼 수 있었고, 향후 TanStack Query와의 연동 가능성까지 고려하며 기술적 지평을 넓힐 수 있었습니다. (참고자료1 참고자료2)
  • 또한, 에러 처리는 개별 API 함수마다 try-catch를 두지 않고 tmdbClient에서 일괄 처리하도록 설계했습니다. res.ok 체크로 HTTP 에러를 조기에 감지하고, catch 블록에서 로깅 후 에러를 상위로 전파하여 호출부까지 버블업하도록 구현했습니다. 덕분에 home.ts, detail.ts 등의 개별 API 함수는 비즈니스 로직에만 집중하며 깔끔한 코드를 유지할 수 있었습니다.

이미지 최적화

  • 이미지 최적화와 로딩 속도 개선에 대해서도 심도 있게 고민했습니다. 대용량 이미지를 불러올 때 데이터 품질을 유지하면서도 사용자에게 빠른 뷰를 제공하기 위해 next/image의 활용 방안을 다각도로 검토하여 적용했습니다.
  • remotePatterns를 설정을 통해 허용된 호스트(image.tmdb.org)로부터의 이미지 서빙을 제한하여 보안을 강화했습니다. 이를 통해 외부 도메인의 이미지를 Next.js 고유의 최적화 파이프라인으로 안전하게 처리할 수 있었습니다. (참고자료)

협업 과정

먼저 5~6주차 과제 관련하여 회의를 진행하였으며, 원활한 협업을 위해 결정된 사항들을 시간 순서대로 정리하였습니다.

컨벤션

코드의 일관성과 효율적인 히스토리 관리를 위해 명확한 코드 및 워크플로우 규칙을 정의했습니다.

  • Git 전략 : 작업 단위별 이슈 발행을 원칙으로 하며, #이슈번호 [타입] 작업 내용 형식의 커밋 메시지와 feature/#이슈번호-작업명 브랜치 전략을 통해 작업 이력을 투명하게 관리했습니다.
  • 개발 원칙 : Next.js의 이점을 극대화하기 위해 서버 컴포넌트 활용을 기본으로 하며, 필요한 경우에만 클라이언트 컴포넌트를 분리했습니다. 명명 규칙은 PascalCase를 준수하고, 인터페이스 구조를 통일하여 가독성을 높였습니다.
  • 코드 리뷰 및 merge : Gemini 리뷰 봇을 보조 도구로 활용하되, 팀원 간의 교차 리뷰를 통해 구조적으로 유의미한 피드백을 주고 받았습니다. 상호 승인 후 작업자가 직접 머지하는 방식을 채택했습니다.

폴더 구조

도메인 중심의 구조로 설계하여 유지보수성을 높였습니다.

next-netflix-23rd/
├── public/                          # 정적 자원 (Font, Image, Lottie 등)
│   ├── favicon.svg
│   ├── og_image.png
│   ├── fonts/
│   ├── images/
│   ├── lotties/
│   └── sounds/
└── src/
    ├── app/                         # Next.js App Router (Page 및 Layout)
    │   ├── detail/[mediaType]/[id]/page.tsx
    │   ├── home/page.tsx
    │   ├── layout.tsx
    │   ├── loading.tsx
    │   ├── not-found.tsx
    │   ├── page.tsx
    │   └── globals.css
    │
    ├── components/                  # 도메인별 컴포넌트 분리 (common, home)
    │   ├── common/
    │   │   ├── BottomNavbar.tsx
    │   │   ├── Button.tsx
    │   │   ├── Header.tsx
    │   │   └── HomeIndicator.tsx
    │   └── home/
    │       ├── TrendingSection.tsx
    │       ├── TrendingHero.tsx
    │       ├── PreviewSection.tsx
    │       ├── NetflixOriginalsSection.tsx
    │       ├── AnimationMoviesSection.tsx
    │       ├── KoreanMoviesSection.tsx
    │       ├── MediaCardCarousel.tsx
    │       └── MediaThumbnail.tsx
    │
    ├── lib/                         # 비즈니스 로직 (apis, utils)
    │   ├── apis/
    │   │   ├── tmdbClient.ts
    │   │   ├── home.ts
    │   │   └── detail.ts
    │   └── utils/
    │       ├── tmdb.ts
    │       └── cn.ts
    │
    ├── constants/                   # 공통 상수 관리
    │   ├── tmdb.ts
    │   └── navItems.ts
    │
    ├── types/                       # TypeScript 타입 정의
    │   ├── home.ts
    │   └── detail.ts
    │
    └── assets/                      # 프로젝트 내부 사용 에셋 (icons)
        └── icons/

기술 스택 및 선정 이유

분류 기술 선정 이유
Package Manager pnpm 전역 저장소 + 심링크 방식으로 중복 패키지 제거, npm 대비 설치 속도 빠르고 디스크 절약
Framework Next.js 16 (App Router) 서버 컴포넌트 기반 SSR, 파일 기반 라우팅, Image/Font 최적화 내장
Language TypeScript 5 정적 타입으로 런타임 오류 사전 방지, IDE 자동완성 지원
Styling Tailwind CSS 4 유틸리티 클래스 기반으로 별도 CSS 파일 없이 빠른 UI 작성 가능
HTTP fetch (native) Next.js App Router의 fetch 확장 기능(next: { revalidate }) 활용을 위해 axios 대신 사용
Carousel Swiper 모바일 터치/드래그 지원, FreeMode,momentum 등 옵션 풍부
Animation lottie-react JSON 기반 벡터 애니메이션으로 용량 가볍고 품질 손실 없음
유틸 clsx + tailwind-merge 조건부 클래스 병합 시 Tailwind 충돌 방지
Formatter Prettier 코드 스타일 자동 통일, prettier-plugin-tailwindcss로 클래스 순서 정렬
Linter ESLint Next.js + TypeScript 규칙, simple-import-sort로 import 순서 자동 정렬
Git Hook Husky + lint-staged 커밋 전 lint/format 자동 실행으로 코드 품질 유지
SVG @svgr/webpack SVG를 React 컴포넌트로 import 가능
Deploy Vercel 조직 레포를 개인 레포로 fork해 무료 플랜으로 배포
  • 초기에 커스텀 훅을 통해 캐러셀을 직접 구현했으나, 미세한 터치만으로도 의도치 않은 드래그가 발생해 카드 클릭 시 상세 페이지 진입이 방해받는 등 UX 저하 문제가 있었습니다. 이를 해결하고자 터치 응답성이 정교하고 드래그와 클릭 이벤트 분리가 최적화된 Swiper 라이브러리를 도입하여 부드러우면서도 정확한 사용자 경험을 제공하고자 했습니다.
  • Next.js 환경에서 별도의 라이브러리 없이 내장 fetch API를 활용한 데이터 페칭 구조를 구축했습니다. 이를 통해 외부 라이브러리 의존성을 최소화할 수 있었을 뿐만 아니라, 프레임워크 수준에서 제공하는 서버 측 캐싱, 재검증을 별도 설정 없이 즉시 활용하여 런타임 성능을 높이기 위한 선택이었습니다.
  • 리소스 관리 효율성과 빌드 속도를 동시에 최적화하고자 pnpm을 채택했습니다. 먼저 전역 저장소에 패키지를 관리하는 콘텐츠 주소 지정형 방식을 활용해, 중복 설치되는 패키지를 제거하고 저장 공간을 획기적으로 아끼고 싶었습니다. 또한, 심링크 기반의 의존성 연결 구조를 통해 npm보다 압도적으로 빠른 설치 속도를 확보하고자 했습니다. 결과적으로 환경 세팅에서 발생하는 병목을 없애고 개발에 집중할 수 있는 환경을 만들고자 선택했습니다.

소통 방식

당장 이번 주 과제만 생각하면 카톡으로만 소통해도 문제 없지만, 장기적인 협업과 효율적인 정보 공유를 위해 채널을 세분화하여 운영했습니다. 서로 연락 확인이 빨라 개발이 수월하게 진행되었습니다.

  1. 카카오톡
    • 긴급 사항 공유
    • 빠른 리마인드 및 실시간 소통
  2. 디스코드
    • GitHub 웹훅을 연결하여 실시간 PR 확인
    • 비대면 회의 및 스레드 기반의 기술 질문([5주차] 제목 형식으로 히스토리 관리)
  3. 노션
    • 회의록 작성 및 내부 RnR 점검
    • 주차별 과제 기록, 컨벤션 문서화 및 리서치 & 참고 자료 아카이빙

업무 분담 및 R&R

단순히 페이지를 나누어 각자 구현하는 방식이 아니라, 전체적인 설계와 기술적 난이도를 사전에 충분히 검토한 뒤 전략적인 R&R을 수립했습니다.

  • 컨벤션, 기술 스택, 소통 방식, PR 및 규칙 등을 함께 정한 후 피그마를 보며 전체적인 서비스 플로우를 먼저 확립했습니다. 어떤 라이브러리가 추가로 필요할지, 어느 기능에 개발 공수가 많이 들지를 미리 논의했습니다.
    스크린샷 2026-05-02 043413

  • 구현 난이도가 높은 부분 또는 레퍼런스 서치가 필요한 부분에 대해서는 리서치 범위를 정하고, 최종적으로 각자의 강점에 맞춰 아래와 같이 업무를 분배했습니다.

    스크린샷 2026-05-02 035045
  • 마감 기한 내에 높은 완성도를 확보하기 위해 상대적으로 경험이 더 많은 제가 초기 환경 세팅 및 공통 레이아웃 작업을 선제적으로 완료하여 오진님이 구현에 집중하실 수 있도록 환경을 세팅했습니다.

  • 또한 작업 충돌을 방지하기 위해 도메인을 명확히 분리했습니다. 오진님이 디자인 시스템을 구축하시는 동안, 저는 전체적인 레이아웃 시스템 및 App Router의 뼈대를 구축하여 개발 병목 현상을 제거했습니다.

  • 협업의 본질에 맞게 업무 비중을 고르게 분배하는 데도 초점을 두었습니다. 그리고 코드 리뷰를 통해 끊임없이 더 좋은 구조를 제안하고 고민했던 시간들이 큰 도움이 되었습니다. 다음 주부터는 남은 기능 개발과 서비스 최적화에 집중해서 완성도를 더 높여보려 합니다.


Review Questions

React 18 버전의 변경점에 대해 설명해주세요.

React 18 버전의 변경점

렌더링 방식 자체를 더 유연하고, 끊김없고 대규모 앱에 적합하게 바꿈

  1. Concurrent Rendering 기반
  2. Suspense의 활용 범위가 넓어짐
  3. 자동 batching이 강화되어 렌더 효율이 좋아짐
  4. SSR과 스트리밍이 개선되어 서버와 클라이언트의 역할 분리가 중요

서버 컴포넌트와 클라이언트 컴포넌트

서버 컴포넌트

  • 서버에서 실행되고 결과만 클라이언트로 전달되는 컴포넌트
  • 오직 서버에서만 실행 가능하며 클라이언트로 전송할 때 브라우저 번들이 포함되지 않음 → 초기 렌더링 성능 향상 및 SEO 이점
  • 이벤트 핸들러나 클라이언트 전용 훅 (useState, useEffect 등)은 직접 사용 불가 → 불필요한 UI 로직을 브라우저에 전송하지 않아도 됨
  • DB, API, 파일 시스템 등 서버에 직접 접근 가능 → 클라이언트 사이드 로딩 낭비 감소

⇒ 서버에서 미리 데이터를 가져와 필요한 마크업을 만들어서 클라이언트에 최소한의 결과와 필요한 상호작용 부분만 남기려고 함

클라이언트 컴포넌트

  • 브라우저에서 실행되며 useState, useEffect, useReducer 훅 사용 가능
  • JS 번들이 전송되어 클릭, 입력, 토글 같은 상호작용 처리
  • 데이터 접근 시 API를 통해서만 접근 가능

⇒ 사용자 이벤트에 반응, 브라우저 전용 API 사용 등 사용자와의 즉각적인 상호작용 필요 시 사용

lazy loading과 Suspense 컴포넌트

lazy loading

  • 컴포넌트를 동적으로 import 하여 실제로 렌더링이 필요한 시점에만 컴포넌트 불러옴
  • 초기 애플리케이션 번들 크기를 줄여 로딩 시간 단축
  • React.lazy로 감싼 컴포넌트는 반드시 Suspense 컴포넌트 하위에서 렌더링되어야 함

Suspense

  • lazy 로 로딩된 컴포넌트가 준비될 때까지 기다렸다가 로딩 상태 표시
  • 컴포넌트가 도착하지 않은 순간 발생하는 빈 시간 사이 fallback UI를 보여줌
    (fallback Prop : 컴포넌트가 로딩되는 동안 보여줄 UI(ex: 로딩 스피너, 스켈레톤 등) 설정)
  • 하나의 Suspense 로 여러 lazy 컴포넌트를 감싸서 한 번에 로딩 상태 관리 가능
  • React 18 이전에는 Suspense 는 코드 분할용이라는 이미지가 강했으나 React 18 이후에는 비동기 UI 경계로 더 중요해짐

Automatic batching

  • batching : 상태 업데이트가 여러 번 일어날 때, 가능하면 묶어서 한 번만 렌더링하려고 하는 것
  • React 18 이전에서 이벤트 핸들러 내부의 state update 작업에 대해서만 batching 가능 → 이전에는 브라우저의 이벤트가 실행되는 중에만 batching 작업 수행
  • Automatic batching : ReactDOM.createRoot 메서드를 기반으로 렌더링 진행할 경우 모든 state update 작업은 자동으로 batching
  • React 18 이후부터 Automatic batching 기능 도입으로 setTimeout, Promise, 이벤트 핸들러 등 어디에서 호출하든 기본적으로 모든 업데이트를 자동으로 묶어서 처리

Concurrent Rendering

  • Concurrency(동시성)
    • 한번에 둘 이상의 작업이 동시에 진행되는 것
    • 어떤 작업이 더 긴급한지에 따라 동시 작업이 겹칠 수 있음
  • React 18 이전 렌더링은 개입할 수 없는 하나의 동기적인 처리로 한번 렌더링 시작되면 렌더링을 중단, 재개, 폐기할 수 없었음
  • Concurrent Rendering
    • 렌더링 작업을 잘게 쪼개어 우선순위에 따라 중단, 재개, 폐기할 수 있는 기술
    • 기존의 render 대신 createRoot를 사용하며, 이와 같은 Concurrent Mode를 설정하면 startTransition, useTransition, useDeferredValue 훅들을 사용하여 개선된 기능들과 동시 처리가 가능해짐
// 기존 React 18 이전
import ReactDOM from "react-dom";
import App from "App";

const container = document.getElementById("app");

ReactDOM.render(<App />, container);
// React 18
import ReactDOM from "react-dom";
import App from "App";

const container = document.getElementById("app");

//루트 생성
const root = ReactDOM.createRoot(container);

//루트를 통해 앱 렌더
root.render(<App />, container);

waldls and others added 30 commits April 28, 2026 13:21
[DEPLOY] Vercel 프리뷰 및 master 자동 배포 파이프라인 설정
…sist

[SETTING] Gemini PR 리뷰 가이드라인 문서 작성
[FEAT] 공통 레이아웃 구현 (헤더, 하단 내브바, 아이콘 시스템)
Copy link
Copy Markdown

@yiyoonseo yiyoonseo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

바쁘신 와중에도 5주차 과제 너무 깔끔하게 잘 해주신 것 같습니다 ! 많이 배워갑니다😍

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 템플릿까지 신경쓰신 점이 너무 좋은 것 같습니다 !

Comment thread src/app/page.tsx
audio.currentTime = 0;
router.push("/home");
}, 3000);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3000ms로 시간을 고정해두는 방법도 좋지만 lottie-react에서 제공하는 onComplete 콜백을 사용하면 애니메이션이 끝나는 즉시 페이지를 이동시킬 수 있어 훨씬 자연스러울 것 같습니다!

공식 문서입니다!
https://lottiereact.com

Copy link
Copy Markdown

@GirimNam GirimNam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번주차 리뷰를 함께 하게 되어 영광입니당!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mp3까지 넣어서 넷플릭스 사운드까지 구현하신거 너무 멋져요!

priority={index === 0}
/>
))}
<div className="bg-gradient-thumbnail absolute inset-0" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개별적으로 유틸리티 클래스 만드셔서 그라데이션 구현하신거 너무 좋은거 같아요!

Comment on lines +19 to +31
<Swiper
modules={[FreeMode]}
freeMode={{ momentum: true }}
grabCursor
slidesPerView="auto"
spaceBetween={7}
>
{items.map(item => (
<SwiperSlide key={item.id} style={{ width: "auto" }}>
<MediaThumbnail item={item} shape={shape} size={size} />
</SwiperSlide>
))}
</Swiper>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swiper 라이브러리로 영화 포스터 썸네일들을 옆으로 편하게 넘길 수 있어서 너무 효과적인거 같아요

console.error(`[tmdbClient] ${path}`, error);
throw error;
}
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

홈 화면에 필요한 API를 섹션별 함수로 분리한 점이 좋았습니다.
각 섹션이 어떤 데이터를 사용하는지 함수명만 봐도 이해하기 쉽고, 이후 카테고리 추가나 수정사항이 생겨도 관리하기 편할 것 같아요!

Copy link
Copy Markdown

@minseo0614 minseo0614 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5주차 과제 수고하셨습니다! 코드 리뷰하면서 많이 배울 수 있었습니다

Comment on lines +32 to +44
<div className="relative h-103.75 w-full">
{items.map((item, index) => (
<Image
key={item.id}
src={getTmdbImageUrl(item.poster_path ?? "", "w500")}
alt={getMediaTitle(item) || "이미지 없음"}
fill
sizes="375px"
className={`object-cover transition-opacity duration-700 ${index === current ? "opacity-100" : "opacity-0"}`}
priority={index === 0}
/>
))}
<div className="bg-gradient-thumbnail absolute inset-0" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hero 슬라이드를 이미지 src를 갈아끼우는 방식이 아니라 10장을 한 번에 다 렌더해두고 opacity로 전환해서 슬라이드가 깜빡임 없이 부드럽게 페이드되는 부분 너무 좋은 것 같아요!

import MediaCardCarousel from "@/components/home/MediaCardCarousel";
import { getPopularMovies } from "@/lib/apis/home";

const PreviewSection = async () => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

page.tsx에는 레이아웃만 잡고,각 섹션이 server component로 자기 데이터를 직접 가져가게 만드신 구조 깔끔하네요!!

YJ0623 added a commit to YJ0623/next-netflix-23rd that referenced this pull request May 6, 2026
@waldls waldls closed this May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants