-
Notifications
You must be signed in to change notification settings - Fork 0
Error Handling
JEONG edited this page Jun 29, 2026
·
2 revisions
세 가지 에러 표현 방식과 선택 기준. 상황에 맞는 도구를 고르는 것이 핵심입니다.
| 방식 | 용도 | 표현 |
|---|---|---|
| Loadable | 화면 내 인라인 상태 (리스트 로딩, 도메인 에러, 검증 실패) | 뷰 내부 상태 |
| ErrorHandler | 흐름 중단형 전역 에러 (세션 만료, 권한, 네트워크 오류) | 전역 Alert |
| AlertPrompt | 확인/취소 다이얼로그 (파괴적 작업, 분기점) | 모달 다이얼로그 |
enum Loadable<T: Equatable> {
case idle // 초기 상태
case loading // 로딩 중
case loaded(T) // 성공
case failed(AppError) // 실패 (인라인 표시)
}
// View에서 사용
switch viewModel.attendanceState {
case .idle: Color.clear.task { await viewModel.fetch() }
case .loading: ProgressView()
case .loaded(let data): ContentView(data: data)
case .failed(let error): ErrorView(error: error, retry: ...)
}// 네트워크 오류, 세션 만료 등 → Alert
errorHandler.handle(error, context: ErrorContext(
feature: "Activity",
action: "attendanceBtnTapped",
retryAction: { [weak self] in await self?.retry() }
))Loadable vs ErrorHandler
- ErrorHandler: 작업 흐름 중단, 즉각적 사용자 액션 필요 (세션 만료, 권한 요청, 네트워크 오류)
- Loadable: 화면 내 상태 표시 (리스트 로딩 실패, 도메인 에러, 검증 실패)
// ViewModel
@Observable
final class SomeViewModel {
var alertPrompt: AlertPrompt?
func deleteButtonTapped() {
alertPrompt = AlertPrompt(
title: "삭제 확인",
message: "정말 삭제하시겠습니까?",
positiveBtnTitle: "삭제",
isPositiveBtnDestructive: true,
positiveBtnAction: { [weak self] in self?.delete() },
negativeBtnTitle: "취소"
)
}
}
// View
.alertPrompt(item: $viewModel.alertPrompt)AlertPrompt 사용 기준
- 파괴적 작업 전 확인 (삭제, 초기화 등)
- 사용자 선택이 필요한 분기점
| 상황 | 타입 |
|---|---|
| 통신/인증/토큰 문제 | NetworkError |
| 서버 응답은 왔지만 비즈니스 실패/디코딩 실패 | RepositoryError |
| 도메인 규칙 위반 | DomainError |
| 화면 전달 타입 | AppError |
관련 문서: Architecture · Networking