
Next.js App Router์์ Motion์ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ๋ค์ ๋ ๊ฐ์ง ๋ฐฉ์์ด ์๋ค.
// ์ผ๋ฐ์ ์ธ ๋ฐฉ์
"use client";
import { motion } from "motion/react";
// React Server Components ํ๊ฒฝ
import * as motion from "motion/react-client";
๋์ ์ฐจ์ด๋ ๋จ์ํ import ๊ฒฝ๋ก๊ฐ ์๋๋ผ ์ปดํฌ๋ํธ๊ฐ ์ด๋ ๋ ๋๋ง ๊ฒฝ๊ณ์ ๋ฐฐ์น๋๋์ง, ์๋ฒ์ ํด๋ผ์ด์ธํธ์์ ์ด๋ค ์์ ์ด ์ํ๋๋์ง, ๋ธ๋ผ์ฐ์ ๋ก ์ ๋ฌ๋๋ JavaScript์ ๋ฒ์๊ฐ ์ด๋ป๊ฒ ๋ฌ๋ผ์ง๋์ง์ ์๋ค.
1. motion/react
motion/react๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Motion์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ์ "use client"๋ฅผ ์ ์ธํด์ผ ํ๋ค.
"use client";
import { motion } from "motion/react";
export default function Page() {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
Hello
</motion.div>
);
}
๋ ๋๋ง ํ๋ฆ์ ๋จ์ํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Browser
โ
โ Request
โผ
Next.js Server
โ
โโ Page (Client Component)
โโ Client Component ๋ ๋๋ง
โโ HTML ์์ฑ
โโ RSC Payload
โ
โผ
Browser
โ
โโ HTML ํ์
โโ Client JS ๋ค์ด๋ก๋
โ
โผ
Hydration
โ
โโ React ์ด๋ฒคํธ ๋ฐ ์ํ ์ฐ๊ฒฐ
โโ Motion ๋ก์ง ์ด๊ธฐํ
โโ Motion ์ปดํฌ๋ํธ ํ์ฑํ
โ
โผ
Animation ์คํ
๋ ๋๋ง ํ๋ฆ์์ ๋ฌ๋ผ์ง๋ ์ฃผ์ ๋ด์ฉ
1. ์ปดํฌ๋ํธ์ ๋ ๋๋ง ๊ฒฝ๊ณ๊ฐ ํด๋ผ์ด์ธํธ๋ก ์ด๋ํ๋ค
"use client"๋ ํด๋น ํ์ผ์ Client Component์ ์์์ ์ผ๋ก ๋ง๋ ๋ค.
๋ฐ๋ผ์ ํด๋น ํ์ผ์ ์๋ฒ์์๋ง ์คํ๋๋ ์ปดํฌ๋ํธ๊ฐ ์๋๋ผ, ๋ธ๋ผ์ฐ์ ์์ ์คํํ JavaScript๋ฅผ ํฌํจํ๋ ํด๋ผ์ด์ธํธ ๋ ๋๋ง ๊ฒฝ๊ณ๊ฐ ๋๋ค.
"use client"
โ
โผ
ํด๋น ํ์ผ์ด Client Boundary๊ฐ ๋จ
โ
โผ
์ปดํฌ๋ํธ ์ฝ๋๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ๋จ
2. ์ปดํฌ๋ํธ ์ฝ๋๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ๋๋ค
์๋ฒ์์ HTML์ ์์ฑํ๋๋ผ๋, ํด๋น Client Component๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ๋์์ํค๋ ค๋ฉด ๊ด๋ จ JavaScript๊ฐ ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋์ด์ผ ํ๋ค.
Server
โ
โโ HTML ์์ฑ
โโ Client JS ๋ฒ๋ค ์์ฑ
โ
โผ
Browser
โ
Hydration
์ฆ ์ด๊ธฐ HTML์ ์๋ฒ์์ ์์ฑ๋ ์ ์์ง๋ง, Motion ์ปดํฌ๋ํธ๋ฅผ ํ์ฑํํ๊ธฐ ์ํ JavaScript ๋ค์ด๋ก๋์ Hydration์ด ํ์ํ๋ค.
3. ์๋ฒ ์ ์ฉ ๋ก์ง์ ๊ฐ์ ์ปดํฌ๋ํธ์์ ์ง์ ์ฌ์ฉํ ์ ์๋ค
Client Component๊ฐ ๋ ํ์ผ์์๋ ์๋ฒ ์ ์ฉ API๋ ์๋ฒ์์๋ง ์คํ๋์ด์ผ ํ๋ ๋ก์ง์ ์ง์ ์ฌ์ฉํ ์ ์๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ์์ ์ ๋ณ๋์ Server Component์์ ์ฒ๋ฆฌํ ๋ค props๋ children์ผ๋ก ์ ๋ฌํด์ผ ํ๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ
- ์๋ฒ ์ ์ฉ ๋ชจ๋ ์ฌ์ฉ
- ์๋ฒ ์ ์ฉ ํ๊ฒฝ ๋ณ์ ์ ๊ทผ
- ์๋ฒ์์๋ง ์คํ๋์ด์ผ ํ๋ ๋ฐ์ดํฐ ์กฐํ
๋ฐ๋ผ์ ํ์ด์ง ์ ์ฒด๊ฐ Client Component๊ฐ ๋ ํ์๊ฐ ์๋ค๋ฉด Client Boundary๋ฅผ ๊ฐ๋ฅํ ์๋์ชฝ์ผ๋ก ๋ด๋ฆฌ๋ ๊ฒ์ด ์ ๋ฆฌํ๋ค.
2. motion/react-client
Motion์ Next.js์ RSC ํ๊ฒฝ์ ์ํด ๋ณ๋์ entry point๋ฅผ ์ ๊ณตํ๋ค.
import * as motion from "motion/react-client";
export default async function Page() {
const data = await getData();
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
{data.title}
</motion.div>
);
}
์ด ๊ฒฝ์ฐ Page ์์ฒด์ "use client"๋ฅผ ์ ์ธํ์ง ์์๋ ๋๋ค.
๋ ๋๋ง ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ์ด ์ดํดํ ์ ์๋ค.
Browser
โ
โ Request
โผ
Next.js Server
โ
โโ Page (Server Component)
โ โ
โ โโ getData()
โ โโ Server rendering
โ
โโ motion.div
โ
โผ
Client Boundary
โ
โโ HTML
โโ RSC Payload
โ
โผ
Browser
โ
โโ HTML ํ์
โโ Motion Client JS ๋ค์ด๋ก๋
โ
โผ
Motion ๋ถ๋ถ Hydration
โ
โผ
Animation ์คํ
๋ ๋๋ง ํ๋ฆ์์ ๋ฌ๋ผ์ง๋ ์ฃผ์ ๋ด์ฉ
1. ํ์ด์ง์ ๊ธฐ๋ณธ ๋ ๋๋ง ๊ฒฝ๊ณ๊ฐ ์๋ฒ์ ์ ์ง๋๋ค
Page์ "use client"๊ฐ ์์ผ๋ฏ๋ก ํ์ด์ง๋ ๊ณ์ Server Component๋ก ๋์ํ๋ค.
Page
โ
โโ ์๋ฒ์์ ์คํ
โโ ์๋ฒ์์ ๋ฐ์ดํฐ ์กฐํ
โโ ์๋ฒ์์ HTML ๋ฐ RSC Payload ์์ฑ
โโ Motion ๋ถ๋ถ๋ง ํด๋ผ์ด์ธํธ ๊ธฐ๋ฅ ์ฌ์ฉ
์ฆ Motion์ ์ฌ์ฉํ๋๋ผ๋ ํ์ด์ง ์ ์ฒด๊ฐ Client Component๋ก ์ ํ๋์ง ์๋๋ค.
2. Client Boundary๊ฐ Motion ์ปดํฌ๋ํธ ๋ด๋ถ์ ํ์ ๋๋ค
motion/react-client๋ Motion์ด ์ ๊ณตํ๋ ์ปดํฌ๋ํธ ์์ฒด๋ฅผ Client Component๋ก ์ฐ๊ฒฐํ๋ค.
Page (Server Component)
โ
โผ
motion.div (Client Component)
โ
โผ
Motion Hydration
์ด ๊ตฌ์กฐ์์๋ ํ์ด์ง์ ๋ฐ์ดํฐ ์กฐํ ๋ก์ง์ ์๋ฒ์ ๋จ๊ณ , Motion ์ ๋๋ฉ์ด์ ์ ํ์ํ ๋ถ๋ถ๋ง ํด๋ผ์ด์ธํธ์์ ํ์ฑํ๋๋ค.
3. ์๋ฒ ๋ฐ์ดํฐ ์กฐํ๊ฐ ์๋ฒ์์ ๊ณ์ ์ํ๋๋ค
๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ Client Component๋ก ์ ํ๋์ง ์๊ณ ์๋ฒ์์ ์คํ๋๋ค.
export default async function Page() {
const data = await getData();
return (
<motion.div>
{data.title}
</motion.div>
);
}
๋ ๋๋ง ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
Next.js Server
โ
โโ Page ์คํ
โโ getData() ์คํ
โโ ์๋ฒ ์ ์ฉ ๋ก์ง ์ํ
โโ HTML ์์ฑ
โโ RSC Payload ์์ฑ
โ
โผ
Browser
โ
motion.div hydrate
โ
โผ
Motion animation
4. ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋๋ JavaScript์ ๋ฒ์๋ฅผ ์ค์ผ ์ ์๋ค
ํ์ด์ง ์ ์ฒด๊ฐ Client Component๊ฐ ๋๋ ๋์ Motion ์ปดํฌ๋ํธ์ ํ์ํ ํด๋ผ์ด์ธํธ ์ฝ๋๋ง ์ฐ๊ฒฐ๋๋ค.
Server Component ์ฝ๋
โ
โโ ๋ธ๋ผ์ฐ์ ์์ ๋ค์ ์คํํ ํ์ ์์
Motion Client Component
โ
โโ ๋ธ๋ผ์ฐ์ ์์ Hydration ํ์
๋ฐ๋ผ์ ์ด๊ธฐ HTML ์์ฑ๊ณผ ๋ฐ์ดํฐ ์กฐํ๋ ์๋ฒ์์ ์ฒ๋ฆฌํ๊ณ , ์ ๋๋ฉ์ด์ ์คํ์ ํ์ํ JavaScript๋ง ํด๋ผ์ด์ธํธ์์ ์ฌ์ฉํ ์ ์๋ค.
3. Server Component๋ฅผ motion.div ๋ด๋ถ์ ๋ฃ๋๋ค๋ฉด?
์ฌ๊ธฐ์ RSC์ Composition Model์ด ์ค์ํ๋ค.
import * as motion from "motion/react-client";
export default async function Page() {
return (
<motion.div>
<Profile />
</motion.div>
);
}
Profile์ด Server Component๋ผ๋ฉด ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
Page
โ
โโ Server Component
โ
โโ motion.div
โ
โโ Profile
โโ Server Component
motion.div๊ฐ Client Component๋ผ๊ณ ํด์ Profile๊น์ง Client Component๊ฐ ๋๋ ๊ฒ์ ์๋๋ค.
๋ ๋๋ง ํ๋ฆ์์ ๋ฌ๋ผ์ง๋ ์ฃผ์ ๋ด์ฉ
1. Client Component์ Server Component๊ฐ ํ๋์ ํธ๋ฆฌ ์์ ๊ณต์กดํ๋ค
Page (Server Component)
โ
โโ motion.div (Client Component)
โ
โโ Profile (Server Component)
Client Boundary๊ฐ ์กด์ฌํ๋๋ผ๋ ๊ทธ ์๋์ ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ์๋์ผ๋ก Client Component๊ฐ ๋๋ ๊ฒ์ ์๋๋ค.
2. Server Component์ ๊ฒฐ๊ณผ๋ ์๋ฒ์์ ๋จผ์ ์์ฑ๋๋ค
Profile์ ์๋ฒ์์ ์คํ๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ RSC Payload์ ํฌํจ๋์ด ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋๋ค.
Next.js Server
โ
โโ Page ์คํ
โโ Profile ์คํ
โโ DB / API ์ ๊ทผ
โโ ์๋ฒ์์ ๊ฒฐ๊ณผ ์์ฑ
โโ RSC Payload ์์ฑ
โ
โผ
Browser
โ
motion.div hydrate
โ
โผ
Motion animation
3. children์ ์๋ฒ์์ ์์ฑ๋ ๊ฒฐ๊ณผ๋ก ์ ๋ฌ๋๋ค
motion.div๋ ํด๋ผ์ด์ธํธ์์ ๋์ํ์ง๋ง, ๋ด๋ถ์ Profile์ ์๋ฒ์์ ๋ ๋๋ง๋ ๊ฒฐ๊ณผ๋ก ์ ๋ฌ๋ ์ ์๋ค.
Server
โ
โโ Profile ๋ ๋๋ง
โโ motion.div์ ์ ๋ฌํ children ์์ฑ
โ
โผ
Browser
โ
motion.div ํด๋ผ์ด์ธํธ ๋์ ํ์ฑํ
๋ฐ๋ผ์ motion/react-client๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ฒ์์ ์ํํ ์ ์๋ ์์
์ ๊ณ์ ์๋ฒ์์ ์ํํ๋ฉด์, Motion์ ํ์ํ ํด๋ผ์ด์ธํธ ๋์๋ง ํด๋ผ์ด์ธํธ์์ ์คํํ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค ์ ์๋ค.
4. ์ค์ Motion ์์ค ์ฝ๋ ํ์ธ
์ด ๋์์ด ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋์ง Motion์ ์์ค ์ฝ๋๋ฅผ ๋ฐ๋ผ๊ฐ ๋ณด๋ฉด ๋ ๋ช ํํ๋ค.
ํ์ฌ Motion ํจํค์ง์ motion/react-client entry๋ ๋ค์ ํ์ผ์์ ์์ํ๋ค.
packages/motion/src/react-client.ts
์ด ํ์ผ์ framer-motion/client๋ฅผ ๋ค์ exportํ๋ ๋งค์ฐ ์์ entry point๋ค.
motion/react-client
โ
โผ
packages/motion/src/react-client.ts
โ
โผ
framer-motion/client
โ
โผ
Motion Client Components
๊ทธ๋ฆฌ๊ณ ์ค์ Motion HTML element๋ฅผ ๋ง๋๋ ๋ถ๋ถ์ ๋ค์ ์์น์์ ํ์ธํ ์ ์๋ค.
packages/framer-motion/src/render/components/motion/elements.ts
์ฌ๊ธฐ์๋ "use client"๊ฐ ์ ์ธ๋์ด ์๊ณ , MotionDiv ์ญ์ createMotionComponent("div") ํํ๋ก ์์ฑ๋๋ค.
elements.ts
โ
โโ "use client"
โ
โโ MotionDiv
โ
โผ
createMotionComponent("div")
๋ ๋๋ง ํ๋ฆ์์ ๋ฌ๋ผ์ง๋ ์ฃผ์ ๋ด์ฉ
motion/react-client๋ ํ์ด์ง์ "use client"๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ์์ด ์๋๋ผ, Motion ๋ด๋ถ์ ์ปดํฌ๋ํธ ๊ตฌํ์ Client Boundary๋ฅผ ํฌํจํ๋ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
motion/react-client
โ
โผ
Motion ๋ด๋ถ Client Entry
โ
โผ
MotionDiv ์์ฒด๊ฐ Client Component
โ
โผ
ํ์ด์ง๋ Server Component๋ก ์ ์ง
๊ทธ๋ฆฌ๊ณ ์ด createMotionComponent๋ฅผ ์ค์ ๋ก ๊ตฌ์ฑํ๋ ํต์ฌ ์ฝ๋๊ฐ ๋ค์ ํ์ผ์ด๋ค.
packages/framer-motion/src/render/components/motion/create.ts
์ด ํ์ผ์์๋ createMotionComponentWithFeatures()๊ฐ Motion Component๋ฅผ ์์ฑํ๋ฉด์ feature bundle๊ณผ DOM visual element๋ฅผ ์ฐ๊ฒฐํ๋ค.
๊ฒฐ๊ตญ ์ฐ๋ฆฌ๊ฐ ์์ฑํ๋:
<motion.div animate={{ opacity: 1 }} />
๋ ๊ฐ๋ ์ ์ผ๋ก ๋ค์ ๊ตฌ์กฐ๋ฅผ ๊ฑฐ์น๋ค.
motion/react-client
โ
โผ
framer-motion/client
โ
โผ
MotionDiv
โ
โผ
createMotionComponent("div")
โ
โผ
createMotionComponentWithFeatures()
โ
โโ Motion features
โโ DOM Visual Element
์ด ๊ตฌ์กฐ์ ํต์ฌ์ Motion ์ปดํฌ๋ํธ ์์ฒด๋ ํด๋ผ์ด์ธํธ์์ ๋์ํ์ง๋ง, Motion ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ์์ ํ์ด์ง๊น์ง ํด๋ผ์ด์ธํธ๋ก ์ ํํ์ง ์๋๋ค๋ ์ ์ด๋ค.
๊ฒฐ๋ก
Next.js App Router์์ ๋ ๋ฐฉ์์ ์ฐจ์ด๋ฅผ ๋ ๋๋ง ํ๋ฆ ๊ด์ ์ผ๋ก ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
motion/react
"use client"
โ
โผ
์ฌ์ฉ์ ์ปดํฌ๋ํธ๊ฐ Client Boundary
โ
โโ ์ปดํฌ๋ํธ ์ฝ๋๊ฐ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ
โโ ํด๋ผ์ด์ธํธ์์ Hydration ํ์
โโ ์๋ฒ ์ ์ฉ ๋ก์ง์ ๊ฐ์ ํ์ผ์์ ์ง์ ์ฌ์ฉํ๊ธฐ ์ด๋ ค์
โโ Motion ํ์ฑํ
โ
โผ
Animation ์คํ
motion/react-client
Server Component
โ
โโ ์๋ฒ์์ ๋ ๋๋ง
โโ ์๋ฒ์์ ๋ฐ์ดํฐ fetching
โโ ์๋ฒ ์ ์ฉ ๋ก์ง ์ํ
โโ Server Components ์ ์ง
โ
โผ
motion.div
โ
โโ Motion ๋ด๋ถ์ Client Boundary ์กด์ฌ
โโ Motion ๊ด๋ จ ์ฝ๋๋ง ํด๋ผ์ด์ธํธ์์ ํ์ฑํ
โโ Motion ๋ถ๋ถ๋ง Hydration
โ
โผ
Animation ์คํ
๋ ๋ฐฉ์์ ๋ ๋๋ง ํ๋ฆ์์ ๊ฐ์ฅ ์ค์ํ ์ฐจ์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
| ๊ตฌ๋ถ | motion/react |
motion/react-client |
|---|---|---|
| Client Boundary | ์ฌ์ฉํ๋ ํ์ผ์ ์ง์ ์์ฑ | Motion ์ปดํฌ๋ํธ ๋ด๋ถ์ ์กด์ฌ |
| ํ์ด์ง ์ปดํฌ๋ํธ | Client Component๊ฐ ๋จ | Server Component๋ก ์ ์ง ๊ฐ๋ฅ |
| ๋ฐ์ดํฐ ์กฐํ | ๋ณ๋ Server Component๋ก ๋ถ๋ฆฌ ํ์ | ๊ฐ์ ํ์ด์ง์์ ์๋ฒ ๋ฐ์ดํฐ ์กฐํ ๊ฐ๋ฅ |
| ์๋ฒ ์ ์ฉ ๋ก์ง | ๊ฐ์ ํ์ผ์์ ์ง์ ์ฌ์ฉํ๊ธฐ ์ด๋ ค์ | ์๋ฒ์์ ๊ณ์ ์คํ ๊ฐ๋ฅ |
| ํด๋ผ์ด์ธํธ JavaScript | ํด๋น Client Component ๋ฒ์์ ํฌํจ | Motion์ ํ์ํ ๋ฒ์๋ก ํ์ |
| Hydration | Client Component ์ ์ฒด์ ํ์ | Motion ์ปดํฌ๋ํธ ์ค์ฌ์ผ๋ก ์ํ |
| Server Component ์กฐํฉ | ๋ณ๋ ๊ตฌ์ฑ ํ์ | Motion ๋ด๋ถ์ Server Component๋ฅผ children์ผ๋ก ์ ๋ฌ ๊ฐ๋ฅ |
๋ฐ๋ผ์ ๋จ์ํ Motion์ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ด์ง ์ ์ฒด๋ฅผ Client Component๋ก ๋ง๋ค ํ์๊ฐ ์๋ค๋ฉด **motion/react-client**๊ฐ Next.js์ RSC ๋ชจ๋ธ์ ๋ ์์ฐ์ค๋ฝ๊ฒ ๋ง๋ ์ ํ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
๋ฐ๋ฉด useMotionValue, useScroll, useState, useEffect ๋ฑ React์ ํด๋ผ์ด์ธํธ ๊ธฐ๋ฅ์ ์ง์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ผ๋ฉด ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ช
์์ ์ผ๋ก Client Component๋ก ๋ง๋ค๊ณ motion/react๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ์ ํฉํ๋ค.
'๐ STUDY > WEB' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [JavaScript] JavaScript๊ฐ ๋์ํ๋ ์๋ฆฌ - ๊ธฐ๋ณธํธ (0) | 2026.01.16 |
|---|