[iOS] NSCoding과 Codable은 무엇이 다른가

Objective-C와 Swift를 함께 사용하다 보면 NSCoding과 Codable을 비슷한 기능으로 오해하기 쉽다. 둘 다 값을 인코딩하고 복원하지만 목적과 데이터 형식이 다르다.

NSCoding: 객체 그래프 아카이빙

NSCoding은 객체를 NSCoder로 인코딩하고 디코딩하기 위한 Foundation 프로토콜이다. 일반적으로 NSKeyedArchiver와 함께 객체 그래프를 파일이나 Data로 보관할 때 사용한다.

@interface Person : NSObject <NSSecureCoding>
@property (nonatomic, copy) NSString *name;
@end

@implementation Person
+ (BOOL)supportsSecureCoding { return YES; }

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.name forKey:@"name"];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _name = [coder decodeObjectOfClass:NSString.class forKey:@"name"];
    }
    return self;
}
@end

새 코드에서는 허용할 클래스를 검증하는 NSSecureCoding과 보안 디코딩 API를 우선한다. 신뢰할 수 없는 아카이브를 아무 클래스로나 복원하면 객체 치환 문제가 생길 수 있다.

Codable: 외부 표현과의 변환

Swift의 Codable은 Encodable과 Decodable을 합친 별칭이다. JSON 전용 프로토콜은 아니며, 선택한 Encoder와 Decoder에 따라 JSON, Property List 등으로 변환할 수 있다.

struct Person: Codable {
    let name: String
}

let person = Person(name: "yep")
let data = try JSONEncoder().encode(person)
let decoded = try JSONDecoder().decode(Person.self, from: data)

컴파일러가 저장 프로퍼티에 대한 구현을 합성할 수 있어 Swift 값 타입과 잘 맞는다.

무엇을 선택할까

요구 사항 적합한 선택
서버 JSON API와 통신 Codable + JSONEncoder/JSONDecoder
Swift 구조체를 명시적 형식으로 저장 Codable
기존 Objective-C 객체 그래프 아카이브 NSSecureCoding
Cocoa 프레임워크가 NSCoder를 요구 NSCoding 또는 NSSecureCoding

NSCoding 결과를 JSON으로 바꾸는 것은 프로토콜의 목적이 아니다. JSON이 필요하면 각 필드를 JSON 모델로 명시적으로 매핑하거나 Swift 모델에 Codable을 적용해야 한다. 반대로 오래 보관할 데이터는 어느 방식을 사용하든 스키마 변경과 마이그레이션 전략이 필요하다.

참고

댓글남기기