시간이 많이 없어 주 정보원은 GPT와의 스무고개뿐이라, 이중 검증이 아직 덜 된 부분이 많구요..!
제가 생각하기에 확실하지는 않지만 "이게 맞는 것 같다"싶은 부분들로 글을 쓰겠습니다.
1. Persistent Store 초기화 전 Entity(context:) 사용 시 크래시 발생
An NSManagedObject of class ‘BookEntity’ must have a valid NSEntityDescription.
이 메시지와 함께 crash가 났는데
담기 버튼을 누르면 코어 데이터에 CartBookEntity를 저장하는 로직을 실행하도록 하는 과정에서 문제가 생겼다.
관련 코드를 보며 아직 코어 데이터 생태계에 아무것도 몰라서 찾아봐도 무슨 말인지 모르겠고 gpt랑 스무고개를 진행했다.
"persistentContainer가 아직 초기화되기 전에 BookEntity(context:)를 호출한 경우"가 원인이 되겠다.
해당 컴포넌트 선언한 곳을 보면, lazy var로 이걸 실제로 써야할때 생성하도록 한다.
코어 데이터 관련 비즈니스 로직에선 viewContext를 여기서 추출한 걸 가져다가 쓰도록 구현했는데, 이때 생성이 시작되고 생성이 완료되면 context를 가져다가 엔티티를 만들고 관련 로직을 실행할텐데 ...
문제 시점 코드를 보면 Entity를 생성할때 바로 context만 주고 생성했다.
크래시 상황에서 보여주는 메시지를 보면 알 수 있듯이 Entity를 만들기 위한 과정 속엔 NSEntityDescription이라는 객체가 필요하다.
NSManagedObjectModel의 문서 속 내용인데, 하나 혹은 그 이상의 NSEntityDescription을 포함하고 있다고 함.
결국 NSEntityDescription을 쓰기 위해선 그걸 가지고 있는 NSManagedObjectModel이 메모리에 올라와야하고, 그걸 또 가지고 있는 객체는 NSPersistentContainer. 앞서 말한 모든 객체들에 있어서 하위 객체들이 메모리 상에 올라가고 상위로 연결되며 준비가 된다.
근데 일단 lazy var로 persistentContainer를 생성하게 되면 방금 말한 순서대로 올라오기 시작할테고 결국 이것들이 메모리에 올라와서 건강하게 엔티티를 쓸 준비를 할 수 있기도 전에, Entity(context: context) 방식을 쓰게 되면 내부적으로 description을 자동으로 호출해서 가져오려고 하고 만약 그 시점이 아직 NSManagedObjectModel이나 PersistentStore가 로드되지 않은 상태라면..?
네...
쨋든 이걸 해결하기 위해서 엔티티 생성 메서드를 다른 방향으로 돌렸다.
해결한 코드
코드를 보면 기존 Entity 생성 방식과 다르게 description과 context를 넣어서 하고 그 description을 명시적으로 준비하도록 한다.
이건 무조건이다!는 아닌데 아마 크래시가 났던 이유가 여기 있는 것 같은게, Description 또한 결국 lazy하게 로드가 되는데 그걸 미리 guard let ~~ 를 통해서 불렀고 이를 받아온 다음에 Entity 생성 때 넣어줘서 문제가 없었던 것 같다.
그럼 기존 방식은? 바로 엔티티 만드는 과정에서 Description을 가져오다보니 로드되던 중에 끝내버리던 로드가 되기도 전에 생성을 끝내버리려고 해서 크래시가 나는게 아닐까!라고 결론지었다.
2. Transformable 타입 애트리뷰트의 Transformer 관련 경고
An NSManagedObject of class ‘BookEntity’ must have a valid NSEntityDescription.
이게 거의 몇십줄이떠서 깜짝 놀라 해결해봤는데, 경고 메시지를 요약 시켰더니 다음과 같았다.
"Core Data에서 Transformable 타입을 사용하는 경우, 어떤 방식으로 데이터를 인코딩/디코딩(직렬화/역직렬화)할지를 나타내는 Value Transformer를 명시하지 않았을 때 발생하는 경고."
기본적으로 Core Data는 Transformable 타입의 값을 저장할 때 NSKeyedArchiver / NSKeyedUnarchiver를 사용하는데, iOS 12이후부터 보안상 이유로 NSSecureCoding을 강제하는 NSSecureUnarchiveFromDataTransformer 사용을 권장하게 됐다고 한다.
기존 NSKeyed~ 방식은 타입 체크를 하지 않기 때문에 악의적인 객체나 타입이 주입될 수 있는데, NSSecureUnarchiveFromData는 직렬화된 객체가 어떤 클래스인지 명시적으로 지정해야 하며, 예상한 클래스만 디코딩한다고 한다. -> 보안 강화됨
...일단..그렇다!
요렇게 애트리뷰트 인스펙터에 넣어주어 해결했다.
네트워크는 코어 데이터가 아니라 안썼구요, URL 관련 내부적인 정책 변경이 있었던건지는 모르겠으나 관련 이슈도 있어서 이건 다른 포스트로 정리하겠읍니다 !
+ 05.14 내용 덧붙임
아 다시 검증하는데 위로 해결은 어찌저찌 됐는데 그냥 Clean Build를 안해줘서 문제가 됐던 것 같다.....
코어 데이터 내 구조가 바뀌면 앱 빌드를 그대로 해줄때 바로 적용이 안되고 꼭 빌드를 해줘야 하는 것 같아서 이 부분은 시간 날 때 다시
테스트하고 수정해봐야겠다 ㅠ
이번 3레벨... 정말 .. 쉽지 않았다 .. 코어 데이터는 정말 .. 하.. 개인적으로 Rx보다 성가셨습니다 진짜..
'iOS > Swift' 카테고리의 다른 글
[TIL / 25.05.27] 날씨 앱 main 페이지 구조 트러블슈팅 (5) | 2025.05.27 |
---|---|
[TIL / 25.05.18] 의존성 주입 담당 DIContainer를 처음 적용해보았습니다 (4) | 2025.05.18 |
[TIL / 25.05.12] BookSearchApp 트러블슈팅 - 일부 배경색이 투명한 현상 (2) | 2025.05.12 |
[TIL / 25.05.11] RxSwift.. 처음 공부해볼게요 2 (0) | 2025.05.11 |
[TIL / 25.05.08] RxSwift.. 처음 공부해볼게요 1 (0) | 2025.05.08 |