Decodable을 이용한 API 파싱

이건준·2022년 6월 30일
0

1. 문제제기

  • Connect 앱을 개발하게되면서 기존에 항상 Decodable을 이용해서 데이터를 파싱하였는데 사실 어느정도 외워서 코드를 했어서 이번에 좀더 이를 위한 이유에 대해서 대략적으로나마 감을 잡고자 정리하려한다

2. 문제해결

1. 코드

struct MapAddress: Decodable {
    let address: Address?
    let addressName: String
    let addressType: String?
    let roadAddress: String?
    let x: String
    let y: String
    
    enum CodingKeys: String, CodingKey {
        case address, x, y
        case addressName = "address_name"
        case addressType = "address_type"
        case roadAddress = "road_address"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.address = try? values.decode(Address.self, forKey: .address)
        self.addressName = (try? values.decode(String.self, forKey: .addressName)) ?? ""
        self.addressType = try? values.decode(String.self, forKey: .addressType)
        self.roadAddress = try? values.decode(String.self, forKey: .roadAddress)
        self.x = (try? values.decode(String.self, forKey: .x)) ?? ""
        self.y = (try? values.decode(String.self, forKey: .y)) ?? ""
    }
}
  • 위 코드를 보면은 누구나 Decodable을 이용해보았다면 누구나 해봤을 코드이다, 그렇다면 이렇게 코드한 이유에 대해서 하나하나 알아가보자

1. 데이터파싱을 위한 구조체선언시 옵셔널을 사용하고 안 사용하고의 기준은 무엇일까 ??

  • 사실 이 부분에 대해서 이전에는 KeyNotFound에러가 발생할 수 있기때문에 모든 멤버들을 옵셔널로 선언한 이후에 decode하였다
    -> 하지만 이 같은 경우는 모든 데이터에 대해 옵셔널바인딩을 해줘야하는 단점이 존재한다

  • 내가 개발하는데 있어서 사용하고자하는 데이터와 그렇지않은 데이터를 기준으로 옵셔널을 선언하는 기준으로 잡는게 어떨까 생각해보았다

  • 사용하려는 데이터는 그대로, 사용하지않는 데이터를 옵셔널을 붙여주어서 사용하지않은 데이터가 내려오지않아 nil값이여도 상관이 없고 사용하고자하는 데이터는 그대로 받아오기때문에 사용할때 옵셔널 바인딩을 거치지않아도 된다는 장점이 있다

2. 그렇다면 만약에 사용하고자하는 데이터가 존재하지않은 경우도 있을까 ??

  • 우리가 사용하려는 API들은 항상 정해져있는 틀이 존재하고 우리는 이에 맞춰서 Decodable하기위한 구조체를 정의한다

  • 흔치 않은 일이지만 만약에 API의 데이터 구조가 변경된다면 기존에 정의되있는 틀에서는 Decodable시 찾지못하게되어 KeyNotFound에러가 발생할 수 있다

  • 이와 같은 일이 있기에 init(decoder:) 생성자를 이용하여 디폴트값을 넣어준다면 우리는 API의 데이터구조에 어긋나더라도 저 생성자를 통해 디폴트값을 넣어 가지게되기에 런타임크래시가 날 위험이 감소하게된다

0개의 댓글