열거 타입에 연관 값을 이용하여 활용성과 재사용성을 향상시키는 사례를 살펴보겠습니다. 에러 타입을 정의하기 위해 열거 타입을 활용하는 경우, 아래와 같이 코드를 작성할 수 있습니다.
enum ExpoAppError: Error {
case invalidJSONFileName
case invalidJSONFormat
case foundNil
case numberFormattingFailed
case unknownError
}
extension ExpoAppError: CustomDebugStringConvertible {
var debugDescription: String {
switch self {
case .invalidJSONFileName:
return "📃 존재하지 않는 JSON 파일이에요. 파일 이름을 다시 확인해주세요!"
case .invalidJSONFormat:
return "📑 JSON 형식이 맞지 않아요. 데이터를 다시 확인해주세요."
case .foundNil:
return "😵 이 값은 nil이에요!"
case .numberFormattingFailed:
return "😅 숫자 형식 변환에 실패했어요! 숫자를 다시 확인해주세요."
case .unknownError:
return "𝙛 알 수 없는 에러가 발생했어요!"
}
}
}
그럼 이런 에러는 아래와 같이 반환하거나 던질(throw) 수 있습니다.
static func decode<Decoded>(
to type: Decoded.Type,
from jsonFileName: String
) -> Result<Decoded, ExpoAppError> where Decoded: Decodable {
var decodedResult: Decoded
guard let jsonData: NSDataAsset = NSDataAsset(name: jsonFileName) else {
return .failure(ExpoAppError.invalidJSONFileName) // 에러 반환
}
do {
decodedResult = try jsonDecoder.decode(Decoded.self, from: jsonData.data)
} catch {
return .failure(ExpoAppError.invalidJSONFormat) // 에러 반환
}
return .success(decodedResult)
}
이 경우, 유사한 에러이지만 발생 위치가 다를 경우 이를 특정하기 위해 새로운 에러 케이스를 작성해야 합니다. 하지만 열거 타입의 연관 값(associated value
)를 활용하면 에러와 관련된 값을 에러 메시지에 포함하여 나타낼 수 있으면서도 같은 케이스를 활용할 수 있게끔 할 수 있습니다. 적용은 아래와 같이 하면 됩니다.
enum ExpoAppError: Error, Equatable {
case invalidJSONFileName(String) // 연관값의 타입을 소괄호 내부에 명시
case invalidJSONFormat(String)
case foundNil(String)
case numberFormattingFailed(Int)
case unknownError(String)
}
extension ExpoAppError: CustomDebugStringConvertible {
var debugDescription: String {
switch self {
case .invalidJSONFileName(let fileName):
return "📃 존재하지 않는 JSON 파일이에요. 파일 이름을 다시 확인해주세요! 파일 이름: \(fileName)" // 연관 값 활용
case .invalidJSONFormat(let fileName):
return "📑 JSON 형식이 맞지 않아요. 데이터를 다시 확인해주세요. 파일 이름: \(fileName)"
case .foundNil(let valueName):
return "😵 이 값은 nil이에요! 값 이름: \(valueName)"
case .numberFormattingFailed(let number):
return "😅 숫자 형식 변환에 실패했어요! 숫자를 다시 확인해주세요. 입력한 숫자: \(number)"
case .unknownError(let location):
return "𝙛 알 수 없는 에러가 발생했어요! 발생 위치: \(location)"
}
}
}
static func decode<Decoded>(
to type: Decoded.Type,
from jsonFileName: String
) -> Result<Decoded, ExpoAppError> where Decoded: Decodable {
var decodedResult: Decoded
guard let jsonData: NSDataAsset = NSDataAsset(name: jsonFileName) else {
return .failure(ExpoAppError.invalidJSONFileName(jsonFileName)) // 입력한 파일 이름과 함께 반환
}
do {
decodedResult = try jsonDecoder.decode(Decoded.self, from: jsonData.data)
} catch {
return .failure(ExpoAppError.invalidJSONFormat(jsonFileName))
}
return .success(decodedResult)
}
멋지지 않나요? associated value
를 활용해서 열거 타입을 더 유용하게 활용해봅시다!