221004 TIL [Realm migration하는 (간단한)방법 - (속성 추가 혹은 제거의 경우)]

Doogie·2022년 10월 4일
0
post-thumbnail

로아랑 프로젝트 진행 중 Realm에 저장되는 객체에 대한 수정 사항이 생겼다
물론 아직 출시 전이라 수정하고서 그냥 어플 삭제하고 다시 빌드하면 되지만 만약 출시를 했다고 가정했을 때 이렇게 DB모델에 수정사항이 생긴다면 마이그레이션을 필수이기에 출시 전 이에 대해 알아보았다

몽고DB의 홈페이지를 보면 마이그레이션 방법에는 크게 두 가지 방법이 있는 것 같은데(아마도?)

첫 째는 간단한 속성 추가나 제거와 같은 경우 사용 할 수 있는 방법이고
둘 째는 조금 복잡한 상황(이미 정해져있는 이름이나 타입의 변경등의 상황에 사용할 수 있는 방법)에서 migrationBlock을 이용하는 방법인데 이 부분은 추후 공부하고 새로 포스팅을 작성해볼 예정이다

1번 방법은 방법은 너무나도 간단하다

[Realm 모델 속성 추가 & 제거]

1. 스키마 버전(schemaVersion) 설정

로아랑의 경우, Realm을 SceneDelegate에서 생성해 주입해주고 있으며 기존 코드는 아래와 같다

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.makeKeyAndVisible()
        
        guard let realm = try? Realm() else {
            window?.rootViewController = UIViewController()
            window?.rootViewController?.showExitAlert(message: "앱 저장소 오류가 발생했습니다.\n앱 재설치 혹은 고객센터로 문의 부탁드립니다.")
            return
        }
        
        let container = Container(storage: AppStorage(LocalStorage(realm: realm)))
        let navigationController = UINavigationController(rootViewController: TabBarViewController(container))
        navigationController.isNavigationBarHidden = true
        window?.rootViewController = navigationController
    }
}

여기서 configuration을 담는 프로퍼티를 만들어주고 그걸 Realm에 할당만 해주면 된다

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.makeKeyAndVisible()
        
        //추가
        let config = Realm.Configuration(schemaVersion: 0)
        Realm.Configuration.defaultConfiguration = config
        
        guard let realm = try? Realm() else {
            window?.rootViewController = UIViewController()
            window?.rootViewController?.showExitAlert(message: "앱 저장소 오류가 발생했습니다.\n앱 재설치 혹은 고객센터로 문의 부탁드립니다.")
            return
        }
        ... 이하 생략 ...

2. DB모델 수정

final class BookmarkUserDTO: Object {
    @Persisted(primaryKey: true) var name: String
    @Persisted var imageData: Data
    @Persisted var `class`: String
    
    var convertedInfo: BookmarkUser {
        return BookmarkUser(name: self.name,
                            image: UIImage(data: imageData) ?? UIImage(),
                            class: self.`class`)
    }
}

현재 BookmarkUserDTO는 위와 같이 정의되어 있는데 만약 여기서 guild라는 프로퍼티가 추가적으로 필요한 상황이라고 가정해보자

final class BookmarkUserDTO: Object {
    @Persisted(primaryKey: true) var name: String
    @Persisted var imageData: Data
    @Persisted var `class`: String
    //추가
    @Persisted var guild: String
    
    var convertedInfo: BookmarkUser {
        return BookmarkUser(name: self.name,
                            image: UIImage(data: imageData) ?? UIImage(),
                            class: self.`class`)
    }
}

이렇게 프로퍼티만 추가하고 실행시키면

아예 실행 단계에서 realm 오류가 발생해 지정해준 얼럿을 띄우게 된다

        let config = Realm.Configuration(schemaVersion: 1)

그런데 1번과정에서 추가해준 스키마 버젼을 위와 같이 올려주기만 하면 정상 실행 된다

아직 guild에 대한 값을 넣는 로직을 만들지 않아 값은 없지만 Realm Studio를 확인 해도 추가 된 모습이다

반대로 다시 guild프로퍼티를 제거하고 스키마 버젼을 다시 한단계 높여 2로 수정하면

이렇게 사라진 모습이다

[모델 추가는 따로 스키마 버젼 설정이 필요 없다!]

사용자가 유저를 검색을 했을 때 최근 검색 기록을 가져오기 위해 RecentUserDTO라는 객체를 추가할 일이 있어

final class RecentUserDTO: Object {
    @Persisted(primaryKey: true) var name: String
    @Persisted var itemLV: String
    @Persisted var `class`: String
}

위와 같은 모델을 만들어줬는데 이 때는 스키마 버젼을 올려주지 않아도 정상적으로 추가되었다

안쓰는 모델 삭제는 어떻게..?

바로 위에서 만들어준 RecentUserDTO라는 모델을 사용할 일이 없어져서 제거 했을 때 xcode내에서는 RecentDTO는 없는 것이지만 Realm Studio에는

없어져야 할 요녀석이 계속 있다...

이 부분은 차차 알아가봐야겠다...!

마치며...

사실 지금단계에서는 필요 없는 내용이긴하다
어차피 출시할때는 스키마 버젼 0으로 출시를 할 것이고 사용자들은 그 때 새로 설치를 하게 될 것이기 때문이다
그럼에도 나중에 기능이 추가되면서 새로운 속성이 추가 혹은 제거될 수도 있기에 수정을 하였으며 수정이 될 수도 있으니 두 번째 방법 또한 익혀놔야겠다

참고자료
https://www.mongodb.com/docs/realm/sdk/swift/model-data/change-an-object-model/

profile
끊임없이 문을 여는 개발자

0개의 댓글