Next.js 15로 개인 프로젝트를 만들다가, 메인 화면에 가벼운 애니메이션 하나 넣고 싶어서 LottieFiles + lottie-react 조합을 써봤다.
처음에는 "json 파일 하나 내려받아서 컴포넌트에 박으면 되겠지" 하고 가볍게 시작했는데, 막상 TypeScript랑 같이 쓰다 보니 타입 에러 한 번 제대로 맞고 정리하게 됐다.
이 글은
- LottieFiles에서 애니메이션 고르는 과정
- Next.js에서 lottie-react 설치하고 붙인 방법
- 내가 당했던 JSON 타입 관련 에러와 해결 방법
1. LottieFiles에서 애니메이션 고르기
나는 LottieFiles에서 무료 애니메이션을 하나 골라서 가져왔다.
1-1. LottieFiles 접속
사이트에 접속하면 이런 메인 화면이 나온다.

- 회원 가입 후 로그인
- 무료 애니메이션 위주로 사용
1-2. 애니메이션 검색하고 선택
검색창에 키워드를 넣거나, 카테고리별로 골라 볼 수 있다.
원하는 느낌의 이미지를 하나 고르면 상세 모달이 열린다.
여기서 나는 오른쪽 상단 Download 버튼을 눌러서 애니메이션 파일을 내려받았다.


1-3. 내 작업공간에 저장 후 JSON 받기
- 먼저 내 워크스페이스에 애니메이션을 저장하고
그다음 JSON 파일 형식으로 내려받았다.
나는 Next.js 프로젝트라서 이 JSON을 그대로 public 폴더에 넣어서 사용했다.


2. lottie-react 설치
프로젝트에 lottie-react를 설치한다.
pnpm add lottie-react
공식 저장소와 문서
GitHub: https://github.com/Gamote/lottie-react
GitHub - Gamote/lottie-react: A lightweight React library for rendering complex After Effects animations in real time using Lott
A lightweight React library for rendering complex After Effects animations in real time using Lottie. - Gamote/lottie-react
github.com
가이드 사이트: https://lottiereact.com/
Lottie
Lottie for React
lottiereact.com
*가이드 사이트도 참고
설치는 여기까지면 끝이다.
3. 애니메이션 JSON 파일 위치
Next.js에서는 정적인 파일을 public 아래에 두면 편하다.
나는 이렇게 넣어 뒀다.

나중에 페이지에서 바로 import 해서 쓰는 구조로 갔다.
4. 컴포넌트 구성
구조는 대략 이런 느낌으로 만들었다.
- MainLottie 컴포넌트
- lottie-react를 실제로 사용하는 얇은 래퍼
- Hero 컴포넌트
- 메인 섹션 레이아웃 담당
- 이미지 영역에 MainLottie를 받도록 설계
- page.tsx
- Hero를 불러오면서 animationMain.json을 props로 내려줌
4-1. MainLottie 컴포넌트
"use client";
import Lottie from "lottie-react";
type MainLottieProps = {
animationData: object;
};
export default function MainLottie({ animationData }: MainLottieProps) {
return <Lottie animationData={animationData} />;
}
처음에는 animationData 타입을 JSON으로 선언했다가 에러를 맞았고,
현재는 일단 object로 두고 쓰고 있다. (아래 트러블슈팅에서 자세히)
4-2. page.tsx에서 사용
대략 이런 구조다.
import Hero from "@/components/Hero";
import MainLottie from "@/components/MainLottie";
import animationMain from "@/public/animationMain.json";
export default function Home() {
return (
<Hero imgSection={<MainLottie animationData={animationMain} />} />
);
}
Hero 쪽에서는 imgSection을 ReactNode로 받도록 해 두고,
그 자리에서만 Lottie 애니메이션을 렌더링했다.
5. 트러블슈팅 – JSON 타입으로 선언했다가 맞은 에러
처음에는 MainLottie props 타입을 이렇게 적었다.
그리고 page.tsx에서 이렇게 넘겼다.


그러자 TypeScript가 아래와 같은 에러를 뿜었다.
TS2739: Type '{ nm: string; ddd: number; h: number; w: number; meta: { g: string; };
layers: ... }' is missing the following properties from type 'JSON':
parse, stringify, [Symbol.toStringTag]
요약하면
- 내가 생각한 JSON 타입은 "json 파일에서 읽어온 데이터" 느낌이었는데
- TypeScript 입장에서 JSON은 JSON.parse, JSON.stringify 같은 전역 JSON 객체의 타입을 말한다
- 그래서 animationMain 같은 실제 데이터 객체를 JSON 타입으로 볼 수가 없어서 타입 에러가 발생했다.
5-1. lottie-web의 스키마를 보고 깨달은 점
공식 animation.json 스키마를 보면 이런 부분이 있다.

즉, Lottie 애니메이션 json은 결국
- 파일 확장자는 .json이지만
- 코드로 사용할 때는 그냥 일반 JavaScript 객체다.
그래서 타입도 JSON이 아니라 object 쪽에 가깝다고 보는 게 맞다.
5-2. 우선 object로 정리해서 해결
그래서 현재는 일단 이렇게 바꿨다.

이렇게 바꾸자 위의 TS2739 에러는 바로 사라졌다.
엄밀하게 들어가면 lottie-react 내부에서 기대하는 타입을 가져와서
좀 더 정확하게 정의하는 게 맞지만, 지금은
- 빠르게 붙여서 화면에서 동작을 확인하고 싶었고
- 복잡한 타입 정의는 나중에 정리하기로 마음먹었다
그래서 우선은 object로 마무리했다.
6. 정리하면서 남겨두는 메모
이번에 LottieFiles + lottie-react를 붙이면서 느낀 점을 간단히 정리하면
- 애니메이션 자체는 LottieFiles에서 JSON 하나 받으면 끝이라 생각보다 간단했다
- Next.js에서는 public 폴더에 넣고 import 해서 쓰면 편했다
- TypeScript에서 JSON 타입은 내가 막연히 생각했던 "json 데이터"가 아니라 전역 JSON 객체라는 걸 다시 한 번 배웠다
- Lottie 애니메이션 json은 결국 "object"라서,
props 타입도 그 관점에서 생각해야 한다
일단은 "Next.js에서 lottie-react로 LottieFiles 애니메이션 한 번 붙여 봤다" 정도의
실무 기록으로 남겨둔다.