프로그램의 에러 조건에서 응답하고, 복구하는 프로세스
일부 작업(디스크 파일 I/O 등)은 항상 실행이 완료되거나, 유용한 출력을 생성하는 것을 보장하지 않는다.
이 때 적절한 응답을 위해 에러의 원인을 쉽게 알아낼 수 있다.
Error의 상호 운용
Swift의 에러 처리는 Cocoa와 Objective-C의
NSError
을 사용하는 에러 처리 패턴과 상호 운용
에러는 Error
프로토콜을 준수하는 값 타입
enum
은 에러 조건을 모델링하는데 특히 적합enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
// 코인이 5개 더 필요하다는 것을 쉽게 인지
에러 발생 시 주변 코드에서 에러 처리를 담당
Swift의 에러 처리 방법은 크게 4가지로 구분
throw
)do-catch
구문을 사용try?
)try!
)
throw
의 성능Swift에서의 에러 처리는 다른 언어의 에러 처리와 다르게,
계산 비용이 많이 드는 호출 스택 해제가 포함되지 않음
따라서throw
의 성능은return
과 유사
throws
키워드를 함수의 선언 중 파라미터 부분 뒤에 작성해 에러가 발생할 것을 선언
throws
키워드로 선언된 함수를 Throwing Function이라고 함
func canThrowErrors(...) throws -> String
func cannotThrowErrors(...) -> String
Throwing Function이 아닌 함수는 함수 내부에서 발생할 수 있는 모든 오류를 처리해야 함
do-catch
구문을 사용하여 코드 블럭 내에서 에러를 처리
catch
뒤에 패턴을 작성하여 처리할 에러를 선택 가능
패턴이 없다면 이는 모든 에러를 수용하고, error
라는 지역 상수로 에러를 바인딩
do-catch
에서 처리되지 않은 에러는 주변에 전파됨do-catch
구문이나 호출한 함수에서 에러를 처리해야 함do-catch
구문에서 에러를 처리해야 함try?
를 사용하여 에러를 옵셔널 값으로 변환
let weatherJsonData = fetchData()
let weather = try? JSONDecoder().decode(Weather.self, weatherJsonData)
print(weather)
// if decode success - Optional(weather)
// if decode fail - nil
가끔 Throwing Function이 에러를 발생시키지 않는다는 것을 잘 알고 있을 때, try!
를 사용하여 호출을 래핑
defer
구문은 현재 코드 블럭이 throw
에 의해 종료되거나, return
및 break
에 의해 종료되거나 하는 방식에 상관 없이 종료되기 직전에 호출
defer
은 구문의 밖으로 이동을 제어하거나(return
, ...) 에러를 발생시킬 수 없음defer
구문은 코드에 작성된 순서와 반대로 실행