이전글에서는 swiper 라이브러리에 구현되어 있는 슬라이드 종류와 일반 슬라이드 구현의 특징에 대해 알아보았다.
이번에는 Virtual 슬라이드의 개념과 쓰임에 대해 알아보려 한다.
Virtual 슬라이드의 메소드 인터페이스는 virtual.d.ts에서 볼 수 있다.
Virtual 슬라이드에서는 일반 슬라이드 메소드인 appendSlide, prependSlide, removeSlide, removeAllSlides외에도 from, to, cache, slides, update를 가진다.
이 메소드들은 왜 더 필요할까? 그것은 DOM을 다루는 방식에 있다.
virtual.slides배열 - 지금 화면에 어떤 인덱스를 보여줘야 할지 (from/to)
- 지금 렌더링된 DOM을 어디에 놓아야 하는지 (offset)
- 이미 만들어 둔 DOM을 재사용해야 하는지 (cache)
Virtual은 렌더링 엔진이 하나 더 붙은 구조라서, 인터페이스가 "상태+렌더 제어"까지 포함한다.
Virtual은 전체 슬라이드가 DOM에 없다. 그래서 "현재 렌더링된 구간"을 반드시 기억해야 한다.
Virtual은 일부만 DOM에 렌더링하기 때문에, 실제로는 "100번째 슬라이드부터 렌더링"해도 DOM상으로는 첫 번째처럼 보일 수 있다.
그래서 원래 위치처럼 보이도록 밀어주는 값이 필요하다.
가로면 left/right, 세로면 top을 사용한다. 실제로 React호환성 코드에서도 이 값을 style로 사용한다. react/virual.mjs
Virtual은 계속 DOM을 만들었다가 지웠다를 반복한다. 매번 새로 만드는 비용을 줄이기 위해 한 번 만든 SlideEl을 저장해두고 재사용하는 방식으로 비용을 줄인다.
일반 슬라이드는 DOM에 계속 존재하기에 cache가 필요없다.
일반 슬라이드는 DOM을 추가하면 되지만, Virtual은 데이터만 바뀌면 DOM을 다시 맞춰 렌더링해야 한다.
그래서 virtual.update()는 아래와 같은 역할을 수행한다.
from, to 재계산Virtual에 addSlide가 없는 이유는 중간 삽입은 배열 수정으로 하고 update만 호출하면 되기 때문이다.
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과 충돌한다.
virtual.css에서는 Virtual 슬라이드의 성능이나 스크롤이 깨지지 않도록 한다.
핵심부분을 살펴보자면
translateZ(0)
backface-visibility: hidden
Virtual에서 이 부분들이 중요한 이유는 DOM을 계속 갈아끼우는 데에 있다. 그렇게 갈아끼운 DOM의 위치를 transform으로 재조정한다.
만약 GPU 레이어로 올리지 않으면 페인트 비용과 시각적으로 깨짐이 발생한다. 이것은 브라우저 렌더링 순서와 관련이 있다.
여기서 깨짐(flicker, jitter, tearing)은 대부분 Paint 단계에서 발생한다.
Virtual은 스와이프할 때마다 기존 슬라이드 DOM 제거 -> 새로운 슬라이드 DOM 삽입 -> 위치 재조정이 일어난다. 즉, 한 프레임 안에서 DOM 트리 변경, 위치 변경, 스타일 변경이 한꺼번에 일어나는 것이다.
DOM 제거/추가는 reflow, 위치 변경은 repaint라 하면 브라우더 렌더링 순서 중 Layout -> Paint가 자주 발생하게 된다. 프레임 안에 다 못 끝낸다면 중간 상태가 화면에 노출된다.
Paint는 이전 비트맵 위에 변경된 영역만 다시 그리는 누적 비트맵이라 Virtual에서 Layout -> Paint 가 원자적으로 처리되지 않으면 앞에서 말한 "깨짐"이 발생한다.
GPU 레이어의 특징은 이렇다.
그렇기에 요소를 별도의 합성 레이어로 분리함으로써 repaint가 아니라 composite단계에서 처리하는 것이다.
깨짐이 사라지는 이유도 프레임 단위로 레이어가 교체되기 때문에 중간 상태가 화면에 노출될 일이 없기 때문이다.
일반 슬라이드에선 DOM이 거의 고정되어 있고 위치 변화가 적다. 그렇기에 repaint 빈도가 낮은 반면, Virtual에서는 DOM을 자주 교체하여 offset이 계속 변경되므로 repaint 빈도가 높다.
CPU 레이어는 Virtual 슬라이드에서 일어나는 Paint를 감당할 수 없기에 GPU 레이어로 올린 것이다.
Virtual 슬라이드를 알아보니 브라우저 내부 동작과 관련있다는 것이 신기했다. 다음은 React에서 Swiper가 어떻게 돌아가는지 알아볼 예정이다.