[iOS-Swift] 에러처리

TIL 15일 차 - Swift 문법 에러처리

Swift는 프로그램이 정상적으로 실행되지 않을 때 발생할 수 있는 에러를 처리하고 안전하게 대응하는 방법을 제공한다.

 

1. Error 프로토콜

Error 프로토콜은 '이 타입은 에러로 사용할 수 있다'라는 표시이다.

protocol Error {
}
// 내용이 없는 마커(marker) 프로토콜임

 

Error 프로토콜은 보통 enum으로 만든다.

enum NetworkError: Error {
    case invalidURL
    case timeout
    case noConnection
}

그 이유로는 에러는 종류중에 하나이며 행동이 없으므로 enum이 적합하다.

 

 

2. do, try, catch 구문 사용하여 오류 처리 및 관리하기

- try 키워드를 사용해 에러가 발생할 가능성이 있는 코드를 실행하고, 에러가 발생하면 catch 블록에서 해당 에러를 처리할 수 있음

- catch 블록에서는 특정 오류만 처리 가능함

 

3. throws

- 함수가 에러를 던질 수 있다는 것을 명시할 때 사용함

- 함수의 파라미터 뒤에 throws 키워드를 작성

- 함수 내부에서 에러가 발생하면 throw를 사용해 에러를 던질 수 있음

- 에러는 함수를 호출한 곳에서 처리해야 함

 

// 에러를 던지는 함수 선언
// 파라미터 괄호 뒤에 throws를 입력
func fetchData(url: String) throws -> String {
    guard let url = URL(string: url) else {
        throw NSError(domain: "Invalid URL", code: 404, userInfo: nil)
    }
    return "Data"
}
// NetworkError라는 이름의 Error 프로토콜 생성
enum NetworkError: Error {
    case badURL(String)
    case requestFailed
}

// do, try ,catch를 사용하여 에러 핸들링하는 코드
do {
	// 에러는 함수를 호출하는곳에서 처리
    let data = try fetchData(url: "https://invalid.url") 
    print("Data received: \(data)") // 오류가 없으면 프린트문 출력
} catch NetworkError.badURL(let stringValue) {
    print("Invalid URL")
    print(stringValue)
} catch NetworkError.requestFailed {
    print("Request failed")
} catch {
    print("Unknown error: \(error)") // 위의 catch에서 잡히지 않은 모든 에러
}

 

마지막 catch문에 대해서 더 자세히 봐보자

catch {

     print("Unknown error: \(error)")

}

이 코드가 어떻게 위의 catch에서 잡히지 않은 모든 에러를 잡을 수 있냐면..

 

catch { }는 사실

catch let error {  }의 축약형이다.

즉, catch { } 안에서는 스위프트가 자동으로 let error: Error를 만들어준다.

따라서 error를 바로 쓸 수 있는 것이다.

 

 

4. try?, try! 와 같이 에러를 간편하게 처리할 수 있는 방법을 제공함

- try? 는 에러가 발생하면 nil을 반환하여 간단하게 처리할 수 있지만 에러의 구체적인 원인을 파악하기 어려움

- try! 는 에러가 발생하면 앱이 크래시가 나므로 조심해서 사용해야 함

- do catch를 사용하지 않아도 됨

// do catch를 생략하고 try? try!를 사용하는 방법

let data = try? fetchData(url: "https://invalid.url")
// try?는 에러가 발생하면 nil을 반환
print(data ?? "NO data") // 에러가 발생하면 nil대신 No data 출력

let data = try! fetchData(url: "https://valid.url")
// try!는 에러가 발생하면 크래시 발생
pritn(data)