클릭 시 확장되는 갤러리
Overview
썸네일 갤러리에서 클릭하면 GSAP Flip으로 이미지가 풀스크린으로 확장되는 인터랙티브 갤러리입니다. 단순한 모달이 아니라 — Flip 레이아웃 전환, SplitType 텍스트 리빌, SVG 동심원 모션, 커스텀 커서까지 프리미엄 인터랙션을 하나의 훅에서 오케스트레이션합니다.
Feature-Sliced Design으로 갤러리 전체 코드를 하나의 feature에 응집하고, 15개 UI 컴포넌트가 역할별로 분리되어 있습니다. 300줄 규모의 커스텀 훅이 Flip · SplitType · 캐러셀 네비게이션을 전담하고, UI 컴포넌트는 순수한 렌더링만 담당합니다.
Anatomy
UI 해부도
갤러리는 8개의 독립 UI 컴포넌트로 구성됩니다. 데스크탑에서는 absolute 레이어로 자유롭게 배치되고, 모바일에서는 flex 세로 레이아웃으로 전환됩니다.
- Nav
- 로고 · 메뉴 · 검색
- CircleSvg
- SVG 동심원 배경 모션
- BigTitle
- SplitType 타이틀 애니메이션
- Carousel
- 썸네일 트랙 + 이미지 카드
- Counter
- 현재 / 전체 인덱스
- MetaInfo
- Established · Based in
- SocialLinks
- 좌측 소셜 아이콘
- BottomLeft
- Play 버튼 · 설명 텍스트
Structure
프로젝트 아키텍처
Feature-Sliced Design 기반으로 갤러리 관련 모든 코드를 하나의 feature 폴더에 응집합니다. 15개 UI 컴포넌트가 역할별로 분리되어 있고, 하나의 커스텀 훅이 전체 애니메이션을 전담합니다.
- gallery.json
- 6개 갤러리 아이템 (이미지 · 제목 · 컬러)
- meta.json
- Established · Based in 메타 정보
- social.json
- 소셜 링크 아이콘 매핑
- useGalleryAnimation.ts
- 300+ lines · Flip 확장 + 캐러셀 오케스트레이션
- SectionGallery.tsx
- 루트 컨테이너 · 훅 연결
- Gallery.tsx
- 3-레이어 레이아웃 (top · carousel · bottom)
- Carousel.tsx
- 썸네일 트랙
- GalleryItem.tsx
- 이미지 카드 + 그림자
- ContentDetail.tsx
- Flip 확장 상세 뷰
- BigTitle.tsx
- SplitType 대형 타이틀
- Counter.tsx
- 슬라이드 번호 카운터
- CarouselNav.tsx
- 이전/다음 버튼
- CustomCursor.tsx
- 커스텀 크로스 커서
- Nav.tsx
- 상단 네비게이션
- CircleSvg.tsx
- SVG 동심원 배경
- MetaInfo.tsx
- 메타 정보 DL
- SocialLinks.tsx
- 소셜 아이콘
- DescRight.tsx
- 우측 설명 텍스트
- BottomLeft.tsx
- Play 버튼 · 하단 텍스트
- gallery.css
- CSS 변수 · 캐러셀 사이징 · 커서 스타일
Data Flow
컴포넌트 데이터 플로우
데이터는 단방향으로 흐릅니다. JSON에서 시작해 커스텀 훅이 Flip · SplitType 로직을 처리하고, UI 컴포넌트는 순수하게 렌더링만 담당합니다.
ANIMATION OUTPUT
- Carousel
- 썸네일 슬라이드
- track translateX + scale
- Flip
- 이미지 확장
- thumbnail → fullscreen 1.25s
- SplitType
- 제목 리빌
- chars clipPath stagger
- ContentDetail
- 상세 진입
- lines yPercent + swatch scale
Timeline
애니메이션 타임라인
상세 뷰 열기는 약 2.0초 동안 9개의 애니메이션 레이어가 정밀하게 오케스트레이션됩니다. GSAP Flip이 이미지 전환을 담당하고, SplitType이 텍스트 리빌을 처리합니다.
- 클릭된 카드 그림자 페이드아웃
- 상단 · 하단 레이어 투명도 0
- GSAP Flip — 썸네일 → 풀스크린 이미지 (1.25s)
- 나머지 카드 clipPath inset 퇴장
- 좌측 세로 레이블 xPercent 진입
- SplitType chars clipPath 리빌 (stagger 15ms)
- 구분선 scaleX 0 → 1
- 본문 lines yPercent 순차 페이드인 (stagger 25ms)
- 컬러 칩 scale + back easing 팝인
Interaction
인터랙션 플로우
사용자 인터랙션은 Carousel Nav, Gallery Click, Detail Click 세 갈래로 분기됩니다. Gallery Click은 GSAP Flip으로 이미지를 확장하고, Detail Click은 역순으로 복원합니다.
- 1
Prev / Next 버튼 클릭
- 2
트랙 translateX 이동
track x: -step (0.6s) - 3
BigTitle SplitType 교체
chars yPercent exit → enter
- 1
썸네일 이미지 클릭
- 2
Flip.getState → 이미지 DOM 이동
Flip.from(state, 1.25s) - 3
나머지 카드 clipPath 퇴장
- 4
상세 텍스트 SplitType 리빌
chars · lines · swatches
- 1
오버레이 또는 Back 버튼 클릭
- 2
텍스트 · 컬러칩 역순 퇴장
- 3
Flip 역전환 → 썸네일 복원
Flip.from(state, 1.25s)
Patterns
핵심 기술 패턴
단순히 모션이 예쁜 것이 아니라, 프로덕션에서 유지보수 가능한 구조로 설계했습니다. Flip 레이아웃 전환 · SplitType 텍스트 리빌 · AbortController 클린업까지 — 실무에서 바로 적용할 수 있는 패턴입니다.
- 레이아웃 전환 애니메이션
- Flip.getState()로 현재 위치 캡처 → DOM 이동 후 Flip.from()으로 자연스러운 위치 · 크기 전환
- const state = Flip.getState(img) target.appendChild(img) Flip.from(state, { duration: 1.25 })
- 텍스트 분할 애니메이션
- chars · lines 단위로 텍스트를 분할하고, clipPath · yPercent로 글자 단위 리빌 — 래퍼 요소로 오버플로 제어
- new SplitType(el, { types: 'chars' }) chars → clipPath: inset(0 100% 0 0)
- 라이프사이클 안전성
- gsap.context()로 모든 트윈을 스코프화 — 언마운트 시 ctx.revert() 한 줄로 전체 클린업
- ctx = gsap.context(() => { ... }, container)
- JS-HTML 디커플링
- data-gallery 속성으로 GSAP 셀렉터 바인딩 — 클래스 충돌 없이 구조 독립적 쿼리
- <figure data-gallery="image-wrapper" />
- 이벤트 리스너 관리
- signal 기반으로 모든 이벤트 리스너 등록 — abort() 한 번으로 전체 정리, 메모리 누수 원천 차단
- el.addEventListener('click', fn, { signal }) // cleanup: abort.abort()
- 인터랙티브 커서 UX
- rAF 기반 lerp 추적으로 부드러운 커서 — 상세 뷰에서 is-open 클래스로 회전 변환하여 닫기 시그널 제공
- cursorX += (targetX - cursorX) * 0.15 cursor.style.transform = translate3d(...)
Responsive
반응형 전략
데스크탑 퍼스트로 설계하고, CSS 변수로 캐러셀 사이징을 제어합니다. 데스크탑은 absolute 레이어 배치, 태블릿 이하는 flex 세로 레이아웃으로 자연스럽게 전환됩니다.
- absolute 레이어 자유 배치
- 캐러셀 우측 50vw 영역
- BigTitle 좌측 고정
- 커스텀 커서 활성
- DescRight · SocialLinks 표시
- flex 세로 레이아웃 전환
- 캐러셀 전체 너비 96vw
- BigTitle 상단 배치
- DescRight 숨김
- MetaInfo 가로 배치
- 캐러셀 2.2장 노출
- BigTitle 대형 12vw
- 메뉴 링크 숨김
- MetaInfo · SocialLinks 숨김
- 터치 기반 인터랙션