꿈돌이랜드

[iOS] 객체 아카이빙과 iOS 12.0 이후의 변화 본문

Programming/iOS

[iOS] 객체 아카이빙과 iOS 12.0 이후의 변화

loinsir 2023. 9. 26. 14:55
반응형

다음 애플 문서를 참고했습니다.

Object archiving
A collection of short articles on the core concepts, patterns, and mechanisms in Cocoa programming.
https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Archiving.html

객체 아카이빙

  • 아카이빙은 객체 그래프를 응용 프로그램 간에 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

반응형