Framer Motion: Claude Code 활용 가이드
framer motion: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.
Framer Motionで洗練された애니메이션を구축する
Framer MotionはReact向けの宣言的애니메이션라이브러리です。CSS애니메이션では難しい複雑なインタラクションや레이아웃애니메이션を、直感的なAPIで구현할 수 있습니다。Claude Code는 애니메이션설계から細かなイージング調整まで的確にサポートしてくれます。
기본적인애니메이션
Claude Code에애니메이션付きの컴포넌트を依頼합시다。
> Framer Motionでカード목록の애니메이션を作って。
> マウント時のスタガー표시、호버時の拡大、클릭時のフィードバック付きで。
import { motion, AnimatePresence } from "framer-motion";
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
};
const cardVariants = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.4, ease: "easeOut" },
},
};
function CardList({ items }: { items: Item[] }) {
return (
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="grid grid-cols-3 gap-4"
>
{items.map((item) => (
<motion.div
key={item.id}
variants={cardVariants}
whileHover={{ scale: 1.03, boxShadow: "0 8px 30px rgba(0,0,0,0.12)" }}
whileTap={{ scale: 0.98 }}
className="p-6 bg-white rounded-lg shadow"
>
<h3>{item.title}</h3>
<p>{item.description}</p>
</motion.div>
))}
</motion.div>
);
}
AnimatePresenceでマウント・アンマウント
要素の추가・삭제に애니메이션を付けるパターンです。
function NotificationStack({ notifications }: { notifications: Notification[] }) {
return (
<div className="fixed top-4 right-4 space-y-2">
<AnimatePresence mode="popLayout">
{notifications.map((notification) => (
<motion.div
key={notification.id}
initial={{ opacity: 0, x: 100, scale: 0.9 }}
animate={{ opacity: 1, x: 0, scale: 1 }}
exit={{ opacity: 0, x: 100, scale: 0.9 }}
transition={{ type: "spring", stiffness: 300, damping: 25 }}
layout
className="bg-white p-4 rounded-lg shadow-lg min-w-[300px]"
>
<p>{notification.message}</p>
</motion.div>
))}
</AnimatePresence>
</div>
);
}
레이아웃애니메이션
layout프로퍼티を使って、레이아웃변경時のスムーズな애니메이션を実現할 수 있습니다。
function FilterableGrid({ items }: { items: Item[] }) {
const [filter, setFilter] = useState("all");
const filteredItems = items.filter(
(item) => filter === "all" || item.category === filter
);
return (
<div>
<div className="flex gap-2 mb-4">
{["all", "design", "dev", "marketing"].map((f) => (
<motion.button
key={f}
onClick={() => setFilter(f)}
className={`px-4 py-2 rounded ${filter === f ? "bg-blue-500 text-white" : "bg-gray-200"}`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{f}
</motion.button>
))}
</div>
<motion.div layout className="grid grid-cols-3 gap-4">
<AnimatePresence>
{filteredItems.map((item) => (
<motion.div
key={item.id}
layout
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3 }}
className="p-4 bg-white rounded-lg"
>
{item.title}
</motion.div>
))}
</AnimatePresence>
</motion.div>
</div>
);
}
스크롤連動애니메이션
useScrollとuseTransformで스크롤位置に連動する애니메이션を구현します。
import { motion, useScroll, useTransform } from "framer-motion";
function ParallaxHero() {
const { scrollY } = useScroll();
const y = useTransform(scrollY, [0, 500], [0, -150]);
const opacity = useTransform(scrollY, [0, 300], [1, 0]);
const scale = useTransform(scrollY, [0, 300], [1, 0.8]);
return (
<motion.div
style={{ y, opacity, scale }}
className="h-screen flex items-center justify-center"
>
<h1 className="text-6xl font-bold">Welcome</h1>
</motion.div>
);
}
function ScrollReveal({ children }: { children: React.ReactNode }) {
const ref = useRef(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start end", "end start"],
});
const opacity = useTransform(scrollYProgress, [0, 0.3], [0, 1]);
const y = useTransform(scrollYProgress, [0, 0.3], [50, 0]);
return (
<motion.div ref={ref} style={{ opacity, y }}>
{children}
</motion.div>
);
}
ジェスチャー애니메이션
드래그やスワイプなどのジェスチャーに대응した애니메이션です。
function DraggableCard() {
return (
<motion.div
drag
dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
dragElastic={0.2}
dragTransition={{ bounceStiffness: 300, bounceDamping: 20 }}
whileDrag={{ scale: 1.1, cursor: "grabbing" }}
className="w-48 h-48 bg-blue-500 rounded-xl cursor-grab"
/>
);
}
function SwipeCard({ onSwipe }: { onSwipe: (dir: string) => void }) {
return (
<motion.div
drag="x"
dragConstraints={{ left: 0, right: 0 }}
onDragEnd={(_, info) => {
if (info.offset.x > 100) onSwipe("right");
if (info.offset.x < -100) onSwipe("left");
}}
className="p-8 bg-white rounded-xl shadow-lg"
>
スワイプしてください
</motion.div>
);
}
정리
Framer Motionを使えば、React애플리케이션に洗練された애니메이션を簡単に추가할 수 있습니다。Claude Code에「こ와 같은애니메이션が欲しい」と伝える만으로、적절한バリアント설계やイージング설정を생성してくれます。
UI컴포넌트との組み合わせはRadix UI컴포넌트활용を、デザインシステムの구축はshadcn/ui활용가이드를 참고하세요.Framer Motion공식 문서도 확인해 두세요.
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code용 CLAUDE.md 템플릿 7선 | 실제 프로젝트에 바로 붙여 넣는 예시
개인 앱, 콘텐츠 사이트, API, 팀 저장소, 레거시 코드베이스에 맞는 실전 CLAUDE.md 템플릿 7개와 피해야 할 실패 사례를 정리했습니다.
Claude Code Approval / Sandbox Guide | 매일 안전하게 쓰는 설정법
Claude Code의 allow, ask, deny, sandbox를 어떻게 나눌지, 실전 settings와 hooks, 실패 사례와 함께 정리합니다.
Claude Code 완벽 입문 가이드 2026 | 제로부터 실무 활용까지 7단계
Claude Code를 처음 사용하는 분들을 위한 완전 입문 가이드. 설치부터 실제 개발 워크플로우에 녹이는 것까지 — Masa가 처음에 겪었던 모든 시행착오를 바탕으로 정리했습니다.