객체 중심 저메모리 데이터베이스, Realm 모바일 데이터베이스를 소개합니다.

Realm Database series header

Realm 데이터베이스 엔진과 개발자가 작업할 수 있는 네이티브 클래스의 장점을 주제로 Realm 모바일 데이터베이스에 대한 연재를 시작합니다. 이 글은 Realm API type의 장점에 대한 두 번째 글플랫폼 간 코드 공유를 다룬 세 번째 글로 이어집니다. 4편 이후의 한글 번역은 아직 진행 중으로, 미리 보고 싶은 분들은 영문 원문인 Realm처럼 유연하고 견고한 SDK가 어떻게 좋은 개발을 돕는지에 대한 네 번째 글, 작은 단위 알림을 기반으로 부분적인 UI 업데이트를 제공할 수 있게 하는 Realm SDK를 다룬 다섯 번째 글, 마지막으로 이같은 기능이 모여 어떻게 최신 모바일 애플리케이션을 만드는지에 대한 여섯 번째 글을 참고해 주세요.


Realm 모바일 데이터베이스는 최신 애플리케이션을 업그레이드하기 위해 처음부터 구축된 새로운 모바일 데이터베이스입니다.

흔히 Realm이 기존 기술을 기반으로 구축됐다거나 다른 라이브러리를 현대적으로 재작성했다고 오해하기 쉽습니다. 사실 서버 데이터베이스와 달리 클라이언트 측에서는 많은 혁신이 일어나지 않았죠.

이 연재에서는 Realm이 다른 기술과 차별성을 가지는 몇 가지 측면을 살펴 보겠습니다. 만약 Realm에 대해 들어봤지만 뭐가 특별한지 잘 모르겠다고 생각하는 분이라면 이 글을 꼭 읽어 보세요.

왜 다음 로고의 회사들과 수많은 회사들이 10 억 명 이상의 사용자들을 가진 자신들의 앱에 Realm을 믿고 적용하는지 알려드리겠습니다.

Realm 사용 회사 로고들: Amazon, Google, Hipmunk, Starbucks 등

데이터 레이어 라이브러리와 ORM

데이터 라이브러리라고 불리는 많은 것들은 단순히 현존하는 데이터 레이어에 접근하기 위해 현대식/함수형/다른 등으로 형용되는 방법을 제공하는 특정 스토리지 엔진을 사용하는 서드파티 라이브러리입니다.

이런 개발 뉴스를 더 만나보세요

Swift나 Java 라이브러리를 통해 Generic 이나 Struct 등을 사용해서 앱의 SQLite 스토리지에 보다 현대적인 방법으로 접근할 수도 있습니다. 하지만 디스크에 모든 읽기와 쓰기 활동을 하는 스토리지 엔진은 결국 SQLite죠.

더군다나 사용하는 서드파티 라이브러리는 네이티브 데이터 구조를 중간 형식으로 변환하고, 눈에 보이지는 않지만 SQL 쿼리를 실행하며, 데이터를 SQL 테이블 행으로 변환해야 합니다.

본격적인 ORM을 사용하는 경우라면 많은 작업이 백그라운드에서 대부분 실행되곤 합니다. ORM은 지속적으로 오브젝트를 중간 포맷으로 변환하고 SQL 쿼리를 실행해서 SQLite file과 통신합니다. 작업하고 있는 오브젝트의 관련 오브젝트에 접근할 때마다 ORM은 이를 SQL JOIN문으로 변환하고, 이 쿼리를 룩업 테이블에 실행한 후 관련 오브젝트가 저장된 다른 테이블에서 일치하는 레코드를 찾습니다.

Objects vs. Tables

데이터를 접근하는 간단한 일인데도 많은 작업이 필요합니다. CPU 사이클과 디스크 시간을 소비할 뿐 아니라, 순식간에 느려질 수 있습니다. 다시 말해 메인 스레드에서 이 작업을 제거하고 적절한 스레딩 기술을 도입해야 하며, 단순히 데이터만을 얻기 위한 코드가 상당히 복잡해집니다.

Realm은 기존 기술을 반복하지 않습니다.

앞서 언급한 기존 솔루션과 단점을 고려해서 Realm 팀은 새로운 성능을 위해 개발된 스토리지 엔진을 만들기로 했습니다.

그러므로 Realm 모바일 데이터베이스는 SQLite나 다른 SQL 데이터베이스와 관련이 없으며, 이들이 가진 많은 문제들을 해결하는 것을 목표로 합니다. 또한 Realm 모바일 데이터베이스는 키-밸류 스토어 역시 아닙니다. 이 종류의 스토리지가 특정 상황에서는 훌륭하게 동작하긴 하지만, 사실 개발자들은 코드 안의 네이티브 오브젝트를 직접 작업할 수 있기를 바라기 때문입니다.

마지막으로, Realm 모바일 데이터베이스는 ORM이 아닙니다. ORM은 SQL 데이터베이스 테이블과 같은 이차원적 데이터를 오브젝트 그래프로 변환해서 네이티브 코드에서 사용할 수 있게 합니다. 그러나 Realm의 커스텀 스토리지 엔진은 데이터를 오브젝트 그래프와 상호 변환할 필요가 없으므로 ORM 역시 아닙니다.

Realm 모바일 데이터베이스는 가능한한 타입과 구조 변환을 최소화하여 객체를 직접 디스크에 유지합니다. 복잡한 엔티티에 대한 매핑 등 신속히 처리해야 할 다른 문제가 없으므로, Realm 모바일 데이터베이스는 메모리 상의 오브젝트를 디스크로 빠르게 가져올 수 있습니다.

사실, 이 것이 Realm 모바일 데이터베이스의 트레이드 마크라 할 만한 기능입니다. 메인 스레드에서 얼마든지 읽기/쓰기 작업을 할 수 있죠! 메인 스레드에서 작업하다가 UI가 블럭될까봐 걱정할 필요가 없습니다. (이런 놀라운 기능을 구현했지만 저희가 마법사인건 아닙니다. 🎩)

Realm 모바일 데이터베이스는 경쟁 기술보다 성능이 뛰어납니다.

Realm Core는 초고속 C++로 작성됐으며, C++ 객체를 디스크에 매핑합니다. SDK와 함께 개발된 API와 동작이 모바일 앱에서 실제로 데이터를 사용하는 방법과 밀접하게 연관되어 있으므로 쉽게 동작 방식을 이해할 수 있습니다.

이처럼 긴밀한 연결성은 iOS와 닮아 있습니다. Apple은 iPhone 용 하드웨어를 만들면서 이를 최대한 활용할 수 있도록 하는 최상의 SDK를 개발자에게 제공하죠. 그렇기 때문에 다른 디바이스만큼 하드웨어가 강력하지 않은 iPhone에서 기나긴 연락처를 스크롤해도 프레임이 떨어지지 않습니다.

또한 견고하고, 호환성이 높으며, 멀티 플랫폼인 C++ 코어를 사용함으로써 Realm은 거의 모든 곳에서 실행될 수 있으며 특정 플랫폼이나 공급 업체에 구속되지 않습니다.

슬슬 이런 C++ 얘기가 머리 아파지면서, “Realm을 사용하려면 C++을 알아야 한다는 소리인가요?” 하는 의문이 드실지도 모르겠습니다. 다행히 그럴 필요는 없습니다. 그 이유를 설명드리죠.

여러분이 사용하는 언어를 구사하는 견고한 Core

Realm 모바일 데이터베이스는 다섯 종류의 SDK를 지원하며, 이들은 모바일 프로그래밍 언어에서 내장된 Core API에 접근할 수 있도록 하는 가벼운 래퍼 API입니다.

Realm SDKs: Java, Objective-C, React Native, Swift, Xamarin

각 SDK는 개발자가 이미 익숙한 언어 및 플랫폼 기능을 사용하도록 설계됐습니다. Realm Swift와 Realm Java의 기초를 한번 살펴 볼가요?

Realm Swift를 시작하려면 먼저 객체를 정의해야 합니다.

class Repository: Object {
  dynamic var id: Int = 0
  dynamic var stars: Int = 0
  dynamic var url: String = ""

  dynamic var name: String?
  dynamic var favorite: Favorite?
}

다음으로 이들 중 몇 개의 오브젝트를 쿼리합니다.

let repos = realm.objects(Repository.self)
  .filter("name contains[c] %@", searchTerm)

이 코드는 Swift의 generic을 사용해서 결과 집합의 타입을 결정하며, NSPredicate를 사용하므로 익숙한 문법으로 쿼리를 사용할 수 있습니다. 표준 컬렉션 타입에 map, filter, sort 등으로 메서드 체이닝을 하는 함수형 스타일은 Swift 프로그래머들이 널리 사용하는 방법이므로 Realm의 컬렉션 타입도 비슷한 API를 가지고 있습니다.

같은 컨셉을 Realm Java에서 살펴 볼까요? 동일한 객체를 Java에서 정의하겠습니다.

public class Repository extends RealmObject {
  @PrimaryKey
  private Int id;
  private Int stars;
    
  public Int getId() { return id; }
  public void setId(Int id) { this.id = id; }
  public Int getStars() { return stars; }
  public void setStars(Int id) { this.stars = stars; }

  //etc. 
}

그 다음, 안드로이드에서 이들 Repository 오브젝트를 쿼리합니다.

RealmResults<Repository> results = realm.where(Repository.class)
  .contains("name", searchTerm).findAll();

이 Java 코드는 Swift 코드가 앞서 했던 것과 유사한 동작을 하지만, API는 Swift SDK와 다릅니다. 이 코드는 일반적인 안드로이드 스타일을 따르므로 다른 안드로이드 코드와 잘 어울립니다.

온전한 클래스

마지막이자 중요한 점은 Realm 오브젝트가 온전한 클래스라는 것입니다. 원하는 프로그래밍 언어가 제공하는 모든 도구를 사용해서 신속하게 원하는 작업은 무엇이든 수행할 수 있습니다.

다음처럼 자동으로 값을 넣는 단순한 컴퓨티드 프로퍼티도 만들 수 있습니다.

class Repository: Object {
  dynamic var stars: Int = 0

  var starsDecorated: String {
    return "\(stars) ⭐️"
  }
}

또한 비즈니스 로직을 캡슐화하는 방법까지 만들 수 있죠.

extension Repository {
  static func all(searchTerm: String? = nil) -> Results<Repository> {
    let realm = try! Realm()
    return realm.objects(Repository.self)
      .filter("name contains[c] %@", searchTerm ?? "")
      .sorted(byProperty: "stars", ascending: false)
  }
}

혹시 온전한 Realm 오브젝트에 대해 더 알고 싶다면 이 글을 위해 GitHub에 개설한 프로젝트 를 참고해 주세요.

예제 Repository 클래스의 기능은 다음과 같습니다.

  • 단순한 데이터 프로퍼티 (id, stars)
  • 관련 오브젝트 (favorite)
  • 컴퓨티드 프로퍼티 (nameDecorated)
  • 다이내믹 프로퍼티 (avatarUrl)
  • 커스텀 init
  • 인덱스된 (primaryKey(), indexedProperties())
  • 메타데이터 (ignoredProperties())
  • 간단한 엔티티 메서드 (all(searchTerm:), add(repos:), toggle(favorite:))

지금까지의 내용이 마음에 드셨나요?

Realm 모바일 데이터베이스의 훌륭한 기능 중 일부를 살펴봤습니다. Realm 모바일 데이터베이스의 커스텀 데이터베이스 엔진을 통해 성능과 견고성이 향상됐습니다.

이 글은 Swift 부문에 좀 더 중점을 두긴 했지만, Realm 모바일 데이터베이스는 다른 프로그래밍 언어에서도 사용하기 쉽습니다.

온라인에서 공식 문서를 확인할 수 있습니다.

Realm 모바일 데이터베이스에 대한 연재 중 첫 번째 글을 모두 보셨습니다. 내용이 마음에 드셨는지 모르겠네요. 다음 글에서는 쉽게 구현할 수 있으면서 성능이 최적화된 앱을 만들 수 있는 RealmSwift API에 대해 알아보겠습니다.

다음 글에서 만나요! 👋

다음: Realm의 차별화 요소들 #2: 성능 향상과 메모리 사용량 최소화에 최적화된 Realm API를 소개합니다.

General link arrow white

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.


Marin Todorov

Marin Todorov는 iOS 컨설턴트이자 퍼블리셔입니다. “iOS Animations by Tutorials”의 저자이며 iOS Animations by Emails” 뉴스레터를 운행하고 있습니다. 20년 넘게 Apple 관련 개발을 했으며 Monster Technologies와 Native Instruments 등의 회사에서 일하면서 4개 이상의 나라에서 거주했습니다. 또한 raywenderlich.com 튜토리얼 팀의 설립 멤버이기도 하죠. 코드 개발 이외에는 블로그 게재와 책 저술, 교육과 강연에 관심이 많으며, 코드를 오픈 소스화 하기도 합니다. Santiago 순례 경험도 있습니다.

4 design patterns for a RESTless mobile integration »

close