[트러블 슈팅] SplashView로 UX 개선하기
안녕하세요, 루피입니다!!
오늘은 제가 SwiftUI로 개발한 Hyodor 앱에서 공유 앨범 데이터 로딩 문제를 해결한 경험을 공유하려 합니다.
특히, 앱 실행 시 서버에서 데이터를 가져오는 동안 UX를 개선하기 위해 Splash View 를 활용한 과정에 대해 포스팅해보려합니다.
문제 상황: 데이터 로딩과 UX의 충돌
Hyodor 앱의 핵심 기능 중 하나는 공유 앨범입니다. 사용자가 HomeView에서 공유 앨범 뷰로 진입하면 서버에서 공유된 사진 데이터를 가져오는 API를 호출합니다. 이 과정은 필수적이지만, 네트워크 요청과 데이터 파싱에 시간이 걸리면서 사용자에게 대기 시간이라는 불편함을 줄 것이라는 생각을 했습니다.
이미 로드한 사진은 ImageCache을 통해 빠르게 표시했지만, 앱을 처음 실행할 때는 서버에서 데이터를 처음 가져와야 하므로 최초 로딩 시간이 문제였습니다. 어떻게 하면 이 대기 시간을 자연스럽게 처리하면서도 좋은 UX를 제공할 수 있을까 고민해보았습니다.
해결 방안: Splash 뷰로 데이터 로딩
이 문제를 해결하기 위해 저는 Splash 뷰를 활용했습니다. Splash 뷰는 단순히 앱 로고를 보여주는 디자인 요소로만 생각했었지만, 이번에는 데이터 로딩과 사용자 경험을 동시에 개선하는 도구로 사용했습니다.
SplahView에 진입했을 때, 백그라운드에서 공유 앨범 데이터를 로드하는 API를 미리 호출하여, 추후 공유 앨범 기능을 사용할때는 기다림 없이 바로 기능을 사용할 수 있게 만들었습니다.
1. Splash 뷰 설계
SplashView.swift 에서는 Hyodor 로고를 애니메이션과 함께 표시하고, 백그라운드에서 데이터 로딩을 시작합니다.
struct SplashView: View {
@State private var size = 0.8
@State private var opacity = 0.5
var sharedAlbumViewModel: SharedAlbumViewModel
var body: some View {
VStack {
Text("HYODOR")
.font(.system(size: 42, weight: .bold))
.foregroundColor(.blue)
.scaleEffect(size)
.opacity(opacity)
.onAppear {
withAnimation(.easeIn(duration: 1.2)) {
self.size = 1.0
self.opacity = 1.0
}
Task {
await sharedAlbumViewModel.syncPhotos()
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(red: 0.976, green: 0.976, blue: 0.976))
.ignoresSafeArea()
}
}
onAppear에서 sharedAlbumViewModel.syncPhotos()를 호출해 Splash 뷰가 표시되는 동안 백그라운드에서 데이터를 로드합니다.
2. 앱 실행 흐름 조정
HyodorApp.swift에서 앱 실행 시 Splash 뷰를 먼저 보여주고, 2초 후 `HomeView`로 전환하도록 설정했습니다. 이 2초는 애니메이션과 데이터 로딩이 자연스럽게 마무리될 시간을 확보하기 위한 값입니다.
@main
struct HyodorApp: App {
@State private var isActive = false
let sharedAlbumViewModel = SharedAlbumViewModel()
var body: some Scene {
WindowGroup {
if isActive {
HomeView(
viewModel: HomeVM(coordinator: homeCoordinator, calendarVM: calendarVM),
coordinator: homeCoordinator
)
.environment(\.sharedAlbumViewModel, sharedAlbumViewModel)
} else {
SplashView(sharedAlbumViewModel: sharedAlbumViewModel)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
withAnimation {
self.isActive = true
}
}
}
}
}
}
}
Environment를 활용하여, sharedAlbumViewModel을 @Environment로 전달해 앱 전역에서 공유 앨범 데이터를 쉽게 접근합니다.
3. 데이터 로딩 로직
SharedAlbumViewModel.swift의 syncPhotos() 메서드는 서버에서 사진 데이터를 가져옵니다.
func syncPhotos() async {
isLoading = true
defer { isLoading = false }
do {
let loadedPhotos = try await getAllPhotosUseCase.execute(userId: APIConstants.userId)
self.photos = loadedPhotos.filter { !$0.deleted }
.sorted { $0.uploadedAt > $1.uploadedAt }
self.errorMessage = nil
} catch {
self.errorMessage = "네트워크/파싱 오류: \(error.localizedDescription)"
}
}
오늘도 화이팅입니다!