오늘은 Swift 5에서 등장한 Result Type에 대해서 알아보자.
우선 Apple 공식 문서를 봐보자.
https://developer.apple.com/documentation/swift/result
Result Type은 아래와 같이 정의되어 있다.
@frozen
enum Result<Success, Failure> where Failure : Error
이의 특징으로는 Generic Enumeration이라는 것. 경우에 따라 연관값을 포함하고, 성공과 실패를 나타내는 값이다.
우선 기존 에러처리 방법을 보자.
일반적인 에러처리는 다음과 같이 진행했다.
- 열거형 선언 후
- 함수 제작
- do, try, catch문 정의
enum MyError: Error {
case MentalError
case HealthError
case EtcError
}
struct MyEmotion {
var name: String
var feeling: Int
var health: String
}
let foden = MyEmotion(name: "foden", feeling: 10, health: "Bad")
func checkMyErrors(a: String) throws {
if ...
throw MyError.MentalError
if ...
throw MyError.HealthError
...
}
do {
try checkMyErrors(a: foden)
} catch MyError.MentalError {
print(...)
} catch MyError.HealthError {
print(...)
}
이와 같이 3개의 과정을 거치다보니 명확하게 코드 진행사항을 알기 어려운 단점이 있다.
이를 개선하고자 나온 게 바로 Result Type이다.
위의 코드를 개선하면
enum MyError: Error {
case MentalError
case HealthError
case EtcError
}
struct MyEmotion {
var name: String
var feeling: Int
var health: String
}
let foden = MyEmotion(name: "foden", feeling: 10, health: "Bad")
func checkMyErrors(a: String) -> Result<Bool, MyError> {
if ...
return .failure(.MentalError)
if ...
return .failure(.HealthError)
...
return .success(true)
}
let isOkay = checkMyErrors(a: foden)
switch isOkay {
case .success(let data):
print(data)
case .failture(let error):
print(error)
}
무언가 간단해 진 거 같은데 명확한 차이를 알아보자
일반 에러처리와 Result Type 사용시 차이점
- 일반 에러처리
- 비정상적인 경우에 에러를 던지고, 실제 함수를 호출하는 부분에서 try, do-catch문으로 처리한다.
- 이에 대한 단점으론 실제 함수를 호출하는 곳에서 에러형식을 특정짓기 어렵다.
- Result Type
- 리턴 타입이 성공(정상적인 경우)과 실패(에러)의 정보를 모두 담을 수 있는 열거형인 Result Type으로 리턴
- 에러를 따로 던질 필요가 없기 때문에 throws 키워드가 필요없다.
- 이에 대한 장점으론 실제 함수 정의 시에 에러 타입을 명시적 선언 / 타입캐스팅이 불필요하다.
Result Type 처리 단계
1. 에러 타입 정의
- Error 프로토콜을 채택하면 정의한 에러 타입 열거형이, 스위프트의 에러 프로토콜 내에 통합된다.
enum MyError: Error {
case MentalError
case HealthError
case EtcError
}
struct MyEmotion {
var name: String
var feeling: Int
var health: String
}
let foden = MyEmotion(name: "foden", feeling: 10, health: "Bad")
2. 함수 정의
- 함수의 내부 정의에서 정상적인 경우 .success(연관값)리턴, 비정상적인 경우(에러) .failure(연관값-에러)리턴하도록 정의
func checkMyErrors(a: String) -> Result<Bool, MyError> {
if ...
return .failure(.MentalError)
if ...
return .failure(.HealthError)
...
return .success(true)
}
3. 결과 처리
- 성공과 실패/에러에 대한 분기처리
- 하나의 열거형 타입을 처리하는 (일반적인) 방식
- 결과 인스턴스를 에러처리방식으로 변환하는 get( )메서드도 제공한다.
let isOkay = checkMyErrors(a: foden)
switch isOkay {
case .success(let data):
print(data)
case .failture(let error):
print(error)
}
음 그래그래… 에러처리 하는 코드를 작성하는데 도움이 되겠구만
그런데 찜찜하게 마지막에 “결과 인스턴스를 에러처리방식으로 변환하는 get( )메서드도 제공” 이게 무슨말일까?
- 우선 알아야되는게 switch문은 성공과 실패의 경우를 모두 다루는 것이다.
아 근데, 나는 성공했을 때만 다루고 싶어, 굳이 실패의 경우를 왜 다루는가? 하면은
if let isOkay = try? isOkay.get() {
print(isOkay)
}
→ 위와 같이 사용할 수 있다.
이것또한 get메서드에 대한 애플의 공식문서 입장을 들어보자.
https://developer.apple.com/documentation/swift/result/get()
- Result타입의 get 메서드는 성공했을 경우만 throw하는 표현식으로 리턴한다.
- get 메서드는 아래와 같이 정의되어 있다.
func get() throws -> Success
참고
https://velog.io/@un1945/Swift-Result-Type
https://developer.apple.com/documentation/swift/result
https://developer.apple.com/documentation/swift/result/get()
'iOS > Swift' 카테고리의 다른 글
About Delegate Pattern (0) | 2024.03.10 |
---|---|
[Swift] Date, Calendar, DateFormatter (1) | 2024.02.25 |
제네릭(Generics) (0) | 2024.02.18 |
비동기 프로그래밍(About Asynchronous) [2] (1) | 2024.02.17 |
비동기 프로그래밍(About Asynchronous) [1] (0) | 2024.02.16 |