본문 바로가기
개발하기/SwiftUI

SwiftUI에서 Lottie 애니메이션으로 프로페셔널한 로딩 화면 만들기

by lovedeveloping 2025. 7. 9.
반응형

사용한 이미지

반응형

1. 소개

로딩 화면은 모바일 애플리케이션의 사용자 경험에 있어 매우 중요한 요소입니다. 앱이 데이터를 로드하거나 초기 설정을 수행하는 동안 시각적 피드백을 제공하죠. 이 포괄적인 가이드에서는 Airbnb에서 만든 강력한 애니메이션 라이브러리인 Lottie를 사용하여 SwiftUI에서 멋진 로딩 애니메이션을 구현하는 방법을 살펴보겠습니다.

📱 학습 내용:
  • SwiftUI 프로젝트에 Lottie 통합하는 방법
  • 재사용 가능한 애니메이션 컴포넌트 만들기
  • 전문적인 로딩 화면 구축하기
  • 성능 최적화 기법

2. Lottie란? 왜 사용해야 할까?

Lottie는 After Effects 애니메이션을 모바일 장치에서 실시간으로 렌더링하는 오픈 소스 애니메이션 라이브러리입니다. 복잡한 애니메이션을 앱에 쉽게 통합할 수 있도록 디자이너와 개발자 간의 격차를 좁혀줍니다.

✨ Lottie 사용의 이점:

  • 고품질 애니메이션: After Effects에서 디자이너가 제작한 전문 애니메이션
  • 작은 파일 크기: JSON 기반 형식으로 비디오 파일보다 훨씬 작음
  • 확장 가능: 벡터 기반 애니메이션으로 모든 화면 크기에서 선명함
  • 성능: 하드웨어 가속을 통해 모바일 장치에 최적화
  • 쉬운 통합: iOS, Android, 웹 플랫폼을 위한 간단한 API

🎯 Lottie 사용 시기:

  • 로딩 화면 및 스플래시 화면
  • 빈 상태 일러스트레이션
  • 온보딩 애니메이션
  • 인터랙티브 UI 요소
  • 성공/오류 상태 표시기
  • 마이크로 인터랙션과 즐거운 순간들

3. iOS 프로젝트에 Lottie 설치하기

📦 Swift Package Manager 사용 (권장)

Swift Package Manager는 iOS 프로젝트에서 의존성을 관리하는 현대적인 방법입니다:

  1. Xcode에서 프로젝트 열기
  2. File → Add Package Dependencies로 이동
  3. Lottie 저장소 URL 입력:
https://github.com/airbnb/lottie-ios
  1. 사용할 버전 선택 (최신 안정 버전 권장)
  2. Add Package 클릭
  3. 메시지가 나타나면 앱 타겟 선택
  4. 다시 Add Package 클릭하여 완료
✅ 성공! 이제 Lottie가 프로젝트에 통합되었습니다. import Lottie로 가져올 수 있습니다.

4. Lottie 애니메이션 파일 준비하기

🔍 애니메이션 파일 찾기

옵션 1: LottieFiles.com (권장)

  1. LottieFiles.com 방문
  2. "loading", "spinner", "progress" 등의 키워드로 검색
  3. 필터링 기준:
    • 카테고리 (UI/UX, 로딩 등)
    • 색상 구성
    • 스타일 (플랫, 3D, 아웃라인)
  4. 다운로드 전 애니메이션 미리보기
  5. 라이선스 확인 (많은 것들이 상업적 사용 무료)

옵션 2: 맞춤 애니메이션 제작

  • Bodymovin 플러그인과 함께 Adobe After Effects 사용
  • Fiverr, Upwork, 또는 Dribbble에서 디자이너 고용
  • LottieFiles Creator 또는 Rive 같은 온라인 도구 사용

💾 다운로드 및 Xcode에 추가

📝 단계별 과정:
  1. 애니메이션 다운로드:
    • 선택한 애니메이션 클릭
    • Download → Lottie JSON 선택
    • 품질 선택: 프로덕션용 "Optimized", 편집용 "Original"
  2. Xcode 프로젝트에 추가:
    • .json 파일을 Xcode 프로젝트 네비게이터로 드래그
    • "Copy items if needed" 체크 확인
    • 앱 타겟 선택
    • 전용 폴더 생성 (예: "Animations" 또는 "Lottie")
  3. 명명 규칙:
    • 설명적인 이름 사용: LoadingSpinner.json, SuccessCheckmark.json
    • 공백과 특수 문자 피하기
    • camelCase 또는 snake_case 일관성 있게 사용

5. UIViewRepresentable로 LottieView 만들기

Lottie는 UIKit 프레임워크이므로 UIViewRepresentable을 사용하여 SwiftUI용으로 래핑해야 합니다:

import SwiftUI
import Lottie

struct LottieView: UIViewRepresentable {
    // MARK: - Properties
    let animationName: String
    let loopMode: LottieLoopMode
    let animationSpeed: CGFloat
    
    // MARK: - Initializer
    init(animationName: String, 
         loopMode: LottieLoopMode = .loop,
         animationSpeed: CGFloat = 1.0) {
        self.animationName = animationName
        self.loopMode = loopMode
        self.animationSpeed = animationSpeed
    }
    
    // MARK: - UIViewRepresentable
    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: .zero)
        view.backgroundColor = .clear
        
        // Create and configure animation view
        let animationView = LottieAnimationView()
        animationView.animation = LottieAnimation.named(animationName)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = loopMode
        animationView.animationSpeed = animationSpeed
        animationView.play()
        
        // Add constraints
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        
        NSLayoutConstraint.activate([
            animationView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            animationView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            animationView.topAnchor.constraint(equalTo: view.topAnchor),
            animationView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        // Update animation if needed
    }
}
🔑 핵심 포인트:
  • UIViewRepresentable: UIKit 뷰를 SwiftUI에 연결하는 프로토콜
  • makeUIView: Lottie 애니메이션 뷰를 생성하고 구성
  • Auto Layout: 애니메이션이 사용 가능한 공간을 채우도록 보장
  • 구성: 루프 모드, 속도, 콘텐츠 모드 커스터마이징 가능

6. Lottie를 사용한 로딩 화면 구축

Lottie 애니메이션을 사용한 완전한 로딩 화면을 만들어보겠습니다:

import SwiftUI

struct LoadingView: View {
    // MARK: - State Properties
    @State private var isLoading = true
    @State private var loadingText = "Loading..."
    
    // MARK: - View Body
    var body: some View {
        ZStack {
            // Background
            Color(.systemBackground)
                .edgesIgnoringSafeArea(.all)
            
            if isLoading {
                VStack(spacing: 20) {
                    // Lottie Animation
                    LottieView(animationName: "LoadingAnimation")
                        .frame(width: 200, height: 200)
                    
                    // Loading Text
                    Text(loadingText)
                        .font(.headline)
                        .foregroundColor(.secondary)
                    
                    // Progress Indicator (optional)
                    ProgressView()
                        .progressViewStyle(LinearProgressViewStyle())
                        .frame(width: 150)
                }
                .transition(.opacity)
            } else {
                // Your main content here
                MainContentView()
                    .transition(.opacity)
            }
        }
        .onAppear {
            startLoading()
        }
    }
    
    // MARK: - Helper Methods
    private func startLoading() {
        // Simulate loading process
        DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
            withAnimation(.easeInOut(duration: 0.5)) {
                isLoading = false
            }
        }
    }
}

🎨 재사용 가능한 로딩 오버레이 만들기

앱 전체에서 더 나은 재사용성을 위해:

struct LoadingOverlay: ViewModifier {
    @Binding var isLoading: Bool
    let animationName: String
    let backgroundColor: Color
    
    func body(content: Content) -> some View {
        ZStack {
            content
                .disabled(isLoading)
                .blur(radius: isLoading ? 3 : 0)
            
            if isLoading {
                backgroundColor
                    .edgesIgnoringSafeArea(.all)
                    .opacity(0.8)
                
                VStack {
                    LottieView(animationName: animationName)
                        .frame(width: 150, height: 150)
                    
                    Text("Please wait...")
                        .foregroundColor(.white)
                        .font(.headline)
                }
            }
        }
        .animation(.easeInOut, value: isLoading)
    }
}

// Extension for easy usage
extension View {
    func loadingOverlay(isLoading: Binding<Bool>, 
                       animationName: String = "LoadingAnimation",
                       backgroundColor: Color = .black) -> some View {
        self.modifier(LoadingOverlay(isLoading: isLoading, 
                           animationName: animationName,
                           backgroundColor: backgroundColor))
    }
}

7. 성능 최적화 팁

⚡ 1. 애니메이션 파일 최적화

// Check animation complexity
func analyzeAnimation(named: String) {
    guard let animation = LottieAnimation.named(named) else { return }
    
    print("Animation Details:")
    print("- Duration: \(animation.duration) seconds")
    print("- Frame Rate: \(animation.framerate) fps")
    print("- Start Frame: \(animation.startFrame)")
    print("- End Frame: \(animation.endFrame)")
}

🚀 2. 지연 로딩

struct LazyLottieView: View {
    let animationName: String
    @State private var isVisible = false
    
    var body: some View {
        Group {
            if isVisible {
                LottieView(animationName: animationName)
            } else {
                Color.clear
            }
        }
        .onAppear { isVisible = true }
        .onDisappear { isVisible = false }
    }
}

💾 3. 메모리 관리

class AnimationCache {
    static let shared = AnimationCache()
    private var cache: [String: LottieAnimation] = [:]
    
    func animation(named name: String) -> LottieAnimation? {
        if let cached = cache[name] {
            return cached
        }
        
        guard let animation = LottieAnimation.named(name) else {
            return nil
        }
        
        cache[name] = animation
        return animation
    }
    
    func clearCache() {
        cache.removeAll()
    }
}
⚠️ 성능 팁:
  • 애니메이션을 30초 이하로 유지
  • 30-60 fps로 최적화
  • 가능하면 더 작은 크기 사용
  • 복잡한 마스크와 매트 피하기
  • 구형 기기에서 테스트

8. 일반적인 문제와 해결방법

❌ 문제 1: 애니메이션이 표시되지 않음

해결방법:
// Verify animation file exists
if LottieAnimation.named("YourAnimation") == nil {
    print("Animation file not found!")
    // Check:
    // 1. File name spelling (case-sensitive)
    // 2. File is added to target membership
    // 3. File extension is .json
    // 4. File is in the main bundle
}

🐌 문제 2: 성능 문제

해결방법:
// Use smaller frame size
LottieView(animationName: "HeavyAnimation")
    .frame(width: 100, height: 100) // Smaller = better performance
    .scaleEffect(2) // Scale up if needed

💧 문제 3: 메모리 누수

해결방법:
struct SafeLottieView: UIViewRepresentable {
    let animationName: String
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        let animationView = LottieAnimationView()
        
        // Weak reference to prevent retain cycles
        animationView.backgroundBehavior = .pauseAndRestore
        
        // Setup animation...
        
        return view
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    class Coordinator {
        weak var animationView: LottieAnimationView?
        
        deinit {
            animationView?.stop()
            animationView?.removeFromSuperview()
        }
    }
}

🌓 문제 4: 다크 모드 호환성

해결방법:
// Use color filters for simple adjustments
struct ThemedLottieView: View {
    @Environment(\.colorScheme) var colorScheme
    
    var body: some View {
        LottieView(animationName: "LoadingAnimation")
            .colorMultiply(colorScheme == .dark ? .white : .black)
    }
}

9. 결론

축하합니다! 이제 SwiftUI에서 Lottie 애니메이션을 마스터했습니다. 우리가 다룬 내용을 요약해보겠습니다:

✅ 학습한 내용:
  • iOS 프로젝트에서 Lottie 설치 및 구성
  • UIViewRepresentable을 사용한 재사용 가능한 LottieView 컴포넌트 생성
  • 전문적인 로딩 화면 및 오버레이 구축
  • 고급 애니메이션 제어 기법
  • 성능 최적화 전략
  • 일반적인 문제 해결

📱 모범 사례 체크리스트

  • ✅ 애니메이션을 가볍게 유지 (100KB 이하)
  • ✅ 다양한 기기 및 iOS 버전에서 테스트
  • ✅ 접근성 및 동작 감소 설정 고려
  • ✅ 과도하지 않게 목적에 맞게 애니메이션 사용
  • ✅ 라이트 및 다크 모드 모두 최적화
  • ✅ 메모리 사용량 및 성능 모니터링

🚀 다음 단계

  1. LottieFiles 라이브러리에서 더 많은 애니메이션 탐색
  2. After Effects로 맞춤 애니메이션 생성해보기
  3. 제스처를 사용한 인터랙티브 Lottie 애니메이션 구현
  4. 재사용 가능한 애니메이션 컴포넌트 라이브러리 구축
  5. iOS 개발자 커뮤니티와 작품 공유
💡 프로 팁: 간단한 애니메이션부터 시작하여 라이브러리에 더 익숙해지면서 점진적으로 복잡성을 높여가세요. 최고의 애니메이션은 방해가 되지 않으면서 사용자 경험을 향상시킵니다.

📚 참고 자료

읽어주셔서 감사합니다! 이 가이드가 도움이 되었다면 다른 iOS 개발자들과 공유해주세요.

즐거운 코딩 되세요! 🚀

반응형