아삭아삭 iOS 개발

[위클리 발표] Happy Realming 🤗(4)_Communication Across Threads 본문

카테고리 없음

[위클리 발표] Happy Realming 🤗(4)_Communication Across Threads

바닐라머스크 2022. 12. 20. 20:26

이번 포스팅에서는 happy realming 시리즈의 마지막으로 multithreaded 작업에 대해 간단히 소개해보겠습니다!

 

Part3) Communication Across Threads

  1. thread realm instance 전달하기

  2. realm에서의 async/await


  1. thread간 realm instance 전달하기

지난 포스팅들에서 설명한 것처럼 여러개의 thread에서 각각의 realm instance를 새로 생성했다는 전제 하에는

동일한 realm을 열 수 있었습니다.

 

하지만!  realm에서는 (해당 객체들이 생성된 thread를 제외하고는) 다른 thread로 객체들을 보낼 수는 없습니다.

왜냐하면 멀티스레드 환경에서 Realm Database 처리의 주요사항이 바로 객체들이 스레드 제한적(thread-confined)이라는 것이기 때문입니다.

 

보다 자세한 내용은 realm의 MVCC 구조로 설명할 수 있는데요, 아래 아티클에서 그 흐름을 알아볼 수 있습니다.
 

Designing a Database: Realm Threading Deep Dive

So you’ve read the basics on Realm threading. You’ve learned that you don’t need to worry nor do much in order to harness the power of Realm when working with threads, but you’re still itching for more… You want to know how Realm works under the

academy.realm.io

 

하지만!!!(ㅋㅋㅋ) @ThreadSafe property wrapper를 사용하면 이런 thread 제한적인 인스턴스들을 다른 thread로 보낼 수 있습니다.

 

아래 main thread에서 생성한 realm 객체에 대해 background thread에서 해당 객체의 나이정보를 변경해보는 예시를 작성해보았습니다. 

먼저 realm 인스턴스를 하나 생성하고 main thread에서 해당 객체를 추가해주었습니다.

두 번째 이미지에서 보시다시피 PK와 함께 해당 row가 생성되었고, age값은 50으로 생성되었습니다.

 

main thread에서 생성한 객체를 다른 thread보내는 과정을 세 단계로 나누면 아래와 같습니다.

 

Step1)

아래 코드에서는 변경하고자 하는 오리지널 객체(iOSDeveloper)에 대해, 이를 참조하는 변수(iOSDeveloperRef)를 생성해줍니다.

이 때 @ThreadSafe로 객체를 감싸주어야 합니다.

 

Step2)

위에서 생성한 참조변수를 다른 thread로 보내줍니다.

아래 예시에서는 DispatchQueue(label: "background").async 로 background thread로 전달해주었습니다.

 

Step3)

background작업 실행블록 내에서는 전달받은 해당 참조변수(iOSDeveloperRef)를 사용해서 원하는 작업을 해줍니다.

여기서는 해당 객체의 나이정보인 age값을 20으로 바꾸어주었습니다.

 

 

 

  2. realm에서의 async/await

앞에서 설명한 @ThreadSafe와 @MainActor를 사용하면 realm작업에 대한 async/await도 적용이 가능합니다.

Rose라는 이름을 가진 Developer realm 객체에 대해 이름을 Lilac으로 변경해주는 작업을 (realm 공식 문서 참고해서) 아래와 같이 실행해보았습니다.

 

realm에서의 async/await 예시 코드
예시코드 빌드 결과

빌드시에 해당 객체의 이름이 Rose → Lilac 으로 정상적으로 변경은 완료되었지만 에러가 발생하고 있었습니다 흠..

에러발생..

관련해서 에러가 발생한 케이스를 더 찾을 수 있었는데, 이부분에 대해서는 다음 분기에 작업 예정이라는 코멘트를 아래 링크에서 확인할 수 있었습니다!

다음 분기 release notes에서 async/await 관련내용이 있다면 유의해서 재확인할 필요가 있어 보입니다!

 

https://github.com/realm/realm-swift/issues/7737

 

Opening Realm with async/await in actor causes Crash · Issue #7737 · realm/realm-swift

How frequently does the bug occur? All the time Description When using the async variant for opening a Realm try await Realm() inside an actor or and actor marked function (any defined global actor...

github.com

 

 

여기까지 (1)~(4) 4개의 포스팅에 걸쳐서 간단히 Realm threading에 대해 알아보았습니다!

제가 간략히 공유해본 개념과 메서드들 외에도 multithreading 관련해서 serial queue 사용, realm database의 notification, refresh 사용, 객체 'freeze'하기 등 다른 방안들도 있었습니다.

아래 'Threading-Swift SDK-Realm'사이트에서 자세한 내용이 확인 가능하니 각각 필요하신 케이스에 맞추어 해결 방법을 찾을 수 있으시길 바랍니다ㅎㅎ

 

Happy Realming! 🤗

 

< 참고자료 >

https://www.mongodb.com/docs/realm/sdk/swift/crud/threading/#communication-across-threads

 

Threading - Swift SDK — Realm

A realm instance is designed to work with one version at a time, not several different versions. Consider what Realm Database would have to do to support working with several different versions at once: it would need to store a potentially enormous graph t

www.mongodb.com