SwiftUI의 가장 강력한 기능 중 하나는 Xcode Preview입니다.
UI를 빌드할 때마다 시뮬레이터를 돌리지 않고도 즉시 결과를 확인할 수 있죠. 하지만 규모가 커질수록 프리뷰 코드가 뷰 파일을 어지럽히고, 시나리오별 테스트가 복잡해지는 문제가 생깁니다. 이번 글에서는 프리뷰 코드를 모듈화해 관리성과 속도를 개선하는 방법을 정리합니다.
⸻
👉 해결책은 뷰 로직과 프리뷰 로직을 분리하고, Mock 서비스와 샘플 데이터를 활용하는 것입니다.
⸻
프로젝트 내에서 다음과 같이 나눕니다:
📂 Feature/
┣ 📄 UsersView.swift // 실제 뷰 + 뷰모델
┗ 📄 UsersView+Preview.swift // 프리뷰 전용 코드
⸻
UsersView.swift에는 뷰 로직과 뷰모델만 둡니다.
struct UsersView: View {
@StateObject private var vm: UsersViewModel
init(service: UserService) {
_vm = StateObject(wrappedValue: UsersViewModel(service: service))
}
var body: some View {
NavigationStack {
Group {
if vm.isLoading {
ProgressView("Loading…")
} else if let error = vm.error {
Text(error).foregroundStyle(.red)
} else if vm.users.isEmpty {
ContentUnavailableView("No Users")
} else {
List(vm.users) { user in
Text(user.name)
}
}
}
.navigationTitle("Users")
}
.task { vm.load() }
}
}
👉 여기에는 실제 서비스 주입과 UI 로직만 남습니다.
프리뷰용 목업은 모두 따로 분리합니다.
⸻
UsersView+Preview.swift에는 Mock 서비스와 샘플 데이터를 정의합니다.
extension User {
static let samples: [User] = [
.init(name: "Lee"),
.init(name: "Kim"),
.init(name: "Park")
]
}
struct MockUserService: UserService {
var users: [User] = .samples
func fetch() async throws -> [User] { users }
}
extension UsersView {
static var mockList: UsersView { .init(service: MockUserService()) }
}
#Preview("List • Light") {
UsersView.mockList
.preferredColorScheme(.light)
}
#Preview("List • Dark") {
UsersView.mockList
.preferredColorScheme(.dark)
}
⸻
프리뷰를 활용하면 실제 상황을 다양하게 재현할 수 있습니다.
• ✅ 다크 모드 / 라이트 모드
• ✅ Empty State / Error State
• ✅ 접근성 글자 크기
• ✅ RTL 레이아웃 (아랍어, 히브리어 등)
이렇게 여러 시나리오를 정의해두면, QA 단계에서 발견할 문제를 미리 캐치할 수 있습니다.
⸻
⸻
SwiftUI 프리뷰는 단순히 “UI 미리보기”가 아니라,
실제 앱의 다양한 상태를 테스트하는 강력한 도구입니다.
👉 핵심은 뷰 로직과 프리뷰 로직을 분리하고,
👉 Mock 데이터와 서비스로 시나리오를 풍부하게 구성하는 것입니다.
이렇게 모듈화하면:
• 파일이 깔끔해지고,
• 프리뷰 속도가 빨라지며,
• QA 품질도 높아집니다.
⸻