다음 애플 문서를 참고했습니다.
Object archiving
A collection of short articles on the core concepts, patterns, and mechanisms in Cocoa programming.
객체 아카이빙
- 아카이빙은 객체 그래프를 응용 프로그램 간에 1)저장하거나, 2) 전송가능한 타입으로 변환하는 과정을 말합니다.
- 아카이빙의 최종 결과인 아카이브는 객체의 ID, 캡슐화된 값, 다른 객체와의 관계가 기록된 byte stream입니다.
- 아카이빙의 반대인 언아카이빙은 아카이브를 가져와서 다시 원래의 객체로 되돌리는 과정입니다.

- 아카이브는 객체를 영속성으로 만드는 일반적인 방법을 제공합니다.
- 객체 데이터를 특수한 파일 형식으로 기록하는 대신에, 파일로 기록할 수 있는 아카이브에 모델 객체를 저장하는 경우가 많습니다.
- 또한 이를 통해서 다른 애플리케이션으로 전송할 수도 있습니다. ex) 복사, 붙여넣기
- 인스턴스가 아카이브에 포함되려면 해당 클래스는 NSCoding 프로토콜을 채택해야하고 해당하는 메서드를 구현해야 합니다. →
init(coder:)
,func encode(coder: NSCoder)
- 아카이브는 캡슐화된 데이터와 객체 타입을 함께 저장하므로, 다시 디코딩되면 원래의 인코딩된 객체와 동일한 클래스가 됩니다.
Archiver
Foundation에는 아카이빙, 언아카이빙을 위한 클래스가 존재합니다.
- NSKeyedArchiver, NSKeyedUnarchiver
- 문자열 키를 이용해서 인코딩, 디코딩할 데이터의 키로 사용합니다.
- 특히 객체를 아카이빙/언아카이빙 하는데에 선호되는 방식입니다.
- NSArchiver, NSUnarchiver
- 현재는 deprecated 되었습니다.
- 오래된 고전 방식의 아카이빙으로, 순차적인 순서로 객체를 인코딩 합니다.
- 언아카이빙도 인코딩과 마찬가지로 순서대로 객체를 디코딩합니다.
iOS 12.0 이후의 아카이브 생성
- 기존에는 NSKeyedArchiver의 static 메서드인
archiveRootObject:toFile:
메서드를 사용하여 아카이빙 합니다. 해당 메서드의 인자로 넣는 객체가 객체 그래프의 루트가 되고, 재귀적으로 해당 루트 객체의 NSCoding 프로토콜을 준수하는 하위 객체들의encode()
메서드가 호출되어 아카이빙 됩니다.
- 그러나 iOS 12.0 이후로 해당 메서드는 deprecated 되었고, NSKeyedarchiver의 static 메서드인
archivedData(withRootObject:requiringSecureCoding)
메서드를 사용하여 아카이빙 해야 합니다.
- 위 메서드는 아카이빙하려는 객체 그래프의 각 객체가 기존의 NSCoding 프로토콜이 아닌, 해당 프로토콜을 상속한 NSSecureCoding 프로토콜을 준수해야 합니다.
NSSecureCoding
- NSSecureCoding 프로토콜은 객체 대체 공격에 대항하여 (보안 문제) 강력한 방식으로 인코딩, 디코딩이 가능케 하는 프로토콜 입니다.
- 역사적으로는 다음과 같이 디코딩 방식이 이뤄졌습니다.
if let object = decoder.decodeObjectForKey("myKey") as MyClass { // ...succeeds... } else { // ...fail... }
- 이런 방식은 디코딩된 객체의 클래스 타입을 확인하려고 할 때, 해당 객체가 이미 생성(디코딩)되어 있고, 해당 객체가 컬렉션 클래스의 일부인 경우에는 객체 그래프에 삽입되기 때문에 객체 대체 공격으로부터 안전하지 않게 됩니다.따라서 NSSecureCoding을 준수하여 이런 방식을 막을 수 있습니다.
- NSSecureCoding은 다음을 준수해야 합니다.
init(coder:)
생성자를 오버라이드 하지 않는 객체는 NSSecureCoding을 아무런 변경을 하지 않고 준수할 수 있습니다. (준수하는 다른 객체의 서브클래스일 경우)
init(coder:)
생성자를 오버라이드 하는 객체는 반드시decodeObjectOfClass:forKey:
메서드를 통해 디코드 해야합니다.let obj = decoder.decodeObject(of:MyClass.self, forKey: "myKey")
- 추가적으로,
supportsSecureCoding
프로퍼티가 true를 리턴하도록 오버라이드 해야합니다.
- 추가적으로,
iOS 12.0 이후의 언아카이브
- 위에서 NSKeyedArchiver의
archiveRootObject:toFile:
메서드가 deprecated됨에 따라, 이를 언아카이빙 하는 NSKeyedUnarchiver의unarchiveTopLevelObjectWithData(:)
메서드도 deprecated 되었습니다.
- 대신 NSKeyedUnarchiver의
unarchivedObject(ofClass:from:)
메서드를 통해 언아카이빙 시킬 수 있습니다.
- 해당 메서드의 인자로 넣는 객체가 객체 그래프의 루트가 되고, 재귀적으로 해당 루트 객체의 NSSecureCoding 프로토콜을 준수하는 하위 객체들의
init?(coder:)
메서드가 호출되어 언아카이빙 됩니다.
Uploaded by N2T