본문으로 건너뛰기

Lazy Load

renderOnlyVisible 옵션과 visibleChange 이벤트를 조합하여, 보이는 패널만 이미지를 로드하는 성능 최적화 패턴입니다.

import Flicking from "@egjs/flicking";
import "@egjs/flicking/dist/flicking.css";
import "./styles.css";

const TOTAL = 100;
const COLORS = ["#e74c3c", "#3498db", "#2ecc71", "#f39c12", "#9b59b6"];
const getImageUrl = i => `https://picsum.photos/seed/${i}/250/180`;

const camera = document.querySelector(".flicking-camera");
for (let i = 0; i < TOTAL; i++) {
  const panel = document.createElement("div");
  panel.className = "flicking-panel";
  panel.style.background = COLORS[i % COLORS.length];
  panel.innerHTML = `<div class="placeholder">Panel ${i}</div>`;
  camera.appendChild(panel);
}

const loadedSet = new Set();
const infoBar = document.querySelector(".info-bar");

const updateInfo = () => {
  infoBar.textContent = `Images loaded: ${loadedSet.size} / ${TOTAL} (only visible panels are loaded)`;
};

const loadImage = panel => {
  const idx = panel.index;
  if (loadedSet.has(idx)) return;
  loadedSet.add(idx);
  panel.element.innerHTML = `<img src="${getImageUrl(idx)}" alt="Panel ${idx}" />`;
  updateInfo();
};

const flicking = new Flicking("#flick", {
  renderOnlyVisible: true,
  align: "prev",
  bound: true,
  preventDefaultOnDrag: true
});

flicking.on("ready", e => {
  e.currentTarget.visiblePanels.forEach(loadImage);
});

flicking.on("visibleChange", e => {
  e.added.forEach(loadImage);
});

요약

주요 옵션/이벤트

항목타입기본값설명
renderOnlyVisiblebooleanfalse보이는 패널만 렌더링
visibleChangeVisibleChangeEvent-화면에 보이는 패널이 변경될 때 발생

이벤트 속성

속성타입설명
addedPanel[]새로 화면에 진입한 패널
removedPanel[]화면에서 벗어난 패널
visiblePanelsPanel[]현재 화면에 보이는 패널 전체

동작 비교

방식이미지 로드 시점적합한 상황
일반 로딩모든 패널 한 번에 로드패널이 적을 때 (10개 이하)
Lazy 로딩화면에 진입할 때 로드패널이 많을 때 (수십~수백 개)

상세 설명

동작 원리

  1. renderOnlyVisible: true로 보이는 패널만 렌더링
  2. visibleChange 이벤트의 added 배열에서 새로 보이는 패널 감지
  3. 해당 패널의 이미지를 로드하고, 로드 여부를 기록
  4. 한번 로드된 이미지는 다시 로드하지 않음 (Set으로 추적)

초기 로드

Flicking이 초기화된 직후에는 visibleChange가 아직 발생하지 않으므로, ready 이벤트에서 초기 visible 패널의 이미지를 로드해야 합니다.

연관 옵션

  • renderOnlyVisible과의 관계: 이 옵션이 핵심. 보이지 않는 패널의 렌더링을 생략하여 DOM 부담을 줄임
  • bound와의 관계: bound: true와 함께 쓰면 끝에서 빈 공간 없이 자연스러운 스크롤 가능
  • align과의 관계: align: "prev"로 리스트형 레이아웃에 적합

사용 시나리오

언제 사용하나요?
  • 대량 이미지가 포함된 갤러리 (50개 이상)
  • 무한 스크롤 피드에서 이미지 최적화
  • 모바일 환경에서 네트워크 부담 경감

주의사항

주의
  • renderOnlyVisible은 프레임워크(React, Vue) 환경에서 사용을 권장합니다
  • visibleChange 이벤트의 added 패널은 Panel 객체이며, index 속성으로 식별할 수 있습니다
  • 초기 로드 시 ready 이벤트에서 별도로 visible 패널을 처리해야 합니다

관련 링크

관련 옵션

관련 데모