개요
오늘은 사소하게 보일 수 있지만, 제가 항상 개선하고 싶었던 애니메이션이에요. 바로 GSAP을 이용한 부드러운 움직임의 인디케이터 애니메이션입니다.

일단 맥락의 이해를 돕기위해서 다음과 같은 순서로 설명을 하도록 해볼게요
- 기존 코드 구성
- 변경이 필요한 부분
- GSAP 라이브러리 적용
- 결과
기존 코드 구성
기존 코드가 구성된 방식은 태그리스트를 props로 받아서 map함수를 활용해서 div태그로 렌더링 하고 있었어요. 그리고 쿼리파라미터를 받아서 일치하는 태그가 있다면
isSelected
가 활성화되요. 그러면 그 조건에 따라서 적용되는 스타일이 달라지도록 적용했었죠. 기존 코드 방식

일반적으로 선택된 모습을 보여주기 위해서 이러한 방식을 사용하실거에요. 하지만 GSAP애니메이션으로 매끄럽게 이동하는 애니메이션을 적용하기 위해서는 구조를 약간 변경해주셔야되요.
구조 변경
기존 코드가 조건에 따라 적용되는 스타일이 다르게 구현이 되어있었다면은, 이번 블로그에 적용할 애니메이션을 위해서는
선택된 모습의 스타일의 div태그가 위에 떠다닐 수있게 따로 분리
해야되요. 그리고 해당 스타일 div태그
가 떠다닐 반경을 지정해주어야 하죠. 구조변경 시각적으로 이해하기

그림으로 보시니까 좀 더 이해가 되시죠? 기존에는 해당 태그 스타일링을 다르게 적용하는 구조였다면, GSAP애니메이션을 위해서는 따로 태그를 분리해야지 좀 더 깔끔하게 애니메이션을 적용할 수 있어요. 그럼 DOM구조를 변경하는 것은 완료가 되었고 이제 GSAP을 적용해볼 차례에요.
GSAP 애니메이션 적용하기
GSAP을 처음 사용하시는 분도 있으실 수 있으니, 기본 설치하는 방법은 아래 글에서 참고해주세요 🙂
GSAP 설치 방법과 기본 문법
GSAP을 설치하셨으면, 파일 최상단에
gsap
을 import
해주세요. 그리고 우리가 위에서 DOM구조를 변경했었잖아요? 이 두 요소를 DOM API가 추적하기 쉽게 스타일 태그에는
indicator
, 그리고 이동할 반경이 되는 태그 목록에는 tabs-row
라는 클래스를 추가하도록 할게요. 클래스 추가 indicator, tabs-row

그럼 아래와 같은 이벤트 핸들러 함수를 작성할 수 있을거에요.
클릭시 실행될 이벤트 핸들러 함수
// 클릭시 실행될 이벤트 핸들러 정의 const updateIndicator = (target: Element) => { const indicator = document.querySelector('.indicator'); const tabRow = document.querySelector('.tabs-row'); if (!indicator || !tabRow) return; const tagetBounds = target.getBoundingClientRect(); const rowBounds = tabRow.getBoundingClientRect(); const offset = tagetBounds.top - rowBounds.top; gsap.to(indicator, { y: offset, duration: 0.4, ease: 'back.out(1)' }); }; // Link 컴포넌트에 updateIndicator 함수 연결 <Link href={tag.name === '전체' ? '/' : `?tag=${encodeURIComponent(tag.name)}`} key={tag.name} onClick={() => { handleTagClick(tag.name); updateIndicator(document.getElementById(tag.name) as Element); }} prefetch={true} scroll={false} >
로직을 설명하자면,
- 클릭시에 DOM API를 사용해서
indicator
와tabRow
를 찾게 되요.
- 그리고 각각의 요소의
getBoundingClientRect
함수로 위치를 사용할 수 있게 정의해요
- 그리고 각 요소의
top
을 계산해서 이동할 거리를 나타내는offset
을 정의해요
- 그리고 GSAP을 사용해서 이동 애니메이션을 정의해요
- 이동애니메이션에는 to함수를 사용했어요.
to함수
는정의된 자리로 이동해
라는 뜻이죠. - 가로 위치는 변하지 않기 때문에 세로 위치
y
에 변하는 정도인offset
을 할당해요 duration
은 애니메이션이 총 걸리는 시간을 정할 수 있어요. 직접 사용해보시고 보시기에 자연스럽다하는 시간을 정의해주면 될거 같아요.- ease는 애니메이션이 이동할 때 어떤 움직임으로 이동할 지를 정할 수 있어요. 여기서 사용된
‘back.out(1)’
은 지정된 위치를 살짝 벗어났다가 되돌아 오는 특징 때문에, 자석에 끌려가는 것 같은 느낌을 줘요.(1)
에 정의된 숫자는벗어나는 정도
를 정할 수 있는데, 저는 1이 자연스러워서1
로 선택했어요.
결론
GSAP을 사용해서 작지만 좀 더 세련된 느낌의 이동 애니메이션을 구현할 수 있었어요. 이런 작은 디테일이 사용자가 사용하는 맛과 재미를 더해주는 것 같아요.
결과물

여러분의 프로젝트에서도 한 번 적용해보고 싶으신 분은 한 번 시도해보시길 추천드려요. 뭔가 다된 파스타에 후추를 뿌리듯 풍미를 더해주는 거 같아요. 물론 GSAP은 이것 말고도 더 많은 애니메이션을 테스트 해볼 수가 있는데, 공식 문서가 너무 잘 만들어서 아래 문서 링크를 참고해서 여러가지 시도해보시면 좋을 것 같아요.
공식 문서 easing 설명
오늘도 글을 읽어주셔서 감사하고, 웹개발에 필요한 모든 지식을 알기 쉽게 전달하기 위해서 노력해볼게요! 다음에 또 봐요!