encoder.keyEncodingStrategy 이해좀 해보자

김재형·2024년 5월 2일
0
post-custom-banner

상황 설명 -
결제 API를 구성하고 테스트하는 도중 401에러가 발생 했었습니다.
정확한 에러 내용은 공개할 수 없지만, 요청이 잘못 되었다는 대략적인 내용입니다.

Encoding 모델이 잘못되었거나, 요청할 때 빠진 부분이 있는 건지 확인하는데 많은 시간을 소모했습니다. 문제의 원인은 다음과 같았습니다…

encoder.keyEncodingStrategy = .convertToSnakeCase

Encoding에 대해 다시 공부해야겠습니다~

인스턴스를 Json 형식으로 바꾸는 것? 알죠 알죠~!

encodingModel

struct Person: Encodable {
    var firstName: String
    var lastName: String
}

JSONEncoder

Swift에서는 JSONEncoder를 사용해 Encodable 타입의 인스턴스를
JSON 데이터로 변환할 수 있습니다.
모델의 프로퍼티를 JSON 키와 매칭시키고, 해당 데이터를 JSON 형식의 Data 객체로 만들어 줍니다.

let encoder = JSONEncoder()
let person = Person(firstName: "Bren", lastName: "Din")
let jsonData = try encoder.encode(person)

keyEncodingStrategy란?

JSONEncoder님은 옵션이 있으셔요!

  1. .useDefaultKeys:
    • 기본 설정으로, Codable 구조체나 클래스의 프로퍼티 이름을 JSON의 키로 직접 사용합니다.
    • 예: struct { var firstName: String } 는 JSON에서 {"firstName": "value"}로 인코딩됩니다.
  2. .convertToSnakeCase:
    • 프로퍼티 이름을 스네이크 케이스(Snake Case)로 변환하여 JSON 키로 사용합니다.
      이는 일반적으로 카멜 케이스(Camel Case)로 작성된 프로퍼티 이름을 스네이크 케이스로 자동 변환해 주며, 주로 백엔드 API와의 연동 시 사용됩니다.
    • 예: struct { var firstName: String }는 JSON에서 {"first_name": "value"}로 인코딩됩니다.
  3. .custom((CodingKey) -> CodingKey):
    • 클로저를 통해 각 프로퍼티의 이름을 원하는 방식으로 매핑할 수 있습니다.
      클로저는 각 CodingKey에 대해 호출되며, 클로저에서 반환한 CodingKey
      JSON 키 이름으로 사용합니다.

그니까 뭐가 문제인데?

저는 해당 인코딩 모델에서 코딩키를 통해 이름을 정의해 사용하고 있었습니다.

// 결제 영수증 검증
struct PaymentsModel: Codable {

    let impUID: String
    let postID: String
    let productName: String
    var price: Int

    enum CodingKeys: String, CodingKey {
        case impUID = "imp_uid"
        case postID = "post_id"
        case productName
        case price
    }

    init(impUID: String, postID: String, productName: String, price: Int) {
        self.impUID = impUID
        self.postID = postID
        self.productName = productName
        self.price = price
    }

    init(from decoder: any Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.impUID = try container.decode(String.self, forKey: .impUID)
        self.postID = try container.decode(String.self, forKey: .postID)
        self.productName = try container.decode(String.self, forKey: .productName)
        self.price = try container.decode(Int.self, forKey: .price)
    }
}

해당 코드를 인코딩할 때, 카멜 케이스 설정을 주면 어떻게 될까요?

convertToSnakeCase의 문제점

    let impUID: String
    let postID: String
    let productName: String
    var price: Int

    enum CodingKeys: String, CodingKey {
        case impUID = "imp_uid"
        case postID = "post_id"
        case productName
        case price
    }

위의 코드에서
case impUID = "imp_uid"
case postID = "post_id"

이 두 친구는 문제가 발생하지 않았습니다.
그런데, let productName: String 부분은 어떻게 될까요?

productName 키는 카멜 케이스에서 스네이크 케이스로 변환되어
"product_name"으로 바뀌게 됩니다.
내가 바라지도 않았었는데...>!!!!!

encoder.keyEncodingStrategy = .useDefaultKeys

회고

개발 과정에서 발생하는 간단한 실수가 예상치 못하게 시간이 길어졌습니다.. ㅠㅠ
실제 회사 프로젝트 였다면 더 큰 문제로 이어질 수 있었을거라고 생각합니다.
이번 경우처럼, JSONEncoderkeyEncodingStrategy 설정이 잘못되어
예상치 못한 API 오류를 유발한 것은, 자칫 큰 프로젝트 지연의 원인이 될 수 도 있구요
단순히 새로운 기술을 익히는 것 뿐만 아니라, 기존의 기술들 을 충분히 이해 하고 작업할
능력이 필요 하겠구나 를 다시한번 생각하게 하는 시간이였습니다.

profile
IOS 개발자 새싹이
post-custom-banner

0개의 댓글