프로그래밍iOS 개발자

Codable 프로토콜은 Swift에서 어떻게 구현되며, 언제 사용하는 것이 좋고, 자동 및 수동 직렬화 시 어떤 세부사항을 고려해야 합니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

Codable 프로토콜은 JSON 또는 Property List와 같은 데이터의 직렬화 및 역직렬화 프로세스를 간소화하기 위해 Swift에서 도입되었습니다. 이전에는 이를 위해 수동으로 파싱을 구현해야 했으며, 이는 많은 작업을 요구하고 오류에 취약하며 읽기가 어려웠습니다. 이 프로세스의 자동화는 더 안전하고 간결한 코드를 개발할 수 있게 해주었습니다.

문제는 자동으로 Codable을 적용할 경우 모든 속성이 또한 Codable이어야 하며, 이 체인의 어떤 위반 사항이 있을 경우 명시적인 디코딩 및 인코딩 메서드를 구현해야 한다는 것입니다. 또한 구조체 및 상속이 있는 클래스, 키 매핑을 사용자 지정할 때의 특성이 있습니다.

해결책은 간단한 모델에 대해 Codable을 사용하고 어떤 속성이 직렬화되어야 하는지를 엄격하게 살피며, 복잡한 모델의 경우 encode(to:) 및 init(from:) 메서드를 구현하고 CodingKeys를 사용하여 키 매핑을 수행하는 것입니다.

코드 예:

struct User: Codable { let id: Int let name: String let email: String? enum CodingKeys: String, CodingKey { case id case name = "full_name" case email = "contact_email" } }

주요 특징:

  • 모든 속성이 Codable 프로토콜을 따를 경우 자동 직렬화를 제공합니다.
  • CodingKeys를 사용하여 속성과 외부 키의 매핑을 구성할 수 있습니다.
  • 계산 속성이나 특정 직렬화 로직이 있는 경우 수동 구현이 필요합니다.

함정 질문.

상속이 있는 클래스와 자식의 고유 속성이 Codable을 사용해 자동으로 올바르게 직렬화될 수 있을까요?

아니요, Swift는 상속이 있는 클래스의 경우 자식 클래스에서 encode(to:) 및 init(from:)을 수동으로 구현해야 하며, 그렇지 않으면 부모 및 자식의 속성이 올바르게 직렬화되지 않습니다. 예:

class Animal: Codable { let species: String } class Dog: Animal { let breed: String enum CodingKeys: String, CodingKey { case breed } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) breed = try container.decode(String.self, forKey: .breed) try super.init(from: decoder) } override func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(breed, forKey: .breed) try super.encode(to: encoder) } }

구조체의 속성이 private으로 표시되고 자동 Codable이 사용될 경우 어떻게 됩니까?

속성이 private이고 명시적인 CodingKeys로 var/let으로 선언되지 않은 경우, 해당 속성은 직렬화되거나 역직렬화되지 않습니다. 따라서 private 속성에는 반드시 CodingKeys를 선언하고 필요할 경우 이 열거형에 포함시켜야 합니다.

오직 디코딩만을 위해 Codable을 구현할 수 있을까요?

네, 이를 위해 init(from:)만 구현하고 타입을 Codable 대신 Decodable 프로토콜에 따르게 하면 됩니다.

struct ReadOnlyModel: Decodable { let id: Int }

일반적인 오류 및 안티 패턴

  • 오류: 비즈니스 로직이나 외부 소스에 없는 캐시 가능한 필드가 있는 모델에 Codable을 사용하는 경우.
  • 안티 패턴: Codable이 명시적인 메서드 구현 없이 중첩 및 상속의 모든 경우를 자동으로 처리할 것이라고 기대하는 경우.

실제 사례

** 부정적인 케이스

개발자가 모델에 계산 속성을 추가하면서 자동 Codable 처리를 기대하며 사용자 지정 encode 및 decode 메서드를 구현하지 않았습니다.

장점:

  • 빠른 프로토타이핑, 코드 양 감소.

단점:

  • 데이터가 완전히 직렬화되지 않아 읽기/쓰기에 문제가 발생하고, 버그가 발생하며, 항상 명확하게 확인되지 않습니다.

** 긍정적인 케이스

개발자가 복잡한 경우에 대해 사용자 지정 CodingKeys 및 사용자 지정 encode/decode 메서드를 구현하여 속성이 키와 일치하지 않거나 계산된 필드가 있을 경우, 상속이 적용됩니다.

장점:

  • 직렬화에 완전한 제어, 서버와 명시적으로 동기화된 로직이 있으며, 양쪽에서 변화에 대한 투명한 지원을 제공합니다.

단점:

  • 약간의 코드 양 증가 및 유지 관리에 소요되는 시간, 그러나 가독성이 높아지고 버그가 적어집니다.