Lottie — Airbnb의 오픈소스 라이브러리로, Bodymovin 플러그인을 통해 Adobe After Effects에서 JSON 형식으로 내보낸 벡터 애니메이션을 렌더링합니다. 애니메이션은 프로그래밍 방식으로 렌더링되며 모든 화면 해상도에서 품질 저하가 없습니다. GitHub(2026)에 따르면 Lottie는 iOS, Android 및 웹에서 50,000개 이상의 프로젝트에 사용됩니다. 다른 유형의 애니메이션에 대한 자세한 내용은 애니메이션 일반 가이드를 참조하세요.
주요 내용
Lottie — 벡터 애니메이션을 재생하기 위한 크로스 플랫폼 라이브러리로, 2015년 Airbnb에서 개발되었습니다. 무거운 비디오 파일과 래스터 스프라이트 시트의 문제를 해결합니다. 디자이너가 After Effects에서 애니메이션을 만들고 Bodymovin을 통해 JSON으로 내보내면 개발자가 이 파일을 모바일 앱에 임베드합니다. Lottie는 플랫폼에 따라 Canvas, Core Animation 또는 Skia를 통해 프로그래밍 방식으로 애니메이션을 렌더링합니다.
Lottie의 주요 장점 — 벡터 애니메이션은 Apple Watch에서 4K TV까지 모든 화면에서 품질 저하 없이 확장됩니다. 애니메이션 JSON 파일 크기는 일반적으로 5–50KB로, 동등한 비디오 파일보다 수십 배 작습니다. Airbnb Engineering(2025)에 따르면, Lottie는 마스크, 효과, 곡선 및 표현식을 포함하여 Adobe After Effects 기능의 80% 이상을 지원합니다.
Bodymovin — After Effects용 플러그인(무료, GitHub)으로, Lottie 런타임이 이해할 수 있는 JSON 형식으로 컴포지션을 직렬화합니다. After Effects CC 2018 이상을 지원합니다. 많은 키프레임이 있는 복잡한 애니메이션의 경우 dotLottie가 권장됩니다 — Lottie JSON을 기반으로 하지만 압축되어 단일 파일로 패키징된 형식입니다.
Lottie는 플랫폼 기능에 적응하는 계층형 렌더링 아키텍처를 사용합니다. Android에서는 Canvas API를 통해 애니메이션이 그려집니다 — Lottie 자체 렌더러(LottieDrawable)로, 시스템 애니메이션을 사용하지 않습니다. iOS에서는 Lottie가 Core Animation Layers에 의존하여 높은 성능과 60FPS를 제공합니다. Flutter에서는 Lottie가 CustomPainter를 통해 Skia Canvas를 사용합니다.
렌더링은 세 단계를 거칩니다: JSON 파싱 — 애니메이션을 LottieComposition(모든 레이어, 셰이프, 키프레임)으로 파싱; 보간 — 이징 곡선을 고려한 키프레임 간 중간 값 계산; 드로잉 — Canvas 또는 Core Animation을 통한 현재 프레임 렌더링. Lottie는 하드웨어 가속을 지원합니다: Android — Hardware Accelerator를 사용한 Canvas 가속, iOS — Core Animation의 내장 GPU 가속을 갖춘 CALayer.
| 플랫폼 | 렌더러 | 하드웨어 가속 | 라이브러리 |
|---|---|---|---|
| Android | Canvas (LottieDrawable) | Hardware Accelerator (API 14+) | com.airbnb.lottie |
| iOS | Core Animation (CALayer) | GPU (Metal, OpenGL) | Lottie-iOS |
| Flutter | Skia Canvas (CustomPainter) | Impeller (Flutter 3.16+) | lottie_flutter |
| React Native | Native bridge | 플랫폼에 따라 다름 | lottie-react-native |
Android에서 LottieAnimationView는 AppCompatImageView를 확장하고 로딩 및 렌더링 전체 주기를 처리합니다. JSON 파일은 res/raw 또는 assets 폴더에 배치됩니다. LottieAnimationView는 재생 제어 — play, pause, resume, setFrame, setProgress, repeat, speed — 및 AnimatorUpdateListener와 AnimatorListener를 통한 리스닝을 지원합니다.
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:lottie_rawRes="@raw/loading_animation"
app:lottie_autoPlay="true"
app:lottie_loop="true" />
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieListener
// LottieAnimationView 프로그래밍 방식 설정
val lottieView = LottieAnimationView(context).apply {
setAnimation(R.raw.celebrate_animation)
repeatCount = ValueAnimator.INFINITE
speed = 1.5f
addAnimatorUpdateListener { animator ->
val progress = animator.animatedValue as Float
progressBar.progress = (progress * 100).toInt()
}
playAnimation()
}
// assets에서 로드 및 캐싱
lottieView.setAnimation("animations/confetti.json")
lottieView.setCacheStrategy(LottieAnimationView.CacheStrategy.Strong)
// LottieDrawable — View 없는 사용자 정의 드로잉
val drawable = LottieDrawable().apply {
setComposition(
LottieCompositionFactory.fromRawRes(context, R.raw.star)
.addListener { composition -> composition?.let { setComposition(it); play() } }
)
}
Android 모범 사례: 자주 반복되는 애니메이션에는 setCacheStrategy(CacheStrategy.Strong)를 사용하세요 — 컴포지션이 메모리에 캐시되어 새 인스턴스마다 JSON을 다시 파싱하지 않습니다. 목록(RecyclerView)의 경우 enableMergePathsForKitKatAndAbove(true) 및 disableExtraScaleModeForOlderWorkarounds()와 함께 LottieAnimationView를 사용하여 렌더링을 최적화하세요. 투명 배경의 애니메이션의 경우 GPU 가속을 위해 android:layerType="hardware"를 설정하세요.
iOS에서 AnimationView는 UIKit 및 SwiftUI용 기본 Lottie 클래스입니다. Swift Package Manager 또는 CocoaPods를 통해 추가됩니다. JSON 파일은 프로젝트 번들에 추가됩니다. AnimationView는 자동으로 스케일(논리적 화면 밀도)을 결정하고 Core Animation을 사용하여 60FPS로 레이어를 렌더링합니다.
import Lottie
// UIKit: 수동 제어가 있는 AnimationView
let animationView = AnimationView(name: "confetti")
animationView.frame = view.bounds
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.animationSpeed = 1.5
animationView.play(fromProgress: 0, toProgress: 0.5) { finished in
print("Animation segment finished: \(finished)")
}
view.addSubview(animationView)
// UIKit: 진행률이 있는 애니메이션(이벤트 바인딩용)
animationView.play(fromFrame: AnimationFrameTime(30),
toFrame: AnimationFrameTime(90))
// SwiftUI: UIViewRepresentable로서의 LottieView
import Lottie
import SwiftUI
struct LottieView: UIViewRepresentable {
let name: String
var loopMode: LottieLoopMode = .loop
@Binding var progress: CGFloat
func makeUIView(context: Context) -> AnimationView {
let view = AnimationView(name: name)
view.contentMode = .scaleAspectFit
view.loopMode = loopMode
return view
}
func updateUIView(_ uiView: AnimationView, context: Context) {
uiView.currentProgress = progress
}
}
// SwiftUI에서 사용
LottieView(name: "loading", progress: $animationProgress)
.frame(width: 100, height: 100)
iOS 모범 사례: 로드 직후 시작되는 애니메이션의 경우 loopMode = .playOnce와 함께 animationView.play(fromProgress: 0, toProgress: 1)를 사용하여 일회성 악센트 효과를 만듭니다. UITableView/UICollectionView에서 Lottie를 사용하는 경우 LottieAnimation.cached를 통해 캐시된 애니메이션 파일과 함께 AnimationView를 사용하세요. 많은 수의 레이어(50개 이상)를 렌더링하면 FPS가 떨어질 수 있습니다 — 이러한 경우 macOS의 경우 renderingEngine = .mainThread(기본값) 또는 .coreAnimation을 활성화하세요.
Lottie는 비디오 파일과 근본적으로 다릅니다: 픽셀을 저장하지 않고 벡터 셰이프, 변환 및 시간에 따른 변화 곡선을 설명합니다. 비디오(MP4, WebM)는 고정 해상도의 래스터 프레임 시퀀스입니다. 차이점은 파일 크기, 확대/축소 품질, 상호작용성 및 성능에서 나타납니다.
| 파라미터 | Lottie (JSON) | 비디오 (MP4) | GIF |
|---|---|---|---|
| 파일 크기 | 5–50KB | 200–2000KB | 500–5000KB |
| 확대/축소 품질 | 벡터(무한) | 고정(픽셀) | 고정 |
| 상호작용성 | 진행, 속도, 일시정지, 색상 변경 | 없음 | 없음 |
| 알파 채널(투명도) | 네이티브 | 코덱 필요 | 지원 |
| 성능 (CPU) | 낮은 부하 | 중간(디코딩) | 높음(래스터 디코딩) |
Lottie를 선택해야 할 때: 로딩 아이콘, 좋아요/반응 애니메이션, 온보딩 화면, 버튼의 악센트 마이크로애니메이션. 3D 효과, 사실적인 조명 또는 포토리얼리스틱 캐릭터가 있는 복잡한 장면의 경우 비디오가 더 실용적인 선택입니다. Lottie는 긴 장면(10초 이상) 재생용으로 설계되지 않았습니다 — 하나의 애니메이션 최적 지속 시간은 2~5초입니다.
Lottie 성능은 레이어 수, 마스크 및 효과의 복잡성, 렌더러에 따라 달라집니다. 중간급 기기에서 60FPS를 유지하려면 다음 권장 사항을 따르세요: 장면당 레이어 수를 30~40개로 제한하고, 중첩된 사전 컴포지션을 피하고, 복잡한 애니메이션에는 dotLottie를 사용하세요.
// RecyclerView용 Lottie 최적화
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
import com.airbnb.lottie.LottieCompositionFactory
// 메모리 내 컴포지션 캐싱
private val cache = LottieCompositionFactory.setCacheStrategy(CacheStrategy.Strong)
// 재사용을 위한 LottieAnimationView 풀
class LottiePool {
private val pool = LinkedList<LottieAnimationView>()
fun acquire(context: Context): LottieAnimationView {
return pool.poll() ?: LottieAnimationView(context)
}
fun release(view: LottieAnimationView) {
view.pauseAnimation()
view.cancelAnimation()
pool.add(view)
}
}
// 불필요한 기능 비활성화
lottieView.enableMergePathsForKitKatAndAbove(true)
lottieView.setHardwareAcceleration(true)
lottieView.setMaxFrame(60) // 프레임 수 제한
추가 최적화: Android 4.4+ 기기에서는 enableMergePathsForKitKatAndAbove(true)를 활성화하세요 — 중복 경로를 단일 경로로 병합하여 드로우 호출 수를 줄입니다. JSON 대신 dotLottie를 사용하세요 — 바이너리 형식이 protobuf 직렬화를 통해 애니메이션을 50~80% 압축하여 파싱 시간을 줄입니다. RecyclerView의 애니메이션에서는 repeatCount = 0(단일 재생)으로 설정하고 recyclerView.addOnScrollListener를 통해 스크롤 시 애니메이션을 중지하세요. Airbnb Engineering Blog(2025)에 따르면 이러한 조치는 CPU 부하를 최대 40%까지 줄입니다.
자주 묻는 질문
dotLottie를 사용하세요 — protobuf 기반의 바이너리 형식으로 JSON을 50~80% 압축합니다. After Effects에서 "Glyphs" 설정을 None(텍스트가 필요하지 않은 경우)으로 하여 Bodymovin을 통해 내보내고 불필요한 가이드 및 가이드 레이어를 비활성화하세요. 내보내기 전에 보이지 않는 레이어와 불투명도 0%인 레이어를 제거하세요.
최소 SDK 버전을 확인하세요: Android용 Lottie는 API 14+를 지원하지만 일부 효과(Path Morphing, Gradient)는 API 21+에서만 작동합니다. iOS에서 Lottie는 iOS 11+가 필요합니다. 오래된 기기의 경우 폴백으로 애니메이션의 정적 png 프레임을 사용하세요. LottieCompositionFactory를 통해 애니메이션을 비동기적으로 로드하고 LottieListener.onFailure를 통해 오류를 처리하세요.
네, LottieDynamicProperties 또는 KeyPath를 통해 가능합니다. After Effects에서 레이어 이름을 설정하고(예: "icon-fill"), 코드에서: lottieView.addValueCallback(KeyPath("icon-fill"), LottieProperty.COLOR) { Color.GREEN }. 이를 통해 중복 파일을 만들지 않고 애니메이션을 앱 테마에 맞게 사용자 정의할 수 있습니다. iOS의 경우 AnimationView.setValueProvider(ColorValueProvider)를 사용하세요.
Lottie — After Effects에서 미리 만든 애니메이션을 재생하기 위한 형식입니다. Rive — State Machine, 트리거 및 입력이 있는 대화형 애니메이션입니다. Lottie는 수동적 애니메이션(로딩, 좋아요, 환영 화면)에 적합합니다. Rive는 게임, 대화형 UI 요소, 사용자 작업에 대한 피드백이 있는 애니메이션용입니다. Rive는 자체 편집기가 필요하며 Lottie는 익숙한 After Effects를 통해 작동합니다.
Android: lottieView.addAnimatorListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { ... } }). iOS: animationView.play { finished in }. SwiftUI: onChange와 함께 currentProgress에 Binding을 사용합니다. Kotlin Multiplatform의 경우 lottie-compose 라이브러리에서 LottieAnimatable을 사용하세요.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.