ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [iOS] Realm Migration
    🍎iOS 2022. 10. 13. 12:45

     

    안녕하세요 Skyler입니다 :)
    오늘은 마이그레이션에 대해서 배워봤습니다!
    출시 프로젝트에서 제가 Realm 테이블 구조를 잘못 건드렸다가 Crash가 나는 상황이 생겨서 황급히 마이그레이션을 적용해봤는데요!
    덕분에 Crash를 막아서 한시름 놓았습니다😇
    혹시 저처럼 실수하신 분들은 참고하셔서 오류 해결에 도움 되셨으면 좋겠습니다!😊

     

    마이그레이션

    • 새로운 테이블 추가
    • 기존 테이블 - 칼럼 삭제 / 추가 / 이름 변경 / 타입 변경 등 Realm 데이터에 변화가 있을 때 출시 후에 적용해야 함
    • 이전 스키마 버전과 달라지면 무조건 해야 함!
    • if를 통해서 버전마다의 마이그레이션을 해줘야 함!
    • Realm Schmea Version을 체크해보자!

     

    기존 Realm 모두 삭제하고 실행

    let config = Realm.Configuration(schemaVersion: 1, deleteRealmIfMigrationNeeded: true)
    Realm.Configuration.defaultConfiguration = config
    
    • deleteRealmIfMigrationNeeded를 사용하면 기존 렘을 삭제하기 때문에 디버그 시에는 사용해도 되지만 실제 릴리즈시에는 반드시 제거해줘야 함! 제거하지 않으면 사용자들의 렘 데이터가 모두 삭제돼버림..
    • 위에서 schemaVersion은 항상 최신 버전으로 갱신해줘야 함
    • 렘의 테이블 구조를 변경했다가 다시 원래로 돌려줘도 schemaVersion이 달라지기 때문에 마이그레이션이 필요함
    • schemaVersion은 0으로 했다가 100 입력하게 되면 그 사이에 있는 버전 1~99는 사용을 못하게 됨
    • schemaVersion은 마이그레이션을 진행한 횟수와 같음(따로 값을 지정해주지 않는다면!)
    • 위의 코드를 사용하면 디버그 모드 실행 시 테이블 구조가 변경되어도 앱을 삭제하고 재실행하지 않아도 됨!

     

    스키마 버전에 대한 분기 처리

    let config = Realm.Configuration(schemaVersion: 2) { migration, oldSchemaVersion in
        
        if oldSchemaVersion < 1 {
            
        }
        
        if oldSchemaVersion < 2 {
            
        }
    }
    
    • 현재 나의 스키마 버전이 0이라면 1보다 작은 조건을 수행하고 2가 되지 않았기 때문에 또 2보다 작은 조건에 대해 수행함
    • else if를 사용하지 않는 이유는 각각의 스키마 버전마다 다 체크를 하고 넘어가야 하기 때문에 if를 사용함
    • Realm의 초기화 구문의 매개변수 명을 변경하는 것은 상관없음!

     

    Realm 컬럼 이름 변경 시 사용

    migration.renameProperty(onType: Todo.className(), from: "favorite", to: "importance")
    
    • 만약 Realm 컬럼의 이름을 바꾼다면 위 코드와 같이 기존의 이름과 바뀐 이름을 명시해주면 됨!

     

    Realm 데이터 추가 삭제 및 초기값 설정

    migration.enumerateObjects(ofType: Todo.className()) { oldObject, newObject in
        
        guard let new = newObject else { return }
        guard let old = oldObject else { return }
        
        new["userDescription"] = "안녕하세요 \\(old["title"]!)의 중요도는 \\(old["importance"]!)입니다"
        
    }
    
    • 컬럼 단순 추가 삭제의 경우에는 별도 코드가 필요 없음
    • 단, 데이터가 없는 초기값을 설정해야 한다면 위처럼 따로 설정해줘야 함!
    • newObject에는 새로 추가된 데이터 oldObject에는 기존에 있었던 데이터 값들을 통상적으로 사용
    • 만약 컬럼 단순 추가 삭제의 경우에 별도 코드가 없을 경우 추후에 보았을 때 그때 정확하게 어떤 변화가 있었는지에 대해서 알기 어렵기 때문에 주석과 그때그때의 커밋을 해서 기록해서 관리를 하는 것이 좋음

     

    Realm 컬럼의 타입 변경 시 사용

    migration.enumerateObjects(ofType: Todo.className()) { oldObject, newObject in
        guard let new = newObject else { return }
        guard let old = oldObject else { return }
        
        new["importance"] = old["importance"] ?? 4.4
    
    		if old["importance"] < 4 {
    	    new["importance"] = 5.5
    		}
    }
    
    • 타입이 만약 기본 타입에서 옵셔널로 변경되어도 타입 변경에 대한 마이그레이션을 해줘야 함!
    • 타입 변경은 위처럼 기존의 컬럼을 새로운 컬럼에 할당하는 식으로 넣어주면 됨
    • 그리고 타입 변경 시에는 기존의 값들에 대한 처리도 위처럼 if 문으로 처리를 해줘야 함!
    • 만약 기존의 타입이 옵셔널이고 새로운 타입이 옵셔널이 아니라면 위처럼 nil에 대한 값 처리는 해줘야 함

     

    Realm의 테이블마다의 분기 처리 방법

    migration.renameProperty(onType: Todo.className(), from: "favorite", to: "importance")
    migration.enumerateObjects(ofType: Todo.className())
    
    • 테이블이 여러 개라면 위의 onType이나 ofType에서 테이블 명에 명시해주고 해당 테이블에 대한 마이그레이션만 적용해주면 됨!

     

    Realm에 새로 설정한 Configuration 할당

    Realm.Configuration.defaultConfiguration = config
    • 위에서 스키마의 버전 별로 마이그레이션 처리해준 Realm의 Configuration을 나의 Realm에 할당해주는 작업이라고 생각하면 됨!

     

    '🍎iOS' 카테고리의 다른 글

    [iOS] Realm List, EmbededObject  (0) 2022.10.23
    [iOS] Firebase, Push Notification, Messaging  (0) 2022.10.23
    [iOS] Margin, 데이터베이스  (0) 2022.08.22
    [iOS] UIView, NotificationCenter  (0) 2022.08.19
    [iOS] TypeCasting  (0) 2022.08.18
Designed by Tistory.