Skip to content

@egjs flicking 코드 가이드

malangfox edited this page Jan 17, 2025 · 3 revisions

이 문서는 @egjs/flicking 레파지토리의 개발을 위한 가이드입니다.


프로젝트 개요

@egjs/flicking은 드래그를 통해 움직일 수 있는 캐러셀 형태의 UI를 제공하는 컴포넌트입니다.

사용자는 아래 구조와 같은 엘리먼트를 대상으로 Flicking 인스턴스를 적용할 수 있습니다.

<div id="myflicking" class="flicking-viewport">
  <div class="flicking-camera">
    <div class="panel"></div>
    <div class="panel"></div>
    <div class="panel"></div>
  </div>
</div>
const flicking = new Flicking("#myflicking", options);

Flicking의 UI는 세 가지 종류의 엘리먼트로 구성되어 있습니다.

Viewport

사용자에게 보여지는 Flicking의 영역입니다.

Viewport의 하위에 있는 Camera 엘리먼트는 Flicking의 기본 style로 width: 100%, height: 100%를 가지고 있습니다.

플러그인 중 Arrow 등 Camera의 움직임과 별도로 동작하는 엘리먼트를 추가하는 플러그인을 사용하는 경우,

Viewport의 자식 엘리먼트로 Camera 엘리먼트 외에도 해당 엘리먼트들을 추가해야 합니다.

Camera

Flicking의 이동을 제어하는 엘리먼트입니다.

Flicking의 이동은 Flicking 엘리먼트에서 드래그가 발생했을 때 Camera 엘리먼트에 transform: translate(...px) 처럼 transform style을 적용해서 이루어집니다.

Camera 내부에는 각각의 Panel마다 Camera의 움직임이 멈추는 자리인 Anchor 가 존재합니다.

Camera가 멈추는 지점이 존재하지 않는 moveType: "freescroll" 을 제외하면 Flicking의 이동은 Anchor마다 설정된 좌표로 Camera의 transform이 움직이는 식으로 이루어집니다.

Panel

Flicking 내부에 배치되는 각각의 엘리먼트입니다.

Camera 엘리먼트의 children 하나하나가 Panel로 설정됩니다.


프로젝트 구조

├── camera/                             # Camera 엘리먼트의 상태 및 이동을 관리
│   ├── mode/                           # 현재 옵션 상태에 따라 변할 수 있는 Camera 관련 로직들
│   │   ├── CameraMode.ts               # 이 클래스를 확장해서 Camera에서 사용되는 공통 로직들을 관리
│   │   ├── LinearCameraMode.ts         # 일반적인 경우의 Camera 관련 로직
│   │   ├── BoundCameraMode.ts          # bound 옵션이 활성화되어있을 때의 관련 로직
│   │   └── CircularCameraMode.ts       # circular 옵션이 활성화되어있을 때의 관련 로직
│   └── Camera.ts                       # Camera 클래스와 메서드들을 관리
├── control/                            # Flicking의 입력 이벤트 또는 메서드를 통해 제어되는 내부 상태
│   ├── states/                         # Flicking의 현재 상태에 따른 상태 전환과 이벤트 발생을 관리
│   │   └── ...                         # 각각의 상태에 따른 로직들
│   ├── Control.ts                      # 사용자 입력을 처리하고 이에 맞게 Camera 위치 갱신 및 관련 메서드
│   ├── StateMachine.ts                 # Flicking 내부 Axes 인스턴스(사용자 입력 처리) 의 상태 갱신 로직
│   ├── AxesController.ts               # Axes 인스턴스(사용자 입력 처리) 와 Flicking의 동작을 연동
│   ├── SnapControl.ts                  # moveType: "snap" 의 조작 방식을 관리
│   ├── StrictControl.ts                # moveType: "strict" 의 조작 방식을 관리
│   └── FreeControl.ts                  # moveType: "freescroll" 의 조작 방식을 관리
├── renderer/                           # Flicking 내부 Panel의 렌더링과 배치를 관리
│   ├── strategy/                       # Panel이 렌더링되기 위한 동작인 RenderingStrategy를 관리
│   │   ├── RenderingStrategy.ts        # 다른 RenderingStrategy 들로 확장되는 추상 클래스
│   │   ├── NormalRenderingStrategy.ts  # 일반적인 경우에 Panel을 표시하거나 숨기는 로직들
│   │   └── VirtualRenderingStrategy.ts # virtual 옵션이 활성회되어있을 때의 RenderingStrategy
│   ├── Renderer.ts                     # Panel의 DOM 정보 저장 및 갱신, 크기와 위치를 관리
│   ├── VanillaRenderer.ts              # Renderer의 동작 중 바닐라 JS 환경에서 필요한 동작
│   └── ExternalRenderer.ts             # Renderer의 동작 중 타 프레임워크의 경우 이 클래스 사용
├── core/                               # Flicking에 사용되는 주요 로직들
│   ├── panel/                          # Flicking 내부에 존재하는 각각의 엘리먼트인 Panel을 관리
│   │   └── ...                         # Panel이 가지고 있는 속성과 메서드들
│   ├── AnchorPoint.ts                  # 각 Panel의 위치에 따라 Camera가 멈추는 지점 클래스
│   ├── AutoResizer.ts                  # window에 resize 이벤트가 발생할 때의 처리
│   ├── FlickingError.ts                # Flicking에서 Error를 표시할 때 사용되는 클래스
│   ├── ResizeWatcher.ts                # 현재는 사용되지 않는 코드인 듯
│   ├── Viewport.ts                     # Flicking의 최외곽 엘리먼트읜 Viewport의 크기를 관리
│   └── VirtualManager.ts               # virtual 옵션이 활성화되어 있을 때의 로직
├── Flicking.ts                         # Flicking 인스턴스의 옵션과 핵심 로직들을 관리
├── CrossFlicking.ts                    # Flicking의 Preset, CrossFlicking의 정의 및 내부 로직
└── utils.ts                            # Flicking 내부 유틸리티 함수 모음

주요 클래스 및 메서드

  • 인스턴스 및 플러그인 초기화, 옵션 처리, 이벤트 바인딩을 담당합니다.
  • getter, setter, 메서드 등 주요 동작도 정의되어 있습니다.

  • Flicking 영역의 이동을 관리합니다.
  • Anchor와 관련된 로직도 Camera 클래스에 포함되어 있습니다.

  • 개별 Panel의 상태와 동작을 관리합니다.
  • Panel의 크기와 위치 등을 속성으로 가지고 있습니다.

  • 사용자의 입력 이벤트를 통해 Camera의 이동을 제어합니다.
  • 또한, 현재 Camera의 위치를 변경하는 moveTo 등의 메서드들을 통한 이동을 제어합니다.

  • Flicking 내부의 DOM을 관리합니다.
  • Panel의 추가, 제거 등의 동작이 발생하면 Renderer가 DOM을 갱신합니다.
  • React, Vue, Angular 등 타 프레임워크는 ExternalRenderer 클래스를 사용합니다.

Flicking의 플러그인

Flicking은 플러그인을 통해 추가적인 기능들을 쉽게 덧붙일 수 있습니다.

사용자는 아래와 같이 플러그인을 적용할 수 있습니다.

<div id="myflicking" class="flicking-viewport">
  <div class="flicking-camera">
    <div class="panel"></div>
    <div class="panel"></div>
    <div class="panel"></div>
  </div>
</div>
const flicking = new Flicking("#myflicking", options);
const autoplay = new Flicking.Plugins.AutoPlay();

flicking.addPlugins(arrow, autoplay);

현재 Flicking에는 7개의 플러그인이 존재합니다.

AutoPlay

  • Flicking을 일정한 간격으로 자동으로 이동시키는 기능을 제공합니다

Parallax

  • Flicking의 Panel 이동에 따라 선택한 엘리먼트에 transform을 적용합니다.

Fade

  • 현재 선택되지 않은 Panel들에 페이드 효과를 넣습니다.

Arrow

  • Flicking의 Panel을 이동시킬 수 있는 이전/다음 화살표 버튼을 추가합니다.

Pagination

  • Flicking에 페이지네이션을 추가합니다.

Sync

  • 여러 Flicking 인스턴스의 Camera 진행도를 동기화합니다.

Perspective

  • Flicking의 Panel에 기울어진 transform을 적용합니다.

각 플러그인의 구현은 별도의 플러그인 레파지토리 에서 확인할 수 있습니다.


개발 및 유지보수 가이드

새 기능 추가

  • 새 옵션을 추가하는 경우 Flicking.ts에서 해당 옵션명을 검색한 뒤 유사하게 새 옵션을 추가합니다.
  • 옵션의 동작에 따라 알맞은 곳에 구현을 추가한 뒤 getter, setter가 정상 동작하는지도 확인해보아야 합니다.

버그 수정

  • 버그 제보 이슈의 경우 이슈 템플릿 또는 리액트 이슈 템플릿 에서 재현을 시도합니다.
  • 이슈가 재현이 되었다면 로컬 환경에서 Flicking을 빌드하며 버그 해결 여부를 확인합니다
    • 특정 옵션 버그의 경우 해당 옵션이 쓰이는 곳을 모두 확인해볼 수 있습니다.
    • 특정 플러그인 버그의 경우 플러그인 레파지토리 내의 각 플러그인의 구현을 확인해주세요.
    • 특정 프레임워크만 발생하는 이슈의 경우 packages 폴더 내의 각 패키지를 확인해주세요.

테스트 작성

  • 새 기능을 추가하거나 버그를 수정한 이후에는 관련된 유닛 테스트를 추가해주세요.
  • test/unit 경로에 기존의 유닛 테스트들이 존재합니다.
  • 플러그인의 경우 플러그인 레파지토리에 유닛 테스트들이 존재합니다.

여기서부터 시작해보세요

  • Flicking.ts 는 컴포넌트의 진입 지점입니다.
  • 사용자가 Flicking 인스턴스를 생성하면 constructorinit을 통해 옵션이 반영되고 컴포넌트가 초기화됩니다.
  • constructor 에서는 내부 코어 컴포넌트 Viewport, Renderer, Camera, Control을 생성합니다.
  • init 에서는 각 컴포넌트의 초기화가 이루어집니다.