Realm은 Apple 시스템과 안드로이드를 넘나드는 멀티 플랫폼 데이터베이스입니다.

Realm Database series header

이 글은 Realm 모바일 데이터베이스에 대한 시리즈 글입니다. 여러 플랫폼에서 데이터베이스를 사용할 수 있는 Realm의 멀티 플랫폼 기능과 높은 기기 간 코드 재사용성에 대해 알아봅니다. 혹시 시리즈 시작 글을 놓치셨다면 첫 번째 글과 성능 향상과 메모리 사용량 최소화에 최적화된 Realm API를 소개하는 두 번째 글을 먼저 보시길 추천합니다. 이 시리즈는 Realm처럼 유연하고 견고한 SDK가 어떻게 좋은 개발을 돕는지에 대한 네 번째 글로 이어집니다. 다음 시리즈에 대한 한글 번역은 아직 진행 중으로, 미리 보고 싶은 분들은 영문 원문인 작은 단위 알림을 기반으로 부분적인 UI 업데이트를 제공할 수 있게 하는 Realm SDK를 다룬 다섯 번째 글, 마지막으로 이런 기능이 모여 어떻게 최신 모바일 애플리케이션을 만드는지에 대한 여섯 번째 글을 참고해 주세요.


Realm 모바일 데이터베이스는 개발 초기부터 모바일 기기에서 실행될 수 있도록 설계됐습니다. 당시에는 iOS와 안드로이드 모두 모바일 개발자의 요구에 맞게 설계된 최신 데이터베이스가 없었습니다. SQL 쿼리를 쓰는 대신 객체를 사용해서 쉽게 작업하고, 메인 스레드에서도 많은 양의 작업을 빠르게 처리할 수 있는 빠른 성능의 엔진을 가지며, 사용하는 언어의 API를 사용하는 등의 요구죠.

이전 포스트에서 말했듯, Realm 모바일 데이터베이스는 매우 빠른 C++로 작성됐습니다. 데이터베이스 코어까지 오픈소스이므로 언제든 확인해볼 수 있습니다.

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

거의 모든 곳에서 C++ 코드를 실행할 수 있으므로 Realm 모바일 데이터베이스를 Apple과 Android 기기 모두에서 실행하기는 쉬웠습니다. 사실 양 플랫폼은 기능이 거의 유사한데 단지 고급 API의 문법이 다를 뿐이었죠.

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

  • Swift 개발자들은 보다 Swift스러운 API를 사용하고,
  • Objective-C 프로그래머는 Cocoa 스타일의 API를 사용하며,
  • 안드로이드 개발자들은 Java와 유사한 API를 사용합니다.

최대한 많은 모바일 개발자에게 데이터베이스를 제공하기 위해, Realm은 멀티 플랫폼 솔루션을 위한 고급 API 역시 제공합니다.

  • C# 개발자는 Xamarin Studio를 사용해서 iOS와 안드로이드 앱을 모두 만들 수 있으며,
  • JavaScript 개발자 역시 ReactNative로 사용할 수 있습니다.

Apple 플랫폼 간에 데이터 레이어 공유하기

Apple 은 크로스 플랫폼 코드를 작성하기 쉬우므로 각 Apple 기기가 사실 다른 운영 체제를 가진다는 점을 간과하기 쉽습니다.

하지만 완전한 Mac 애플리케이션이나 Apple Watch 애플리케이션을 만들 때는 각기 다른 SDK를 사용합니다. 물론 프로그래밍 언어는 Swift나 Objective-C처럼 같은 것을 사용할 수 있지만 SDK와 OS는 다르죠.

하지만 Apple의 멀티 플랫폼 프로젝트를 만들기 쉽고 코드를 재사용할 수 있으므로 플랫폼과 관계없이 프로젝트 간에 많은 것을 공유할 수 있습니다. 게다가 Realm을 사용하면 데이터 레이어도 공유할 수 있습니다!

이 포스트에서는 iOS, macOS, tvOS, watchOS 간에 데이터 레이어를 공유하는 프로젝트를 살펴보겠습니다.

Realm poweres watchOS, iOS, macOS, and tvOS apps

GitHub에서 프로젝트를 클론해서 실행해볼 수 있습니다.

“Top GitHub Repos” 앱 예제를 살펴볼 텐데요. GitHub에서 인기 있는 100위까지의 저장소를 불러와서 사용자가 탐색하거나 즐겨찾기할 수 있도록 하는 앱입니다. 많이 복잡하지는 않은 예제이지만 전체 데이터 레이어를 플랫폼 간에 재사용하는 장점을 명료하게 보여줍니다.

Xcode 프로젝트에는 지원되는 플랫폼 각각을 위한 코드가 포함되며, 네트워킹 레이어 등은 Apple의 Foundation에만 의존적으로, 모든 플랫폼에서 공유됩니다.

또한 Realm 객체와 전체 데이터 레이어는 FoundationRealmSwift에만 의존적으로 전체 플랫폼 사이에서 공유됩니다.

Demo project shared files

프로젝트의 Mac 버전을 실행하면 일반적인 Mac 애플리케이션을 시작할 수 있습니다.

Mac app powered by Realm

Watch 타깃을 실행하면 watchOS의 전형적인 UI를 가진 애플리케이션이 Watch 시뮬레이터에서 실행됩니다.

Apple Watch app powered by Realm

참고: watch 시뮬레이터에서 GitHub에서 저장소를 가져오는 것이 오래 걸릴 수 있습니다. 상용 앱에서는 iOS 앱에서 가져오는 것이 나을 수 있지만, 이 예제에서는 코드 공유부분에만 집중했습니다.

이제 코드를 살펴보겠습니다. 다른 언어를 사용하더라도 쉽게 이해할 수 있는 예제입니다.

Favorite는 앱 사이에서 공유되는 Realm 객체입니다. 저장소를 즐겨찾기 표시하고 즐겨찾기 기호를 지정합니다.

import Foundation
import RealmSwift

class Favorite: Object {
    
  //persisted property
  dynamic var symbol = "💖"

  //dynamic property
  var symbolIndex: Int? {
    return Favorite.symbols.index(of: symbol)
  }

  //static properties
  static let symbols = ["💖", "🚀", "🤕"]
  static let noSymbolIndex = -1
}

클래스는 저장되는 속성과 다이내믹 속성을 모두 가지고 있지만 FoundationRealmSwift에만 의존적입니다. 덕분에 이들이 지원하는 모든 플랫폼 사이에 이 클래스를 공유할 수 있습니다. Xcode에서 파일 멤버십을 확인하면 이 파일이 네 개의 타깃 모두에서 그대로 재사용되는 것을 볼 수 있습니다.

Demo project shared files

공유와 재사용이 가능한 코드의 장점은 한 번만 작성하고 테스트해도 데이터 엔티티가 앱의 다른 버전 사이에서 동기화되는 것을 보장할 수 있다는 것입니다.

Favorite 파일을 더 자세히 볼까요? 간단한 도움 메서드를 확인할 수 있습니다.

// MARK: - Favorite model methods

extension Favorite {
  func set(symbol newSymbol: String?) throws {
    guard let realm = realm, 
      let symbol = newSymbol else { return }

    try realm.write {
      self.symbol = symbol
     }
  }
}

좀 더 완벽한 비즈니스 로직을 구현하려면 아마 별도의 클래스 구조를 만들고 싶겠죠? 하지만 위 예제와 같은 일부 기본 메서드는 직접 Favorite 클래스에서 엔티티 정의와 함께 재사용할 수 있습니다.

“한 번 작성해서, 어디서든 쓸 수 있다”는 설명이 와 닿으시나요? 다음 포스트에서는 Realm 객체의 재사용성과 높은 분리 수준이 어떻게 더 나은 앱 구조를 만드는지 자세히 설명하겠습니다.

더 넓은 범위에 데이터 엔티티 공유하기

여기까지 네 개의 다른 운영체제에서 코드를 재사용하는 법을 보여드렸는데, 이들은 Apple 환경 시스템 내에 속해 있는 운영체제입니다.

즉, Swift나 Objective-C로 된 코드를 네 개의 Apple 플랫폼에 공유할 수 있습니다. 하지만 다른 모바일 사용자도 사용할 수 있게 하려면 Android로 확장할 필요가 있습니다.

이제 Favorite 클래스를 Java로 옮겨서 같은 앱의 안드로이드 버전에서 사용할 수 있게 해보겠습니다.

public class Favorite extends RealmObject {
   @Required
   private String symbol = "💖";
   private static String[] symbols = {"💖", "🚀", "🤕"};
   public static final int NO_SYMBOL_INDEX = -1;

   public String getSymbol() {
     return symbol;
   }

   public void setSymbol(String symbol) {
     if (symbol == null) return;
     this.symbol = symbol;
   }

   public int getSymbolIndex() {
     for (int i = 0; i< symbols.length; i++) {
       if (symbols[i].equals(symbol)) {
         return i;
       }
     }
     return NO_SYMBOL_INDEX;
   }
}

Swift와 클래스가 매우 유사하지만, 정확히 같진 않습니다. 하지만 동일한 기본 C++ 구조에 바인딩 되면서 궁극적으로 디스크에 저장된 같은 데이터에 바인딩 됩니다.

여기에 관련된 흥미로운 측면이 몇 가지 있습니다.

먼저, iOS 코드는 Swift나 Objective-C로 쓰이고 안드로이드 코드는 Java로 쓰이므로 iOS와 안드로이드 간에 코드를 그대로 재사용할 수는 없습니다.

하지만 기본 데이터 유형이 같고 객체 관계를 작성하는 Realm의 API가 같으므로 쉽게 파악해서 적용할 수 있습니다.

게다가 플랫폼 전반에 걸쳐 클래스에 포함된 도움 메서드를 다시 만들 수 있습니다. 그렇게 하면 두 개의 엔티티가 iOS와 안드로이드 사이에 같게 만들 수 있고, Favorites 관련 테스트 역시 동기화할 수 있습니다.

플랫폼 간에 엔티티를 일치하게 하면 일관성, 재사용 가능성, 테스트 용이성이라는 장점을 얻을 수 있을 뿐만 아니라 멋진 API를 플랫폼 사이에서 간단하게 쓴다는 즐거움도 누릴 수 있습니다.

정말 멋진 점은 일단 자신의 서버에 Realm 모바일 플랫폼을 무료로 설치하면 별도의 설치나 구성이 필요 없이 도 tvOS, macOS, iOS, 안드로이드 앱 사이에 데이터 동기화가 가능하다는 겁니다!

엔티티가 이미 같은 구조로 되어 있고, Realm 오브젝트 서버가 어떻게 동기화를 맞추는지 관리해주므로 아무 비용 없이도 데이터가 동기화됩니다.

글이 마음에 드셨나요?

Realm 모바일 데이터베이스를 사용한 멀티 플랫폼 솔루션에 대해 알아봤습니다. 이처럼 견고하고 재사용 가능한 데이터 레이어는 강력한 모바일 앱의 토대가 되며, 다음 글에서는 더욱 자세한 내용을 살펴보겠습니다.

더 자세히 알고 싶은 분은 Realm 모바일 데이터베이스를 사용해 보세요.

다음 연재에서는 시리즈를 위한 예제 프로젝트를 더욱 자세히 살펴볼 예정입니다. Realm API로 어떻게 명료하고 유연한 앱 구조를 만들 수 있는지 알려드리는 다음 글을 기대해 주세요!

다음 편에서 만나요! 👋

다음: Realm의 차별화 요소들 #4: Realm SDK로 관심사별 로직을 간단명료하게 분리하세요

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