Skip to content

Error Handling

JEONG edited this page Jun 29, 2026 · 2 revisions

Error Handling

세 가지 에러 표현 방식과 선택 기준. 상황에 맞는 도구를 고르는 것이 핵심입니다.

한눈에 보는 선택 기준

방식 용도 표현
Loadable 화면 내 인라인 상태 (리스트 로딩, 도메인 에러, 검증 실패) 뷰 내부 상태
ErrorHandler 흐름 중단형 전역 에러 (세션 만료, 권한, 네트워크 오류) 전역 Alert
AlertPrompt 확인/취소 다이얼로그 (파괴적 작업, 분기점) 모달 다이얼로그

Loadable (로컬 / 인라인 에러)

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: ...)
}

ErrorHandler (전역 Alert 에러)

// 네트워크 오류, 세션 만료 등 → Alert
errorHandler.handle(error, context: ErrorContext(
    feature: "Activity",
    action: "attendanceBtnTapped",
    retryAction: { [weak self] in await self?.retry() }
))

Loadable vs ErrorHandler

  • ErrorHandler: 작업 흐름 중단, 즉각적 사용자 액션 필요 (세션 만료, 권한 요청, 네트워크 오류)
  • Loadable: 화면 내 상태 표시 (리스트 로딩 실패, 도메인 에러, 검증 실패)

AlertPrompt (확인/취소 다이얼로그)

// 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

Clone this wiki locally