swiper 라이브러리 내부 톺아보기 2

서성원·2026년 1월 15일

공식문서

목록 보기
2/2
post-thumbnail

이전글에서는 swiper 라이브러리에 구현되어 있는 슬라이드 종류와 일반 슬라이드 구현의 특징에 대해 알아보았다.

이번에는 Virtual 슬라이드의 개념과 쓰임에 대해 알아보려 한다.

Virtural 슬라이드의 내부동작

Virtual 슬라이드의 메소드 인터페이스는 virtual.d.ts에서 볼 수 있다.

Virtual 슬라이드에서는 일반 슬라이드 메소드appendSlide, prependSlide, removeSlide, removeAllSlides외에도 from, to, cache, slides, update를 가진다.

이 메소드들은 왜 더 필요할까? 그것은 DOM을 다루는 방식에 있다.

1. 일반 vs Virtual의 상태를 가지는 주인

일반 슬라이드

  • 상태의 근원 = DOM
  • 슬라이드 추가/삭제 = DOM에 append/prepend/remove
  • Swiper는 DOM을 읽어 (recalcSlides, update) 내부 상태를 재조정

Virtual 슬라이드

  • 상태의 근원 = virtual.slides배열
  • DOM은 "화면에 필요한 만큼" 부분적으로 존재
  • Swiper는 아래의 값들을 계산한다
	- 지금 화면에 어떤 인덱스를 보여줘야 할지 (from/to)
    - 지금 렌더링된 DOM을 어디에 놓아야 하는지 (offset)
    - 이미 만들어 둔 DOM을 재사용해야 하는지 (cache)

Virtual은 렌더링 엔진이 하나 더 붙은 구조라서, 인터페이스가 "상태+렌더 제어"까지 포함한다.

2. Virtual에 cache/from/to/update가 있는 이유

from, to

Virtual은 전체 슬라이드가 DOM에 없다. 그래서 "현재 렌더링된 구간"을 반드시 기억해야 한다.

  • from = 현재 DOM에 존재하는 첫 슬라이드 인덱스
  • to = 현재 DOM에 존재하는 마지막 슬라이드 인덱스

offset

Virtual은 일부만 DOM에 렌더링하기 때문에, 실제로는 "100번째 슬라이드부터 렌더링"해도 DOM상으로는 첫 번째처럼 보일 수 있다.

그래서 원래 위치처럼 보이도록 밀어주는 값이 필요하다.

가로면 left/right, 세로면 top을 사용한다. 실제로 React호환성 코드에서도 이 값을 style로 사용한다. react/virual.mjs

cache

Virtual은 계속 DOM을 만들었다가 지웠다를 반복한다. 매번 새로 만드는 비용을 줄이기 위해 한 번 만든 SlideEl을 저장해두고 재사용하는 방식으로 비용을 줄인다.

일반 슬라이드는 DOM에 계속 존재하기에 cache가 필요없다.

update

일반 슬라이드는 DOM을 추가하면 되지만, Virtual은 데이터만 바뀌면 DOM을 다시 맞춰 렌더링해야 한다.

그래서 virtual.update()는 아래와 같은 역할을 수행한다.

  • activeIndex 기준 from, to 재계산
  • DOM에 있어야 할 슬라이드만 남기고 교체
  • offset 재적용

3. addSlide의 부재

  • 일반 슬라이드: append / prepend / add / remove / removeAll
  • Virtual: append / prepend / remove / removeAll / update

Virtual에 addSlide가 없는 이유는 중간 삽입은 배열 수정으로 하고 update만 호출하면 되기 때문이다.

4. React/Vue에서 Virtual을 지양한다

Only for Core version (in React & Vue it should be done by modifying slides array/data/source)

React와 Vue는 렌더링 주도권이 자신에게 있다.

만약 Swiper가 DOM을 직접 append, prepend하면 React의 Virtual DOM과 충돌한다.

5. Virtual 최적화

virtual.css에서는 Virtual 슬라이드의 성능이나 스크롤이 깨지지 않도록 한다.

핵심부분을 살펴보자면

translateZ(0)

  • 해당 요소를 CPU 레이어로 올리는 역할이다. 스와이프 중 깜빡임이나 떨림을 방지한다.

backface-visibility: hidden

  • 3D 변환 중 뒷면 렌더링으로 발생할 수 있는 텍스트 깨짐을 방지한다.

Virtual에서 이 부분들이 중요한 이유는 DOM을 계속 갈아끼우는 데에 있다. 그렇게 갈아끼운 DOM의 위치를 transform으로 재조정한다.

만약 GPU 레이어로 올리지 않으면 페인트 비용과 시각적으로 깨짐이 발생한다. 이것은 브라우저 렌더링 순서와 관련이 있다.

브라우저 렌더링 순서

  1. style 계산
  2. Layout (reflow) - 위치/크기 계산
  3. Paint - 픽셀 비트맵으로 그림
  4. Composite - 레이어 합성해서 화면에 출력

여기서 깨짐(flicker, jitter, tearing)은 대부분 Paint 단계에서 발생한다.

Virtual에서 일어나는 일

Virtual은 스와이프할 때마다 기존 슬라이드 DOM 제거 -> 새로운 슬라이드 DOM 삽입 -> 위치 재조정이 일어난다. 즉, 한 프레임 안에서 DOM 트리 변경, 위치 변경, 스타일 변경이 한꺼번에 일어나는 것이다.

CPU 레이어만 쓴다면

DOM 제거/추가는 reflow, 위치 변경은 repaint라 하면 브라우더 렌더링 순서 중 Layout -> Paint가 자주 발생하게 된다. 프레임 안에 다 못 끝낸다면 중간 상태가 화면에 노출된다.

Paint는 이전 비트맵 위에 변경된 영역만 다시 그리는 누적 비트맵이라 Virtual에서 Layout -> Paint 가 원자적으로 처리되지 않으면 앞에서 말한 "깨짐"이 발생한다.

GPU 레이어를 쓰면 달라지는 것

GPU 레이어의 특징은 이렇다.

  • Layouy / Paint를 다시 안 함
  • 이미 그려진 비트맵을 CPU에서 위치만 이동
  • Composite 단계에서만 처리

그렇기에 요소를 별도의 합성 레이어로 분리함으로써 repaint가 아니라 composite단계에서 처리하는 것이다.

깨짐이 사라지는 이유도 프레임 단위로 레이어가 교체되기 때문에 중간 상태가 화면에 노출될 일이 없기 때문이다.

virtual에서 특히 중요한 이유

일반 슬라이드에선 DOM이 거의 고정되어 있고 위치 변화가 적다. 그렇기에 repaint 빈도가 낮은 반면, Virtual에서는 DOM을 자주 교체하여 offset이 계속 변경되므로 repaint 빈도가 높다.

CPU 레이어는 Virtual 슬라이드에서 일어나는 Paint를 감당할 수 없기에 GPU 레이어로 올린 것이다.

다음 챕터

Virtual 슬라이드를 알아보니 브라우저 내부 동작과 관련있다는 것이 신기했다. 다음은 React에서 Swiper가 어떻게 돌아가는지 알아볼 예정이다.

profile
Frontend Developer

0개의 댓글