
Lottie player 는 웹 및 모바일 환경에서 vector animation을 표시하기 위한 라이브러리 중 하나로 이를 이용하여 비교적 간단하게 웹에서 애니메이션을 재생할 수 있다.
lottiefiles 에서 다양한 애니메이션을 찾아볼 수 있다. 직접 만드는 것도 가능하지만 홈페이지에서 무료로 제공하는 애니메이션을 사용하는 것도 방법이다.
react-lottie 를 이용하면 react 환경에서 편하게 Lottie를 사용할 수 있다.
$ npm install --save react-lottie
이후 .json 확장자로 된 lottie file을 react project의 src 폴더에 가져온다.
// src/animationData.json
{
"v": "4.8.0",
"meta": {
"g": "LottieFiles AE 3.5.2",
"a": "",
"k": "",
"d": "",
"tc": ""
},
"fr": 60,
"ip": 0,
"op": 180,
"w": 300,
"h": 300,
"nm": "Comp 1",
"ddd": 0,
"assets": [ ...
마지막으로 Lottie를 사용하고 싶은 component에서 react-lottie를 이용하여 json 파일을 불러오면 된다.
import Lottie from "react-lottie-player";
import animationData from "../animationData.json";
const App = () => {
...
return <Lottie
animationData={animationData}
style={{ width: "200px", height: "200px" }}
loop
play
speed={5}
/>;
};

react-lottie를 이용하여 불러온 데이터는 그 자체로 component 이므로 위에서 처럼 style을 지정해 줄 수 있다. 따라서 framer-motion , keyframes 등을 이용하여 추가적인 애니메이션을 적용할 수 있다.
Framer는 매우 자주 사용하는 react library 중 하나이지만 동작 원리를 정확히 알지 못해 이번 기회에 제대로 알고 사용하고 싶었다.
Framer 등 추가적인 애니메이션을 사용하기 위해 Lottie를 div로 한번 더 감싸주었다.
<SheepBox>
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={5}
/>
</SheepBox>
이후 화면 왼쪽 끝에서 오른쪽 끝 까지 양이 이동하게 하는 애니메이션을 추가해주었다.
const sheepVar = {
initial: { x: -200 },
animate: { x: "100vw", transition: { duration: 5 } },
};
<SheepBox variants={sheepVar} initial="initial" animate="animate">
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={5}
/>
</SheepBox>

framer를 이용하여 애니메이션 효과를 주다 보면 무한히 이어지는 효과를 주고싶을 때가 있다. 내가 찾은 방법은 총 두가지 이다.
가장 간단한 방법은 repeat: Infinity 속성을 추가해 주는 것이다.
const sheepVar = {
initial: { x: -200 },
animate: { x: "100vw", transition: { duration: 5, repeat: Infinity } },
};
이 방법은 간단하게 애니메이션을 무한히 실행시킬 수 있는 방법이다. 하지만 반복에 대한 세부적인 조건을 설정하지 못하는 등 불편한 점이 없는 것은 아니라고 생각한다. 따라서 단순한 하나의 애니메이션을 반복할 때 사용하면 좋은 방법이라고 생각한다.
두번째 방법은 component의 key를 이용하는 방법이다. React에서는 당연하게도 서로 key가 다른 component를 다른 component라고 인식한다. 따라서 일정 주기마다 key값이 다른 component를 생성해주면 특정 애니메이션을 무한히 반복할 수 있다.
const [sheepCount, setSheepCount] = useState(1);
useEffect(() => {
const timer2 = setInterval(() => {
setSheepCount(sheepCount + 1);
}, 7000);
});
<SheepBox key={sheepCount} variants={sheepVar} initial="initial" animate="animate">
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={2}
/>
</SheepBox>
이를 이용하면 주기적으로 count를 증가시켜 일정 시간마다 새로운 양이 출발점에서 끝점까지 이동하는 애니메이션을 구현할 수 있다.
경험 상 위 방법이 AnimatePresence를 이용하는 경우(exit 등)에 (1) repeat:Infinity 보다 이어지는 애니메이션을 좀 더 쉽게 구현할 수 있었다.
또한 전체 애니메이션의 시작 / 종료 시점을 한번에 설정할 수 있어 다수의 애니메이션의 주기를 한번에 설정하는데 좀 더 유리한 방법이다.
만약 양 5마리를 동시에 시작점에서 끝점까지 이동시키고 싶다면 어떻게 해야할 까?
속도가 서로 다른 양 5마리가 제각각 다른 주기를 가지고 시작점과 끝점을 이동하고 싶다면 repeat: Infinity 방식이 좀 더 편한 방법일 것이다.
const sheepSecondVar = {
initial: { x: -500 },
animate: { x: "100vw", transition: { duration: 7, delay: 2, repeat: Infinity } },
};
const sheepThirdVar = {
initial: { x: -500 },
animate: { x: "100vw", transition: { duration: 8, delay: 4, repeat: Infinity } },
};
이렇게 구현할 경우 각 양들이 자신의 주기를 가지고 따로따로 출발하는 것을 확인할 수 있다.

하지만 출발한 양들이 도착한 후 다른 양들을 기다리고 또 다시 한번에 출발하고 싶을 때는 위 방법은 좋은 방법이 되지 못한다. repeat: Infinity를 이용하였다면 각 양의 duration과 delay를 계산하여서 repeat delay를 추가적으로 설정해주어야 한다.
이때는 key를 이용하는 것이 더 효과적인 방법일 것이다.
<SheepBox key={sheepCount + "first"} variants={sheepVar} initial="initial" animate="animate">
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={2}
/>
</SheepBox>
<SheepBox key={sheepCount + "second"} variants={sheep2Var} initial="initial" animate="animate">
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={2}
/>
</SheepBox>
<SheepBox key={sheepCount + "third"} variants={sheep3Var} initial="initial" animate="animate">
<Lottie
animationData={animationData}
style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
loop
play
speed={2}
/>
</SheepBox>
모든 양이 같은 주기를 가지고 시작점과 끝점을 이동하는 것을 확인할 수 있다.
