Application에서 Persistent Data를 다루는 방법엔 여러가지가 있다. RDBMS를 사용하거나 단순히 txt로 저장할 수도 있고 네트워크를 통해 외부 시스템을 사용할 수도 있다. 그리고 각 저장 방식에는 메커니즘이 다르기 때문에 구현방법도 모두 다르다. 그렇기 때문에 Persistent Logic은 외부 환경과 Dependency가 매우 강하다. 따라서 Application Logic과 Persistent Logic은 섞이면 안되며 서로 독립된 레이어에 존재해야 한다. 만약 그렇지 않고 로직이 섞인 상태에서 Data Source가 바뀌게 된다면 Application Logic까지 영향도(Force)가 전달되어 변경 전파(Change Propagation)가 발생하게 된다.
[그림 1] Data Access Object Pattern은 특정 Data Source에 접근하는 로직을 추상화하고 캡슐화 한다. DAO는 DataSource의 메커니즘을 구현하고 단순한 API만을 Client에게 제공한다. (이때, DataSource에서 사용하는 ErrorCode나 Exception같은 것도 역시 상위 레이어로 전달하면 안되며, 모두 wrapping하여 상위로 전달 해야한다.) 이제 Client에서는 DAO를 생성하고 저장해야할 Value Object를 생성하여 DAO에 전달하기만 하면 된다. 이렇게 Layer를 분리하면 DataSource가 Oracle에서 외부 네트워크 시스템으로 변경되어도 Client의 수정없이 DAO만 변경하면 된다.
[그림 2]는 Client가 DAO를 통해 데이터를 읽을때의 Sequence Diagram을 나타낸다. DAO는 Data Source를 통해 데이터를 읽어와서 Value Object로 변환하여 반환하고 Client를 Value Object를 통해 실제 데이터를 사용한다.
수도 코드로 예를 들면, 회원 정보를 저장하는 DAO는 아래와 같이 구현될 수 있다.
만약 Data Source와 관련된 로직을 추상화 할 수 있다면, 아래와 같이 Generic으로 추상화하여 CommonDAO를 만들 수 있다. 그렇게 되면 앞으로 생성되는 DAO class들은 정의만 하면 되고 중복 구현은 추상화 되어 없앨 수 있다. 그리고 특정 서비스에서만 사용되는 로직들만 확장하여 사용하면 된다.
Realm Instance는 thread safe하지 않으며, Realm에서 조회된 object 역시 thread safe하지 않다. Realm은 성능을 위해 무복제 아키텍쳐로 설계 되어 있다. 간단히 말하자면 realm에서 조회된 object는 단순히 database에서 복제된 data가 아니라 core database에 직접 연동되어 있다. 그렇기 때문에 조회된 object를 변경하면 database와 이미 조회된 다른 object들에 라이브로 자동 갱신된다.
일반적으로 multi threading 환경에서 critical section을보호하기위해서 Lock을사용하는데, 이는병목현상의원인이됨으로 realm에서는 lock을지원하지않는다. 따라서조회된하나의 object에여러 thread들이접근하게되면문제가발생하게됨으로만약다른 thread에서같은데이터가필요하면그 thread에서 realm instance를하나더만들고 object를다시조회해야한다.
무복제 아키텍쳐인 Realm은 ACID를 보장하기 위해서 Lock이 아닌 MVCC(multiversion concurrency control)를 기반으로 설계되어 있다. [그림 1] 처럼 조회된 object A가 변경이 있을때, realm은 스냅샷을 찍고 v2를 만들어 object가 해당 버전을 바라보게 만든다. 이때 다른 thread들이 A를 접근하게 되면 v1를 조회하게 된다. 서로 다른 버전을 조회하고 변경함으로 ACID를 보장할 수 있게 된다.