[Swift] enum에 정의되지 않은 값으로 디코딩을 시도할 때 발생하는 문제

Decoding enum with invalid value

문제 상황

위와 같이 정의된 ResponseModel로 data를 디코딩을 한다고 해보자. 이때 들어오는 data 중 pageTypeResponseModel 에 정의되지 않은 값이다.

내 예상은 title 에는 정상값이 들어오고, pageType은 nil 이 들어오는 것이었다.

결과는?

둘다 nil 이 찍혀버린다 ㅎ;

해결 방법

init(from decoder: Decoder) throws 를 이용한 커스텀 디코딩이 필요하다.

1. enum 안에 init(from:) 구현

위와 같이 case unknown 을 추가로 선언해두고, 정의된 RawValue 와 맞지 않으면 .unknown 으로 매핑시켜준다.

2. Model 안에 init(from:) 구현

1번 방법의 경우 커스텀 디코딩을 구현할때 self 에 optional 값을 할당할 수 없기 때문에 무조건 unknown 등으로 매핑되게 해야한다. 따라서 pageType 이 nil 이 될 경우가 없다.

정의되지 않은 enum 값 들어왔을때 pageType 값이 nil 이 되게 하려면, ResponseModel 에서 커스텀 디코딩을 구현한다. 이곳에서는 pageType 에 optional 값을 할당할 수 있기 때문이다.

다만 보다시피 ResponseModel에 선언된 다른 값들도 일일이 디코딩이 필요하다는 단점이 있다. 어쨌든 결과는 아래와 같이 찍힌다.

이외에 추가적인 다른 방법들이 궁금하면 아래 사이트들을 참고하자.

추가 배경 지식 — json decode와 에러 핸들링 (feat. try)

기본적으로 iOS에서는 json 을 디코딩 하기 위해 아래와 같이 JSONDecoderdecode 함수를 이용한다.

이때 decode 함수는 throw 를 던질 수 있기 에러 핸들링이 필요하다.

1. try catch

기본적으로 try catch 를 통해 에러 핸들링을 할 수 있다.

정의되지 않은 enum 값이 들어왔기 때는 다음과 같은 error가 프린트 된다.

2. try?

try catch 이외에도, Swift에서는 try? 의 사용을 통해 catch의 상황에서 변수에 nil을 할당하는 방법을 제공한다. (위의 예시에서 쓴 방법)

이때 title 값은 json에서 제대로 들어왔음에도 불구하고, nil이 프린트 되는 것을 확인할 수 있다. 즉 정의되지 않은 enum 값이 들어오면 나머지 데이터도 디코딩하지 못하는 상황인데, 만약 제대로 들어온 title 값만 받기 위해서는 별도의 위에서 설명한 디코딩 처리가 필요하다.

3. try!

또한 try! 와 같이 무조건 유효한 값이 들어옴을 가정하고 변수에 값을 할당할 수도 있는데, 이때 정의되지 않은 enum 값이 들어오면 크래시가 발생한다.

결론적으로 Swift 에서는 json을 디코딩하는 다양한 방법이 존재하고, 이에 따라 정의되지 않은 enum 값이 들어올때 아래와 같은 상황들이 발생할 수 있다.

  • 전체 결과 빈 값으로 들어옴 (try?)
  • 앱 크래시 (try!)
  • 별도 에러 처리 (try catch)

참고

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store