Realm’s Tiny Tip

제가 속한 잔디팀이 최근에 일부 데이터를 SQLite 에서 Realm 으로 전환하였습니다.
관련 내용은 이 곳으로 이동하시면 보실 수 있습니다.

On Bright Side

성능이 정말 빨라졌습니다. 기존보다 DB 로 인한 지연 요소가 거의 없어지다시피 할 정도로 빨라졌습니다.

On Dark Side

업데이트 직후 어마어마한 크래시 리포트가 올라왔습니다. 평상시보다 30배 이상의 오류 리포트였고 심각하게 Roll-back 을 검토해야 했습니다.

긴급하게 오류가 난 원인을 파악해서 수정해야 했습니다.

서비스의 멀티 프로세스과 Realm 초기화

Realm 은 공식 문서에서 멀티 프로세스를 지원하지 않는다고 하였습니다.

제가 만든 로직도 멀티 프로세스때문에 발생하였습니다.

위의 로직으로 인해 문제가 발생하였습니다.

Application 은 기본 프로세스뿐만 아니라 MultiProcess 에서도 함께 로드됩니다. 그러기 때문에 Realm.init() 이 Process 선언된 갯수만큼 호출되어집니다.

문제는 Realm.init() 코드 내부를 따라가면 .realm 파일이라는 Realm 의 Database File 을 로드하도록 되어 있습니다. Realm 의 구성요소 파일들을 보면 단순히 DB 만 있는 것이 아니라 read_lock, write_lock 등이 함께 구성되어 있습니다.

동시에 여러 Process 에서 1개의 Realm 에 접근하다보니 Realm File 이 깨지거나 Realm File 에 Access error 가 발생하게 됩니다.

멀티 프로세스 우회하기

Realm.init 우회하기

가장 먼저 실행한 방법은 멀티 프로세스시에 Realm.init 을 우회하는 것입니다.

pid 와 proccess-name 을 비교해서 Realm 에 접근하도록 하였습니다.

예를 들어 com.myapplication:remote 와 같은 방식으로 선언된 Process 에서는 Realm 에 접근을 하지 못하도록 하였습니다.

그러면 MultiProcess 에서는 데이터에 어떻게 접근해야 하나요?

ContentProvider or SQLite

결국 프로세스가 다르다면 사실상 방법은 ContentProvider 를 통해 Realm 에 접근하거나 반드시 접근해야하는 데이터는 SQLite 로 구현하는 수밖에 없습니다.

SharedPreference 도 마찬가지로 Multi Process 를 지원하지 않으며 강제로 사용하면 Preference XML 파일이 통째로 사라지니 절대로 쓰시면 안됩니다.

이미 에러가 난 유저들은?

MultiProcess 에 의한 오류는 사실상 방법이 없습니다.

이미 Realm 파일이 깨어진 상태이기 때문에 복구할 방법이 없기 때문에 다음과 같은 코드를 추가하여 Realm 파일을 삭제하도록 해야합니다.

대개의 많은 경우가 Realm Init 과정 또는 Access 과정에서 RealmFileException 형태로 에러가 발생하며 대다수가 Bad Header 에 의한 오류라는 에러를 받게 됩니다. 이는 try-catch 로 대응이 가능합니다.

하지만 일부 경우에 Exception 이 아닌 Fatal 오류가 나며 어떤 형태로도 catch 를 할 수 없습니다.
이 경우는 사실상 사용자에게 앱을 스스로 초기화 하도록 하셔야 합니다.

결과

Realm 으로 인한 에러 완전히 해결되진 않았으나 과거의 안정적인 수준에 근접하게 다시 정상화 되었으며 일시적인 문제는 해결이 되었다고 생각되어집니다.

문서상 Multi Process 부분을 가볍게 생각하고 구현을 하였다가 Realm 이 같은 프로세스인 경우에만 read-write lock 을 동작하는 것이라고는 예상하지 못해 발생하였습니다. 
결국 이 문제를 우회적으로 피했고 다행히 잘 해결이 되었습니다. Realm 을 사용하시는 분들은 이 부분을 간과하지마시고 작업하시길 바랍니다.

제가 드리는 가장 안정적인 팁은 사용자가 앱을 사용함에 있어서 가장 기초가 되는 데이터, Session Key 같은 것은 SQLite 로 관리하고 그외의 것, 빈번하지만 언제든 다시 생성할 수 있는 데이터는 Realm 으로 하는 것이 가장 적절한 모습으로 생각합니다.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.