30.GSAP 플러그인 종류와 기초 애니메이션
GSAP의 핵심 기능과 주요 플러그인을 배우고, 실전 예제를 직접 작성해본다.
코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.
구문
GSAP(GreenSock Animation Platform)은 웹에서 가장 많이 쓰이는 JavaScript 애니메이션 라이브러리이다.
CSS나 순수 JavaScript보다 탁월한 퍼포먼스를 발휘할 수 있도록 최적화된 애니메이션 전용 라이브러리이며, 12만 개 이상의 사이트에서 사용되고 있다.
2024년 10월 Webflow가 GSAP을 인수했다. 2025년 4월 30일부터 GSAP 3.13 버전과 함께 모든 플러그인이 100% 무료로 전환되었다. 이전에 유료였던 SplitText, MorphSVG 등도 상업 프로젝트에서 무료로 사용할 수 있다.
0.1. 참조링크
1. GSAP 설치와 기본 세팅
1.1. CDN으로 불러오기
가장 간단한 방법은 HTML 파일에 CDN 링크를 추가하는 것이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>GSAP 시작하기</title>
</head>
<body>
<div class="box">안녕 GSAP!</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="app.js"></script>
</body>
</html>
| 줄 | 설명 |
|---|---|
| 8 | 애니메이션을 적용할 대상 element를 만든다 |
| 9 | GSAP 라이브러리를 CDN에서 불러온다 |
| 10 | 우리가 작성할 JavaScript 파일을 연결한다 |
CDN 방식은 별도 설치 없이 바로 사용할 수 있어 학습 단계에서 편리하다.
1.2. npm으로 설치하기
React나 Vite 프로젝트에서는 npm으로 설치한다. GSAP 3.13부터 모든 플러그인이 공개 npm 저장소에 포함되어, 별도의 token이나 비공개 저장소 설정이 필요 없다.
npm install gsap
import gsap from "gsap";
| 줄 | 설명 |
|---|---|
| 1 | 설치한 gsap package를 불러온다 |
React 프로젝트에서는 @gsap/react 패키지도 함께 설치하면 useGSAP() hook을 사용할 수 있다. npm install gsap @gsap/react
2. Tween — 핵심 Method 4가지
Tween은 GSAP의 기본 애니메이션 단위이다. 대상(target), 지속 시간(duration), 속성을 입력하면 애니메이션을 완성해준다.
2.1. gsap.to() — "여기로 가라"
현재 상태에서 지정한 값으로 변화시킨다. 가장 많이 쓰는 method이다. duration 미지정 시 기본값은 0.5초이다. 실행화면
gsap.to(".box", {
x: 200,
duration: 1,
});
| 줄 | 설명 |
|---|---|
| 1 | .box class를 가진 요소를 선택한다 |
| 2 | x축(가로)으로 200px 이동한다 |
| 3 | 1초 동안 애니메이션을 실행한다 |
2.2. gsap.from() — "여기서 출발하라"
지정한 값에서 현재 상태로 변화시킨다. 등장 효과에 자주 쓴다.
gsap.from(".box", {
y: -100,
opacity: 0,
duration: 1,
});
| 줄 | 설명 |
|---|---|
| 1 | .box 요소를 선택한다 |
| 2 | y축(세로) -100px 위치에서 출발한다 |
| 3 | opacity 0(완전 투명)에서 시작한다 |
| 4 | 1초 동안 실행한다 |
2.3. gsap.fromTo() — "여기서 저기까지"
시작 값과 끝 값을 둘 다 직접 지정한다.
gsap.fromTo(".box",
{ x: 0, opacity: 0 },
{ x: 300, opacity: 1, duration: 1 }
);
| 줄 | 설명 |
|---|---|
| 2 | 첫 번째 object가 시작 값이다 |
| 3 | 두 번째 object가 끝 값이다. duration도 여기에 넣는다 |
2.4. 2.4 gsap.set() — "즉시 바꿔라"
애니메이션 없이 즉시 속성을 변경한다. 초기값 설정에 쓴다.
gsap.set(".box", {
x: 100,
opacity: 0.5,
});
| 줄 | 설명 |
|---|---|
| 1 | .box 요소를 선택한다 |
| 2 | 즉시 x축 100px 위치로 이동한다 |
| 3 | 즉시 opacity를 0.5(반투명)로 설정한다 |
2.5. Tween 실전 예제 — 이동 + 회전 + 색상
여러 속성을 동시에 애니메이션할 수 있다. 실행화면
gsap.to(".box1", {
duration: 3,
x: 200,
opacity: 0.2,
ease: "steps(10)",
delay: 2,
});
gsap.to(".box2", {
duration: 3,
x: 200,
rotate: 720,
scale: 1.3,
});
gsap.to(".box3", {
duration: 3,
x: 200,
ease: "elastic",
backgroundColor: "red",
width: 300,
fontSize: 60,
});
| 줄 | 설명 |
|---|---|
| 1~7 | .box1을 3초간 이동하며, 10단계로 끊어지는 ease를 적용한다. 2초 후 시작한다 |
| 8~13 | .box2를 이동하면서 720도 회전하고 1.3배로 확대한다 |
| 14~22 | .box3를 이동하면서 elastic ease, 배경색 변경, 크기와 글자 크기를 동시에 바꾼다 |
from()으로 바꾸면 애니메이션이 반전되어 실행된다. 지정한 값에서 원래 값으로 돌아오는 방식이다.
3. 자주 쓰는 애니메이션 속성
아래 속성들은 to(), from(), fromTo() 안에서 자유롭게 조합할 수 있다.
| 속성 | 설명 | 예시 값 |
|---|---|---|
x | 가로 이동 | 100, -50 |
y | 세로 이동 | 200, -100 |
rotation | 회전(도) | 360, -90 |
scale | 크기 배율 | 2(2배), 0.5(절반) |
opacity | 투명도 | 0~1 |
duration | 지속 시간(초) | 1, 0.5, 2 |
delay | 지연 시간(초) | 0.5, 1 |
repeat | 반복 횟수 | 3, -1(무한) |
repeatDelay | 반복 전 지연 시간 | 0.5, 1 |
yoyo | 왕복 여부 | true, false |
ease | 가속도 곡선 | "power2.out", "bounce.out" |
stagger | 여러 요소 시간차 | 0.2, 0.5 |
onComplete | 완료 시 callback | () => console.log("끝") |
onUpdate | 매 프레임 callback | () => console.log("진행중") |
4. Ease — 움직임에 생동감 주기
Ease는 애니메이션의 속도 변화 곡선이다. 로봇처럼 딱딱한 움직임 대신, 자연스러운 느낌을 준다.
4.1. 주요 Ease 종류
gsap.to(".box", { x: 300, ease: "power1.out", duration: 1 });
| 줄 | 설명 |
|---|---|
| 1 | ease 속성에 원하는 이름을 string으로 넣는다 |
| Ease 이름 | 느낌 |
|---|---|
"none" | 일정한 속도(기본) |
"power1" ~ "power4" | 숫자가 클수록 강한 가감속 |
"back" | 목표를 살짝 넘겼다 돌아옴 |
"bounce" | 통통 튀는 효과 |
"elastic" | 고무줄처럼 흔들림 |
"circ" | 원형 곡선 가감속 |
"expo" | 지수 곡선 가감속 |
"sine" | 사인 곡선 가감속 |
"steps(n)" | n단계로 끊어지는 효과 |
GSAP 공식 사이트의 Ease Visualizer에서 모든 ease를 눈으로 비교할 수 있다. https://gsap.com/docs/v3/Eases
4.2. Ease 비교 예제
여러 ease를 한 번에 비교할 수 있는 예제이다. 각 요소가 동시에 출발하여 ease별 차이를 눈으로 확인할 수 있다. 실행화면
gsap.to(".box1", { x: 600, ease: "none", duration: 5 });
gsap.to(".box2", { x: 600, ease: "power1", duration: 5 });
gsap.to(".box3", { x: 600, ease: "power2", duration: 5 });
gsap.to(".box4", { x: 600, ease: "power3", duration: 5 });
gsap.to(".box5", { x: 600, ease: "power4", duration: 5 });
gsap.to(".box6", { x: 600, ease: "back", duration: 5 });
gsap.to(".box7", { x: 600, ease: "elastic", duration: 5 });
gsap.to(".box8", { x: 600, ease: "bounce", duration: 5 });
| 줄 | 설명 |
|---|---|
| 1 | none — 일정 속도로 이동한다 |
| 2~5 | power1~power4 — 숫자가 커질수록 급격하게 감속한다 |
| 6 | back — 살짝 넘겼다 돌아온다 |
| 7 | elastic — 고무줄처럼 흔들린다 |
| 8 | bounce — 바닥에서 통통 튄다 |
5. Timeline — 여러 애니메이션을 순서대로
gsap.timeline()을 사용하면 여러 애니메이션을 순서대로 또는 동시에 실행할 수 있다.
5.1. 순서대로 실행하기
let tl = gsap.timeline();
tl.to(".one", { duration: 2, x: 500 })
.to(".two", { duration: 3, x: 500 }, 1)
.to(".three", { duration: 1, x: 500 }, "<")
.to(".four", { duration: 1, x: 500 }, "<0.5");
| 줄 | 설명 |
|---|---|
| 1 | timeline 객체를 생성한다 |
| 3 | .one이 2초 동안 x축으로 500px 이동한다 |
| 4 | 절대값 1 — timeline 시작 후 1초 시점에 실행한다 |
| 5 | "<" — 이전 tween의 시작 시점과 동시에 실행한다 |
| 6 | "<0.5" — 이전 tween의 시작 시점보다 0.5초 뒤에 실행한다 |
5.2. Position Parameter 정리
| 표기 | 의미 |
|---|---|
"-=0.5" | 이전 애니메이션 종료 0.5초 전에 시작 (오버랩) |
"+=0.3" | 이전 애니메이션 종료 0.3초 후에 시작 (갭) |
"<" | 이전 tween의 시작 시점과 동시 |
">" | 이전 tween의 종료 시점과 동시 |
"<0.5" | 이전 tween 시작 시점 + 0.5초 |
3 | timeline 시작 기준 3초 시점 (절대값) |
5.3. defaults로 공통 설정하기
defaults 속성을 사용하면 모든 하위 tween에 공통 값을 상속할 수 있다.
실행화면
let tl = gsap.timeline({ defaults: { duration: 1 } });
tl.from("h1", { y: -50, opacity: 0 })
.from("p", { y: -50, opacity: 0 }, "-=0.5")
.from("a", { y: -50, opacity: 0 }, "+=1")
.from("img", { y: 200, opacity: 0 }, "3");
| 줄 | 설명 |
|---|---|
| 1 | 모든 하위 tween에 duration: 1을 기본값으로 설정한다 |
| 3 | h1이 위에서 내려오며 나타난다 |
| 4 | "-=0.5" — 이전 tween 종료 0.5초 전에 시작한다 (오버랩) |
| 5 | "+=1" — 이전 tween 종료 1초 후에 시작한다 (갭) |
| 6 | "3" — timeline 시작 3초 후에 시작한다 (절대값) |
5.4.애니메이션 핸들링
tween을 변수에 저장하면 play(), pause(), reverse() 등으로 제어할 수 있다.
실행화면
const tween = gsap.to(".box1", {
duration: 8,
x: 400,
width: 400,
paused: true,
});
document.querySelector("#play").onclick = () => tween.play();
document.querySelector("#pause").onclick = () => tween.pause();
document.querySelector("#resume").onclick = () => tween.resume();
document.querySelector("#reverse").onclick = () => tween.reverse();
document.querySelector("#restart").onclick = () => tween.restart();
| 줄 | 설명 |
|---|---|
| 5 | paused: true — 생성 시 자동 재생하지 않고 대기한다 |
| 8 | play() — 재생한다 |
| 9 | pause() — 일시정지한다 |
| 10 | resume() — 멈춘 곳에서 이어 재생한다 |
| 11 | reverse() — 반대로 재생한다 |
| 12 | restart() — 처음부터 다시 재생한다 |
6. GSAP Plugin 전체 목록
GSAP의 진짜 힘은 Plugin에 있다. Plugin은 기본 기능을 확장하는 추가 모듈이다.
2024년 10월 Webflow가 GreenSock을 인수했다. 이후 2025년 4월 30일 GSAP 3.13 릴리스와 함께 모든 Plugin이 100% 무료로 전환되었다. 이전에 Club GSAP 유료 멤버십이 필요했던 SplitText, MorphSVG, ScrollSmoother 등도 이제 누구나 상업 프로젝트에서 무료로 사용할 수 있다.
| Plugin | 분류 | 설명 |
|---|---|---|
| ScrollTrigger | 스크롤 | 스크롤 위치에 따라 애니메이션을 실행한다 |
| ScrollSmoother | 스크롤 | 부드러운 관성 스크롤 효과를 만든다. ScrollTrigger 기반이다 |
| ScrollToPlugin | 스크롤 | 특정 위치로 부드럽게 스크롤한다 |
| Observer | 스크롤 | 스크롤, 터치, 포인터 등 다양한 입력을 감지한다 |
| MorphSVGPlugin | SVG | SVG 도형을 다른 도형으로 부드럽게 변신시킨다 |
| DrawSVGPlugin | SVG | SVG 선이 그려지는 애니메이션을 만든다 |
| MotionPathPlugin | SVG | SVG 경로를 따라 요소를 이동시킨다 |
| SplitText | 텍스트 | 텍스트를 글자/단어/줄 단위로 분리하여 애니메이션한다. 3.13에서 완전히 재작성되었다 |
| TextPlugin | 텍스트 | 텍스트를 한 글자씩 타이핑하는 효과를 만든다 |
| ScrambleTextPlugin | 텍스트 | 텍스트가 무작위 문자로 변환되며 나타나는 효과를 만든다 |
| Draggable | 상호작용·물리 | 요소를 마우스/터치로 드래그할 수 있게 한다 |
| InertiaPlugin | 상호작용·물리 | 드래그 후 관성으로 미끄러지는 효과를 만든다 |
| Physics2DPlugin | 상호작용·물리 | 중력, 속도, 마찰 등 2D 물리 시뮬레이션을 적용한다 |
| PhysicsPropsPlugin | 상호작용·물리 | 개별 속성에 물리 효과를 적용한다 |
| Flip | Ease·유틸리티 | layout 변화를 부드러운 애니메이션으로 전환한다 |
| CustomEase | Ease·유틸리티 | ease 곡선을 직접 디자인할 수 있다 |
| CustomBounce | Ease·유틸리티 | bounce 효과를 세밀하게 조절할 수 있다 |
| CustomWiggle | Ease·유틸리티 | 흔들림 효과를 세밀하게 조절할 수 있다 |
| EasePack | Ease·유틸리티 | 추가 ease 함수 모음이다 |
| PixiPlugin | 렌더러·개발 | PixiJS renderer 객체를 애니메이션한다 |
| EaselPlugin | 렌더러·개발 | Canvas 기반 EaselJS 객체를 애니메이션한다 |
| CSSRulePlugin | 렌더러·개발 | CSS rule 자체를 직접 애니메이션한다 |
| GSDevTools | 렌더러·개발 | 애니메이션을 debugging할 수 있는 컨트롤 패널이다 |
7. ScrollTrigger — 스크롤 연동 애니메이션
스크롤 위치에 따라 애니메이션을 실행하는 Plugin이다. 최신 웹사이트의 스크롤 연동 효과는 대부분 이것으로 만든다.
7.1. 7.1 Plugin 등록
Plugin은 사용 전에 반드시 register해야 한다.
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js"></script>
<script>
gsap.registerPlugin(ScrollTrigger);
</script>
| 줄 | 설명 |
|---|---|
| 1 | GSAP core를 불러온다 |
| 2 | ScrollTrigger Plugin 파일을 추가로 불러온다 |
| 4 | GSAP에 Plugin을 등록한다. 이 줄이 없으면 작동하지 않는다 |
7.2. 주요 속성
| 속성 | 설명 |
|---|---|
trigger | 스크롤 감지 기준이 되는 요소이다 |
start | 애니메이션 시작 지점이다. 형식: "요소위치 viewport위치" |
end | 애니메이션 종료 지점이다. 형식: "요소위치 viewport위치" |
scrub | true이면 스크롤 위치에 따라 애니메이션 진행률이 연동된다 |
pin | true이면 해당 요소를 스크롤 동안 고정한다 |
markers | true이면 개발용 시각 표시를 화면에 보여준다 (배포 시 제거) |
toggleActions | 진입/이탈 시 동작을 지정한다. 기본값: "play none none none" |
toggleClass | 트리거 구간에서 class를 추가/제거한다 |
7.3. 기본 사용법
gsap.to(".box", {
x: 500,
rotation: 360,
borderRadius: 100,
duration: 2,
scrollTrigger: {
trigger: ".box",
start: "top 80%",
end: "bottom 20%",
toggleActions: "play none reverse none",
markers: true,
},
});
| 줄 | 설명 |
|---|---|
| 6 | scrollTrigger 옵션 object를 추가한다 |
| 7 | .box 요소를 스크롤 감지 기준으로 설정한다 |
| 8 | 요소 상단이 viewport 80% 위치에 올 때 시작한다 |
| 9 | 요소 하단이 viewport 20% 위치에 올 때 끝난다 |
| 10 | 진입 시 재생, 되돌아올 때 역재생한다 |
| 11 | 개발용 marker를 표시한다 |
7.4. scrub — 스크롤 연동
scrub: true로 설정하면 스크롤 위치에 따라 애니메이션 진행률이 1:1로 연동된다.
실행화면
gsap.to(".box", {
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: ".box",
start: "top 50%",
end: "bottom 20%",
scrub: true,
},
});
| 줄 | 설명 |
|---|---|
| 8 | scrub: true — 스크롤을 내리면 애니메이션이 진행되고, 올리면 되돌아간다 |
scrub에 숫자를 넣으면 부드러운 지연 효과가 추가된다. scrub: 1은 1초의 지연을 주며 더 자연스럽다.
7.5. pin — 요소 고정
pin: true로 설정하면 스크롤 동안 해당 요소가 화면에 고정된다.
실행화면
gsap.to(".box", {
x: 500,
rotation: 360,
scrollTrigger: {
trigger: ".box",
start: "top 50%",
end: "bottom 200px",
scrub: true,
pin: true,
},
});
| 줄 | 설명 |
|---|---|
| 9 | pin: true — 스크롤하는 동안 .box가 화면에 고정된다 |
7.6. 7.6 ScrollTrigger.create() — timeline과 분리하기
ScrollTrigger.create()를 사용하면 timeline과 scroll 설정을 분리하여 관리할 수 있다.
실행화면
const ani = gsap.timeline();
ani
.to(".box", { rotation: 450, scale: 0, borderRadius: 200 })
.to(".box", { rotation: 360 * 5, scale: 1, borderRadius: 20 });
ScrollTrigger.create({
animation: ani,
trigger: ".sec1",
start: "top top",
end: "+=2000",
scrub: true,
pin: true,
anticipatePin: 1,
markers: true,
});
| 줄 | 설명 |
|---|---|
| 1~4 | timeline 애니메이션을 먼저 정의한다 |
| 6 | ScrollTrigger.create()로 scroll 설정을 별도로 만든다 |
| 7 | animation 속성에 timeline을 연결한다 |
| 10 | "+=2000" — 시작점에서 2000px 스크롤 후 종료한다 |
| 13 | anticipatePin: 1 — pin 시작 1초 전 미리 시작하여 끊김을 방지한다 |
7.7. stagger — 순차 나타나기
여러 요소에 시간차를 주어 순차적으로 나타나게 한다. 실행화면
const ani = gsap.timeline();
ani.from(".sec3 .box", {
y: -300,
scale: 0.5,
autoAlpha: 0,
ease: "back.out(4)",
stagger: {
amount: 3,
from: "random",
},
});
ScrollTrigger.create({
animation: ani,
trigger: ".sec3",
start: "top top",
end: "+=2000",
scrub: true,
pin: true,
});
| 줄 | 설명 |
|---|---|
| 5 | autoAlpha: 0 — opacity와 visibility를 동시에 제어한다 |
| 7~10 | stagger.amount: 3 — 총 3초 동안 무작위 순서로 등장한다 |
7.8. callback 함수
ScrollTrigger 구간에서 특정 시점에 함수를 실행할 수 있다. 실행화면
gsap.to(".box", {
x: 500,
scrollTrigger: {
trigger: ".box",
start: "top center",
end: "bottom 20%",
scrub: true,
onEnter: () => console.log("진입"),
onLeave: () => console.log("이탈"),
onEnterBack: () => console.log("재진입"),
onLeaveBack: () => console.log("재이탈"),
onUpdate: (self) => {
console.log("진행률:", self.progress.toFixed(3));
},
},
});
| 줄 | 설명 |
|---|---|
| 8 | onEnter — 위에서 아래로 스크롤하여 시작점을 지날 때 |
| 9 | onLeave — 끝점을 벗어날 때 |
| 10 | onEnterBack — 아래에서 위로 되돌아올 때 |
| 11 | onLeaveBack — 시작점을 다시 벗어날 때 |
| 12~14 | onUpdate — 스크롤할 때마다 진행률(0~1)을 출력한다 |
8. SplitText — 텍스트 분해 애니메이션
텍스트를 글자, 단어, 줄 단위로 분리하여 각각 애니메이션을 적용한다. GSAP 3.13에서 완전히 재작성되어 파일 크기가 50% 줄었고, screen reader 접근성 지원이 추가되었다.
8.1. Plugin 등록
<h2 class="title">안녕하세요, GSAP 세계에 오신 것을 환영합니다!</h2>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/SplitText.min.js"></script>
8.2. 글자 단위 등장 효과
gsap.registerPlugin(SplitText);
const split = SplitText.create(".title", {
type: "chars, words",
});
gsap.from(split.chars, {
y: 50,
opacity: 0,
stagger: 0.05,
duration: 0.6,
ease: "back.out",
});
| 줄 | 설명 |
|---|---|
| 3~5 | .title 텍스트를 글자(chars)와 단어(words) 단위로 분리한다 |
| 7 | 분리된 개별 글자에 애니메이션을 적용한다 |
| 10 | 글자마다 0.05초 간격으로 순차 등장한다 |
SplitText 3.13 버전은 자동으로 aria-label을 추가하여 screen reader 접근성을 지원한다.
9. TextPlugin — 타이핑 효과
텍스트를 한 글자씩 나타나게 하는 타이핑 효과를 만든다. SplitText와 달리 기존 텍스트를 새 텍스트로 교체하는 방식이다. 실행화면
<h2 class="msg"></h2>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/TextPlugin.min.js"></script>
| 줄 | 설명 |
|---|---|
| 1 | 타이핑 효과가 표시될 빈 요소를 만든다 |
| 2 | GSAP core를 불러온다 |
| 3 | TextPlugin 파일을 추가로 불러온다 |
10. Draggable — 드래그 앤 드롭
요소를 마우스나 터치로 자유롭게 드래그할 수 있게 만든다. 실행화면
<div class="drag-me">나를 드래그해봐!</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/Draggable.min.js"></script>
| 줄 | 설명 |
|---|---|
| 1 | 드래그 대상이 될 요소를 만든다 |
| 2 | GSAP core를 불러온다 |
| 3 | Draggable Plugin 파일을 추가로 불러온다 |
11. MorphSVG — SVG 도형 변신
하나의 SVG 도형을 다른 도형으로 부드럽게 변화시킨다. 이전에는 유료였으나 현재 무료이다. 실행화면
<svg viewBox="0 0 200 200">
<circle id="shape" cx="100" cy="100" r="50" fill="#0ae448" />
</svg>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/MorphSVGPlugin.min.js"></script>
| 줄 | 설명 |
|---|---|
| 1~3 | 변신 대상이 될 SVG circle을 만든다 |
| 4 | GSAP core를 불러온다 |
| 5 | MorphSVGPlugin 파일을 추가로 불러온다 |
12. 가로방향 스크롤
ScrollTrigger를 활용하면 세로 스크롤로 가로 이동을 구현할 수 있다.
12.1. 기본 가로 스크롤
<main class="cont">
<section class="item" id="sec1"><h2>1</h2></section>
<section class="item" id="sec2"><h2>2</h2></section>
<section class="item" id="sec3"><h2>3</h2></section>
<section class="item" id="sec4"><h2>4</h2></section>
<section class="item" id="sec5"><h2>5</h2></section>
</main>
| 줄 | 설명 |
|---|---|
| 1 | 모든 section을 감싸는 container이다 |
| 2~6 | 가로로 나열될 각 섹션이다 |
12.2. 가로 + 세로 혼합 스크롤
일부 구간만 가로 스크롤로 전환하고, 나머지는 일반 세로 스크롤을 유지할 수 있다. 실행화면
<main class="cont">
<section class="item" id="sec1"><h2>1</h2></section>
<section class="item" id="sec2"><h2>2</h2></section>
<div class="horizontal">
<section class="item" id="sec3"><h2>3</h2></section>
<section class="item" id="sec4"><h2>4</h2></section>
<section class="item" id="sec5"><h2>5</h2></section>
</div>
<section class="item" id="sec6"><h2>6</h2></section>
<section class="item" id="sec7"><h2>7</h2></section>
</main>
| 줄 | 설명 |
|---|---|
| 4~8 | .horizontal로 감싼 섹션만 가로 스크롤 대상이 된다 |
13. 실전 종합 예제 — 스크롤에 반응하는 카드 갤러리
지금까지 배운 내용을 조합하여, 스크롤하면 카드가 차례로 나타나는 갤러리를 만들어 본다. 실행화면
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>카드 갤러리</title>
</head>
<body>
<section class="hero">
<h1>스크롤을 내려보세요</h1>
</section>
<section class="gallery">
<div class="card">카드 1</div>
<div class="card">카드 2</div>
<div class="card">카드 3</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js"></script>
<script src="app.js"></script>
</body>
</html>
| 줄 | 설명 |
|---|---|
| 8~10 | 첫 화면 영역이다. 스크롤 유도 문구를 넣는다 |
| 11~15 | 카드 3장이 들어있는 갤러리 영역이다 |
| 16~17 | GSAP core와 ScrollTrigger Plugin을 불러온다 |
14. 바이브 코딩용 프롬프트 모음
각 프롬프트를 AI 코딩 도구(Gemini CLI, Claude Code, Cursor 등)에 입력하면 교안 예제와 동일한 결과물을 생성할 수 있다.
공통 CDN 주소:
- GSAP core:
https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js - ScrollTrigger:
https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js - SplitText:
https://cdn.jsdelivr.net/npm/gsap@3/dist/SplitText.min.js - TextPlugin:
https://cdn.jsdelivr.net/npm/gsap@3/dist/TextPlugin.min.js - Draggable:
https://cdn.jsdelivr.net/npm/gsap@3/dist/Draggable.min.js - MorphSVGPlugin:
https://cdn.jsdelivr.net/npm/gsap@3/dist/MorphSVGPlugin.min.js
14.1. Tween 기본
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
4개의 100x100px 박스를 세로로 배치하고, 각각 다른 색상을 적용해.
- 박스1(빨강): gsap.to()로 x축 300px 이동, 1초
- 박스2(파랑): gsap.from()으로 y축 -100px, opacity 0에서 등장, 1초
- 박스3(노랑): gsap.fromTo()로 x:0,opacity:0 → x:300,opacity:1, 1초
- 박스4(초록): gsap.set()으로 즉시 x:100, opacity:0.5 적용
각 박스 위에 메서드 이름(to, from, fromTo, set)을 h2로 표시해.
불필요한 CSS 장식 금지.
14.2. 02-5. Tween 실전 (이동+회전+색상)
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
3개의 100x100px 박스를 세로로 배치해.
- box1(주황): 3초간 x:200 이동, opacity:0.2, ease:"steps(10)", delay:2
- box2(연두): 3초간 x:200 이동, 720도 회전, scale:1.3
- box3(토마토): 3초간 x:200 이동, ease:"elastic", 배경색 red로 변경, width:300, fontSize:60
모두 gsap.to()를 사용한다.
불필요한 CSS 장식 금지.
14.3. Ease 비교
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
8개의 50x50px 원형(border-radius:50%) 요소를 세로로 나열해.
배경색은 purple이고, 각 원 안에 ease 이름을 텍스트로 표시해.
모든 원이 동시에 x:600으로 이동하되, 각각 다른 ease를 적용한다. duration은 모두 5초.
순서: none, power1, power2, power3, power4, back, elastic, bounce
불필요한 CSS 장식 금지.
14.4. Timeline 순서 실행
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
4개의 100x100px 박스를 세로로 배치해. 색상은 빨강, 초록, 파랑, 핑크.
gsap.timeline()을 사용해서 다음 순서로 애니메이션한다:
- .one: 2초간 x:500 이동
- .two: timeline 시작 1초 시점에 3초간 x:500 (절대값 1)
- .three: 이전 tween 시작 시점과 동시에 1초간 x:500 ("<")
- .four: 이전 tween 시작 + 0.5초 후 1초간 x:500 ("<0.5")
불필요한 CSS 장식 금지.
14.5.Timeline defaults
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
h2 제목, p 설명문, a 버튼(blueviolet 배경), img(picsum.photos/200/150) 요소를 배치해.
gsap.timeline({ defaults: { duration: 1 } })을 사용해서:
- h2: y:-50, opacity:0에서 등장
- p: "-=0.5" 오버랩으로 등장
- a: "+=1" 갭 후 등장
- img: 절대값 "3"초 시점에 y:200에서 등장
모두 gsap.from()을 사용한다.
불필요한 CSS 장식 금지.
14.6. 애니메이션 핸들링
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
100x100px 빨간 박스 1개와 5개의 버튼(시작, 정지, 재개, 반전, 재시작)을 배치해.
gsap.to()로 박스를 8초간 x:400, width:400으로 이동하되 paused:true로 생성해.
각 버튼 클릭 시:
- 시작: tween.play()
- 정지: tween.pause()
- 재개: tween.resume()
- 반전: tween.reverse()
- 재시작: tween.restart()
불필요한 CSS 장식 금지.
14.7. ScrollTrigger 기본
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
3개의 section(각 100vh)을 배치해. 홀수는 #16213e, 짝수는 #0f3460 배경.
두 번째 section 중앙에 150x150px 빨간 박스를 넣어.
gsap.registerPlugin(ScrollTrigger) 후:
- 박스를 x:500, rotation:360, borderRadius:100, duration:2로 애니메이션
- scrollTrigger: trigger는 박스, start:"top 80%", end:"bottom 20%"
- toggleActions: "play none reverse none"
- markers: true
불필요한 CSS 장식 금지.
14.8. ScrollTrigger scrub
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
3개의 section(각 100vh)을 배치해. 두 번째 section 중앙에 150x150px 노란 박스.
gsap.to()로 박스를 x:500, rotation:360, borderRadius:100으로 애니메이션.
scrollTrigger 설정:
- trigger: 박스
- start: "top 50%", end: "bottom 20%"
- scrub: true (스크롤에 1:1 연동)
- markers: true
불필요한 CSS 장식 금지.
15. ScrollTrigger pin
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
3개의 section(각 100vh)을 배치해. 두 번째 section 중앙에 150x150px 초록 박스.
gsap.to()로 박스를 x:500, rotation:360으로 애니메이션.
scrollTrigger 설정:
- trigger: 박스
- start: "top 50%", end: "bottom 200px"
- scrub: true
- pin: true (스크롤 동안 박스 고정)
- markers: true
불필요한 CSS 장식 금지.
15.1. ScrollTrigger.create()
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
위아래에 100vh spacer를 두고, 가운데 sec1 영역(100vh) 중앙에 150x150px 빨간 박스.
gsap.timeline()으로:
1) 박스를 rotation:450, scale:0, borderRadius:200
2) 이어서 rotation:1800, scale:1, borderRadius:20
ScrollTrigger.create()로 별도 설정:
- animation: 위 timeline 연결
- trigger: ".sec1", start: "top top", end: "+=2000"
- scrub: true, pin: true, anticipatePin: 1, markers: true
불필요한 CSS 장식 금지.
15.2. ScrollTrigger stagger
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
위아래에 100vh spacer를 두고, 가운데 sec3 영역(100vh)에 100x100px 빨간 박스 5개를 가로로 나열해.
gsap.timeline()으로 박스들을 gsap.from():
- y:-300, scale:0.5, autoAlpha:0, ease:"back.out(4)"
- stagger: { amount: 3, from: "random" }
ScrollTrigger.create()로:
- trigger: ".sec3", start: "top top", end: "+=2000"
- scrub: true, pin: true, markers: true
불필요한 CSS 장식 금지.
07-8. ScrollTrigger callback
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
3개의 section(각 100vh)을 배치해. 두 번째 section 중앙에 150x150px 노란 박스.
화면 우측 상단에 position:fixed로 로그 패널(#log)을 만들어. 배경 rgba(0,0,0,0.8), 글자색 #0ae448.
gsap.to()로 박스를 x:500으로 애니메이션.
scrollTrigger 설정:
- trigger: 박스, start: "top center", end: "bottom 20%"
- scrub: true, markers: true
- onEnter: 로그 패널에 "진입" 추가
- onLeave: "이탈" 추가
- onEnterBack: "재진입" 추가
- onLeaveBack: "재이탈" 추가
- onUpdate: 진행률(self.progress.toFixed(3)) 추가
addLog() 함수로 p 요소를 동적 생성하여 로그 패널에 append한다.
불필요한 CSS 장식 금지.
16. SplitText 글자 단위 등장
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
SplitText CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/SplitText.min.js
배경색은 #1a1a2e이다.
화면 중앙에 h2 요소로 "안녕하세요, GSAP 세계에 오신 것을 환영합니다!" 텍스트를 배치해.
글자색은 #0ae448, font-size는 40px.
gsap.registerPlugin(SplitText) 후:
- SplitText.create()로 h2를 type:"chars, words"로 분리
- gsap.from(split.chars)로 y:50, opacity:0, stagger:0.05, duration:0.6, ease:"back.out"
불필요한 CSS 장식 금지.
16.1. TextPlugin 타이핑 효과
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
TextPlugin CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/TextPlugin.min.js
배경색은 #1a1a2e이다.
화면 중앙에 빈 h2 요소(.msg)를 배치해. 글자색은 #f0c368, font-size는 36px.
gsap.registerPlugin(TextPlugin) 후:
- gsap.to(".msg")로 text 속성에 "안녕하세요, GSAP 세계에 오신 것을 환영합니다!" 지정
- duration: 3, ease: "none"
- 한 글자씩 타이핑되는 효과가 나타나야 한다
불필요한 CSS 장식 금지.
16.2. Draggable 드래그 앤 드롭
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
Draggable CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/Draggable.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
화면 중앙에 150x150px 빨간 박스(border-radius:16px)를 배치해.
박스 안에 "드래그해봐!" 텍스트. cursor:grab, active 시 cursor:grabbing.
박스 아래에 현재 좌표를 표시하는 div(#coords)를 만들어. 글자색 #0ae448.
gsap.registerPlugin(Draggable) 후:
- Draggable.create()로 type:"x,y", bounds:"body"
- onDrag 콜백에서 #coords에 현재 x, y 좌표를 실시간 표시
불필요한 CSS 장식 금지.
16.3. MorphSVG 도형 변신
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
MorphSVGPlugin CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/MorphSVGPlugin.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
화면 중앙에 200x200 SVG를 배치하고, 초록색(#0ae448) circle(cx:100, cy:100, r:50)을 넣어.
gsap.registerPlugin(MorphSVGPlugin) 후:
- gsap.to("#shape")로 morphSVG 적용
- shape: "M50,10 L90,90 L10,90 Z" (삼각형)
- type: "rotational"
- duration:2, ease:"power2.inOut", repeat:-1, yoyo:true
- 원 ↔ 삼각형을 무한 왕복한다
불필요한 CSS 장식 금지.
17. 기본 가로 스크롤
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
main 안에 5개의 section(각 100vw, 100vh)을 가로로 나열해.
main의 width:500%, display:flex, flex-wrap:nowrap.
각 section에 큰 숫자(1~5)를 중앙 표시하고, 각각 다른 배경색을 적용해.
gsap.registerPlugin(ScrollTrigger) 후:
- gsap.utils.toArray("section")으로 배열 생성
- gsap.to()로 xPercent: -100 * (sections.length - 1)
- ease: "none"
- scrollTrigger: trigger:"main", pin:true, scrub:1, snap:1/(sections.length-1), end:"+=7000"
불필요한 CSS 장식 금지.
18. 가로+세로 혼합 스크롤
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
main 안에 7개 섹션을 배치하되:
- sec1, sec2: 일반 세로 스크롤
- sec3, sec4, sec5: .horizontal div로 감싸서 가로 스크롤 구간
- sec6, sec7: 일반 세로 스크롤
.horizontal: display:flex, flex-wrap:nowrap, width:300%
.horizontal > section: width:100%
main: overflow:hidden
각 섹션에 번호와 "(세로)" 또는 "(가로)" 텍스트 표시. 각각 다른 배경색.
gsap.registerPlugin(ScrollTrigger) 후:
- .horizontal 내부 section만 가로 이동
- end: () => "+=" + (horizontal.offsetWidth - innerWidth)
- pin:true, scrub:1
- snap: { snapTo: 1/(sections.length-1), inertia:false, duration:{min:0.1,max:0.1} }
- invalidateOnRefresh:true, anticipatePin:1
불필요한 CSS 장식 금지.
18.1. 실전 종합 — 스크롤 카드 갤러리
단일 HTML 파일을 만들어줘.
GSAP CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js
ScrollTrigger CDN: https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js
배경색은 #1a1a2e, 글자색은 흰색이다.
- 첫 번째 section(.hero, 100vh): 중앙에 "스크롤을 내려보세요 ↓" 텍스트
- 두 번째 section(.gallery): 카드 3장을 가로로 나열 (250x350px, 배경 #16213e, border-radius:16px, border:2px solid #0f3460)
- 아래에 spacer(60vh)
gsap.registerPlugin(ScrollTrigger) 후:
- gsap.from(".card")로 y:80, opacity:0, duration:0.8, stagger:0.3, ease:"power2.out"
- scrollTrigger: trigger:".gallery", start:"top 70%"
- 스크롤하면 카드가 0.3초 간격으로 아래에서 순차 등장한다
불필요한 CSS 장식 금지.