Skip to content

NetworkError.swift

JiHyeonJang edited this page Sep 10, 2025 · 2 revisions

NetworkError.swift

1. 개요

NetworkError는 네트워크 요청 과정에서 발생할 수 있는 다양한 오류 상황을 표준화하여 처리하기 위해 만들어진 에러 타입입니다.

이 파일의 목적은 다음과 같습니다.

  1. 네트워크 오류를 한 곳에서 관리

  2. 각 오류 상황에 맞는 사용자 안내 메시지 제공

  3. 디버깅 시 필요한 상세 로그 자동 생성

  4. API 서비스, ViewModel, View 어디서든 일관되게 사용 가능


2. 사용 흐름도

flowchart TD
    A[네트워크 요청 시작] --> B{요청 성공 여부?}
    B -- 예 --> C[정상 데이터 처리]
    B -- 아니오 --> D[오류 발생]
    D --> E{오류 원인 확인}
    E --> N[NetworkError 케이스 매핑]
    E -- URL 형식 오류 --> F[invalidURL]
    E -- API 키 문제 --> G[invalidAPIKey]
    E -- 서버 응답 없음 --> H[invalidResponse]
    E -- 디코딩 실패 --> I[decodingError]
    E -- 상태 코드 오류 --> J[notFound / quotaExceeded / serverError]
    E -- 기타 --> K[unknown]
    N --> L[UI 표시: error.localizedDescription]
    N --> M[로그 기록: error.log()]


3. 코드 설명

/// 네트워크 에러를 정의한 객체입니다.
enum NetworkError: Error {
    case networkError(_ error: URLError) // 일반 네트워크 오류
    case taskCancelled // 작업 취소
    case invalidURL // 잘못된 URL
    case invalidResponse // 유효하지 않은 응답
    case encodingError // 인코딩 오류
    case decodingError(_ error: DecodingError) // 디코딩 오류
    case invalidAPIKey // API 키 오류
    case quotaExceeded(_ statusCode: Int) // 호출 한도 초과
    case notFound(_ statusCode: Int) // 리소스 없음
    case uriTooLong(_ statusCode: Int) // URI 길이 초과
    case serviceUnavilable(_ statusCode: Int) // 서버 점검/장애
    case serverError(_ statusCode: Int) // 서버 내부 오류
    case remoteError(_ statusCode: Int, _ errorData: String) // 서버 전달 오류
    case unknown(_ statusCode: Int) // 알 수 없는 상태 코드
    case webSocketError // 웹소켓 오류
}


4. 에러 케이스 표

카테고리 케이스명 설명
일반 네트워크 오류 networkError(_ error: Error) 네트워크 연결 실패, 타임아웃 등
작업 취소 taskCancelled 사용자가 요청을 취소
요청 오류 invalidURL 잘못된 URL
응답 오류 invalidResponse 서버 응답 형식이 유효하지 않음
인코딩 오류 encodingError 요청 데이터 인코딩 실패
디코딩 오류 decodingError(_ error: DecodingError) 응답 JSON 디코딩 실패
인증 오류 invalidAPIKey API 키 누락/유효하지 않음
쿼터 초과 (401) quotaExceeded(_ statusCode: Int) API 호출 한도 초과
리소스 없음 (404) notFound(_ statusCode: Int) 요청 리소스를 찾을 수 없음 (404)
URI 오류 (414) uriTooLong(_ statusCode: Int) URI 길이 초과
서버 점검/장애 (503) serviceUnavilable(_ statusCode: Int) 서버가 유지보수 중/일시적 장애
서버 내부 오류 (500..<600) serverError(_ statusCode: Int) 서버 내부 처리 오류
서버 전달 오류 remoteError(_ statusCode: Int, _ errorData: String) 서버가 상태 코드와 오류 메시지 전달
기타 상태 코드 오류 unknown(_ statusCode: Int) 정의되지 않은 상태 코드
웹소켓 오류 webSocketError 웹소켓 통신 중 오류


5. LocalizedError 확장

extension NetworkError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case .taskCancelled:
            return "작업이 취소되었습니다. 아래 버튼을 눌러 다시 시도해 주세요."
        default:
            return "데이터를 불러오는 데 실패했어요. 잠시 후 다시 시도해 주세요."
        }
    }
}

  • taskCancelled → 취소된 작업임을 안내

  • 기타 → 일반적인 실패 안내 메시지


6. log(file:function:) 메서드

extension NetworkError {
    func log(file: String = #fileID, function: String = #function) -> String {
        if case .decodingError(let err) = self {
            let message: String
            switch err {
            case .typeMismatch(_, let context),
                 .valueNotFound(_, let context),
                 .keyNotFound(_, let context),
                 .dataCorrupted(let context):
                message = context.debugDescription
            @unknown default:
                message = "알 수 없는 디코딩 오류입니다."
            }
            let escaped = message.replacingOccurrences(of: "\"", with: "\\\"")
            return "decodingError(\"\(escaped)\")-\"\(file)#\(function)\""
        }
        return "\(String(describing: self))-\"\(file)#\(function)\""
    }
}


7. catch 시 주의 사항

  • 디버깅이나 UI 업데이트를 위해 error를 받아야 하는 경우, 에러를 throw할 때는 반드시 NetworkError에 정의된 케이스를 사용합니다.

  • 특히 디코딩 에러를 바로 catch 할 때, NetworkError에 구현된 내용을 사용할 때 주의해주세요.

  • 아래 예시처럼 catch 블록에서 처리하면 됩니다.

do {
    ...
} catch {
    guard let ne = error as? NetworkError else { return print(error) }
    print(ne.log()) // error 로그 출력
    // ne.localizedDescription을 이용한 UI 업데이트 등의 작업
}
do {
    return try JSONDecoder().decode(T.self, from: jsonData)
} catch let decodingError as DecodingError {
    // NetworkError로 변환 후 즉시 로그 출력
    let networkError = NetworkError.decodingError(decodingError)
    print(networkError.log())
}


8. 에러 발생 시 로그 예시

디코딩 오류

decodingError("debugDescription")-"Project/MyService.swift#fetchData"

404 Not Found

notFound(404)-"Project/MyService.swift#fetchData"

작업 취소

taskCancelled-"Project/MyService.swift#fetchData"