풀스크린 이미지 슬라이더
Overview
풀스크린 비디오 슬라이더를 Next.js + GSAP으로 구현한 프로젝트입니다. 단순히 움직이는 UI가 아니라 — SVG 클립 패스 리빌, 포인터 드래그 실시간 프리뷰, 캐릭터 단위 텍스트 스플릿까지 프리미엄 인터랙션을 프로덕션 수준의 아키텍처 위에 구현했습니다.
Feature-Sliced Design으로 슬라이더 전체 코드를 하나의 feature에 응집하고, 450줄 규모의 커스텀 훅이 애니메이션 오케스트레이션을 전담합니다. UI 컴포넌트는 순수한 렌더링만 담당하여 관심사 분리가 명확합니다.
Anatomy
UI 해부도
풀스크린 슬라이더는 7개의 독립 UI 컴포넌트로 구성됩니다. 각 영역은 자체 애니메이션 로직을 가지며, 하나의 커스텀 훅이 전체 오케스트레이션을 담당합니다.
- NavBar
- 로고 · 메뉴 · 햄버거
- BigText
- 글자 분할 애니메이션
- InfoBox
- 카테고리 · 제목 · 설명
- StripClip
- 6-strip SVG 마스크
- SlideCounter
- 현재 / 전체 슬라이드
- BottomBar
- SNS 링크 · 카피라이트
Structure
프로젝트 아키텍처
Feature-Sliced Design 기반으로 슬라이더 관련 모든 코드를 하나의 feature 폴더에 응집합니다. UI · 로직 · 데이터 · 스타일이 명확히 분리되어 있어 유지보수와 팀 협업에 유리합니다.
- slides.json
- 5개 슬라이드 데이터
- useSliderAnimation.ts
- 450+ lines · 전체 애니메이션 오케스트레이션
- useMobileMenu.ts
- 모바일 메뉴 토글 · GSAP 연동
- FullSlider.tsx
- 루트 컨테이너
- SlideItem.tsx
- 비디오 슬라이드
- BigText.tsx
- 대형 타이포그래피
- InfoBox.tsx
- 정보 패널
- StripClip.tsx
- SVG 클립 패스
- NavBar.tsx
- 네비게이션
- SlideCounter.tsx
- 번호 카운터
- BottomBar.tsx
- 하단 바
- MobileMenu.tsx
- 모바일 메뉴
- slider.css
- CSS 변수 · clamp 반응형
Data Flow
컴포넌트 데이터 플로우
데이터는 단방향으로 흐릅니다. JSON에서 시작해 커스텀 훅이 애니메이션 로직을 처리하고, UI 컴포넌트는 순수하게 렌더링만 담당합니다.
ANIMATION OUTPUT
- SlideItem
- 비디오 전환
- scale 1.3 → 1.0
- StripClip
- 마스크 리빌
- 6-strip 교차 슬라이드
- BigText
- 글자 분할
- char stagger 60ms
- InfoBox
- 정보 전환
- 라인별 fade 40ms
Timeline
애니메이션 타임라인
슬라이드 전환은 약 2.1초 동안 6개의 애니메이션 레이어가 정밀하게 오케스트레이션됩니다. GSAP Timeline의 절대 시간 오프셋으로 각 레이어의 시작 · 종료를 제어합니다.
- 이전 BigText · InfoBox 퇴장
- 6개 스트립 교차 슬라이드 (stagger 60ms)
- scale 1.3 → 1.0 줌인 효과
- 4면 보더라인 scaleX/Y 진입
- 새 BigText chars yPercent 애니메이션
- InfoBox 라인별 순차 페이드인
Interaction
인터랙션 플로우
사용자 입력은 Wheel과 Drag 두 갈래로 분기됩니다. Drag는 실시간 프리뷰 → 60% 임계값 판정 → 완료/취소 3단계를 거치며, 모든 경로에서 isAnimating 가드가 중복 실행을 차단합니다.
- 1
deltaY 방향 감지
e.deltaY > 0 ? next : prev - 2
modulo 순환 인덱스 계산
- 3
goToSlide() 즉시 실행
→ Timeline 2.1s
- 1
pointerdown → setPointerCapture
8px 최소 이동 후 활성화 - 2
setupDragPreview → 다음 슬라이드 준비
- 3
pointermove → 실시간 스트립 + 엘리먼트 업데이트
smoothstep easing: p²(3-2p) - 4
pointerup → 진행률 판정
Patterns
핵심 기술 패턴
단순히 모션이 예쁜 것이 아니라, 프로덕션에서 유지보수 가능한 구조로 설계했습니다. 메모리 누수 방지 · DOM 쿼리 최적화 · 상태 충돌 가드까지 — 실무에서 바로 적용할 수 있는 패턴입니다.
- 라이프사이클 안전성
- gsap.context()로 모든 트윈을 스코프화 — 언마운트 시 ctx.revert() 한 줄로 전체 클린업
- ctx = gsap.context(() => { ... }, container)
- DOM 쿼리 최적화
- gsap.utils.selector()로 초기화 시 한 번만 DOM을 탐색 — 매 전환마다 재탐색 제거
- q = gsap.utils.selector(container) q("[data-slider='slide']")
- 정밀한 시간 제어
- 절대 시간 오프셋으로 6개 레이어의 시작점을 지정 — 병렬 + 순차 혼합 오케스트레이션
- tl.to(el, {...}, 0.3) // 0.3s에 시작
- JS-HTML 디커플링
- data-slider 속성으로 GSAP 셀렉터 바인딩 — 클래스 충돌 없이 구조 독립적 쿼리
- <figure data-slider="slide" />
- 상태 충돌 방지
- useRef 기반 isAnimating 플래그로 wheel + drag 중복 실행 원천 차단 — 리렌더 없이 상태 관리
- if (isAnimating.current) return
- 리소스 효율화
- 활성 슬라이드의 비디오만 재생 — 전환 완료 시 이전 비디오 정지, 새 비디오 0초부터 시작
- v.currentTime = 0; v.play().catch(() => {})
Responsive
반응형 전략
데스크탑 퍼스트로 설계하고 max-xl · max-md 2단계 브레이크포인트만 사용합니다. CSS 변수 clamp()로 박스 사이즈가 뷰포트에 맞게 자연스럽게 스케일됩니다.
- BigText 좌측 고정
- InfoBox 중앙 배치
- SlideCounter 우하단
- BottomBar 풀 너비
- Drag 제스처 활성
- BigText 좌측 축소
- InfoBox 중앙 유지
- 간격 · 패딩 축소
- clamp 반응형 적용
- 폰트 사이즈 조정
- BigText 상단으로 이동
- InfoBox 하단으로 이동
- 햄버거 메뉴 전환
- Counter · SNS 숨김
- 터치 스와이프 전용