아삭아삭 iOS 개발

[위클리 발표] Happy Realming 🤗(1)_Overview 본문

Swift

[위클리 발표] Happy Realming 🤗(1)_Overview

바닐라머스크 2022. 12. 19. 23:56

 

sesac 과정 중, realm threading을 주제로 위클리 컨퍼런스 발표를 할 기회가 있었습니다.

발표를 준비하면서 공부한 내용을 보다 많은 사람들과 공유하고자 블로그에 올리게 되었는데요,

틀린 내용이 있다면 언제든지 알려주세요!

 

Part1) Overview

  1. realm 사용시 background로 작업의 필요성

  2. realm multithreaded 작업시 주의사항 (규칙 3가지)

  3. Transaction의 정의 및 특징

 


  1. realm 사용시 background로 작업의 필요성

realm을 다루다 보면 Thread 관련해서 이슈들이 많이 발생합니다.

예를 들어, 대량의 데이터를 realm에 저장하고자 할 때 이 작업이 Main Thread에서 처리된다면 소요시간이 길어질 수 있습니다.

그리고 그 시간동안 UI Blocking이 나타나서 사용자가 화면을 아무리 터치해도 반응이 없을 수 있습니다.

 

그래서!! 이러한 경우에는 Main이 아닌 Background에서 해당 작업을 처리해야 합니다.

무거운 작업을 다른 스레드들로 분산시키면 UI Thread는 높은 반응성을 유지할 수 있게 되죠.

 

하지만 이런 멀티스레드 코드를 thread safe하면서도 안정성있게 유지하는 것은 쉽지 않습니다.

그래서 이런 이슈들을 해결하기 위한 방안들을 조사하다보니 Realm에서 이를 위한 여러 메서드와 프로퍼티 래퍼를 제공하고 있다는 것을 알게 되었고, 발표에서 소개하게 되었습니다.

 

Trady(개인 출시앱)의 첫 화면에서는 DART API로 기업 고유번호 데이터는 9만 row정도 받고 있었는데,
이로인해 앱 실행 후 약 3-4초간 홈화면에 UI Blocking이 나타났습니다.
그래서 UI Blocking을 해결하고자 렘 저장코드를 DispatchQueue.global().async로 해결하고자 했으나, incorrect thread라는 에러가 발생했습니다.. 그래서 realm관련 threading을 공부해보면서 해결해보자!는 생각을 계기로 위클리 주제를 정하게 되었죠.

 

 

  2. realm multithreaded 작업시 주의사항 (규칙 3가지)

realm 에서 제공하는 메서드와 프로퍼티 레퍼를 소개하기 전에, multithreaded 코드를 realm에서 보다 안전하게 사용하기 위해 유념해야 할 3가지 규칙을 먼저 소개하겠습니다.

 

1) Don't lock to read

일반적인 멀티 스레드 환경에서는 같은 시점에 여러 개의 스레드에서 하나의 메모리에 동시접근할 때 Race condition이슈가 발생합니다.

만약 한 쪽에서 특정 메모리를 수정하려고 하고, 동시에 다른 쪽에서 동일한 메모리를 읽으려고 한다면 두 데이터가 불일치하게 되는 상황이 발생할 수 있습니다.

이때문에 일반적으로는 다른 스레드에서 동시에 접근하지 못하도록 Lock을 건다고 합니다.

 

하지만 Realm에서는 이 'Lock을 걸지 말아라' 라고 말하고 있는 점이 바료 규칙 1번인데요, 그 이유는 Lock으로 인해 Realm작업에 병목현상이 발생할 수 있기 때문이라도 합니다.

Lock을 걸지 않은 상태로 하나의 메모리에 여러 thread들이 접근하면 문제가 생길 수 있으니,

대신에 접근하려는 thread에서 realm instance를 하나 더 만들고 메모리에 접근해라 라는게 첫 번째 규칙의 의미로 볼 수 있겠습니다.

 

Ex) 제가 이해한 선에서 예시 그림을 한 번 그려봤는데요, Developer라는 realm model의 object인 Developer9객체의 이름에 대해 두 스레드가 접근하고 있다고 가정하겠습니다.
해당 객체의 name이 '감자'였는데, thread X에서는 이름을 '고구마'로 바꾸는 쓰기write을 하고 있고, thread Y에서는 해당 객체의 name을 읽는 읽기write을 동시에 한다고 하였을 때, 일반적으로는 lock이 걸려서 쓰기작업이 진행되는 동안에는 읽기 작업이 불가합니다.
하지만 realm에서는 해당 객체에 변경사항이 생겼을 때 그 상태 그대로를 snapshot으로 찍어서 버전2를 만들고 해당 객체가 해당 버전을 바라보게 만든다고 합니다.
그래서 이름이 '감자'에서 '고구마'로 바뀐점이 모두 자동적으로 반영되고, 읽기 작업에서도 '고구마'로 확인이 가능한 것이죠.

 

 

2) Avoid writes on the UI Thread if you write on a background thread

Main이든 Background이든 어떤 thread에서도 write 작업이 가능하지만,

한 번에 한 개의 writer만 작업이 가능하다는 얘기입니다.

그렇지 않을 경우에는 사용자가 앱의 무응답을 경험하게될 수도 있다고 합니다.

 

 

3) Don't pass live object, collections, or realms to other threads

마지막 세 번째 주의사항인데요, 우선 여기서 live의 의미는 해당 요소들이 수정될 때 자동으로 업데이트 되는 객체들이라는 것을 의미합니다.

그래서 만약 해당 realm 객체들이 thread간에 전달이 된다면, 여러 thread가 확인되지 않은 시점에 객체 데이터들을 변경하려고 할 수 있기 때문에 데이터가 불일치 할 수도 있는 것이죠.

때문에 live 객체들은 본인들이 생성된 thread에서만 유효하고 다른 스레드로는 보내지 않도록 유의해야 합니다.

 

여기까지 1), 2), 3)번 유의사항을 한 줄로 요약해보며 이번 글은 마무리하겠습니다.

다음 포스팅에서는 '3. Transaction의 정의 및 특징'에 대해 realm과 관련된 내용으로 이어가겠습니다~

 

 

결론 : Realm은 Thread-Safe하지 않으니까 위 3개 규칙 잘 지켜서 multithreaded 작업하자

 

 

< 참고자료 >

https://www.mongodb.com/docs/realm/sdk/swift/realm-database/

 

Realm Database - Swift SDK — Realm

Docs Home → Realm Realm Database is a reactive, object-oriented, cross-platform, mobile database:Reactive: query the current state of data and subscribe to state changes like the result of a query, or even changes to a single object.Object-oriented: orga

www.mongodb.com

https://develogs.tistory.com/11

 

Realm은 thread safe하지 않다.

Realm Instance는 thread safe하지 않으며, Realm에서 조회된 object 역시 thread safe하지 않다. Realm은 성능을 위해 무복제 아키텍쳐로 설계 되어 있다. 간단히 말하자면 realm에서 조회된 object는 단순히 database

develogs.tistory.com