왜 만들었나
애플 키노트 같은 sticky 안무 스크롤 진행에 따라 텍스트가 scale/blur/opacity로 변화 를 framer-motion 없이 만들고 싶었습니다. 핵심은 "요소 기준 스크롤 진행도(0~1)" 한 값이고, 그것만 안정적으로 노출하면 나머지는 inline style로 풀린다는 직관에서 출발했습니다.
두 가지 모드
enter-exit: 요소가 viewport 하단에 닿을 때 0, 상단을 벗어날 때 1. 일반적인 등장 효과용.
sticky: ref가 sticky 자식이고 부모가 wrapper일 때, 부모 기준 진행도. 풀스크린 sticky 시퀀스용.
안정화 처리
Next.js의 client navigation으로 페이지를 떠났다 돌아왔을 때 sticky가 멈춰버리는 문제를 겪었습니다. 원인은 mount 시 한 번만 측정하는데 그 시점에 layout이 안정화되지 않은 경우였습니다. 해결로 다음을 모두 적용했습니다.
mount 직후 즉시 측정 + double RAF로 한 번 더 (폰트이미지 로드 후 보정)
ResizeObserver로 element와 부모 크기 변화 시 재측정
visibilitychange / pageshow 이벤트로 bfcache 복원 시 재측정
mapRange 헬퍼
0~1 progress를 임의의 출력 범위로 매핑. mapRange(progress, 0.05, 0.45, 0, 1) 같이 쓰면 "5%에서 시작해 45%에서 끝나는 구간 동안 01로 변화"가 한 줄로 표현됩니다.
언제 좋은가
framer-motion보다 훨씬 가벼움 번들 크기 0 추가
RAF throttle + ResizeObserver로 client navigation 케이스에 강함
mapRange와 짝지어 inline style만으로 어떤 안무도 표현 가능
언제 별로인가
여러 keyframe물리 기반 같은 복잡한 시퀀스는 framer-motion이 적합
sticky 모드는 ref를 반드시 sticky 자식에 붙여야 함 wrapper에 붙이면 진행도가 페이지 전체 기준이 되어 의도와 달라짐