이 문서는 Realm 오브젝트 서버(ROS)의 모든 에디션에 적용됩니다. 프로페셔널 에디션과 엔터프라이즈 에디션에 특화된 기능은 PE/EE 문서를 참고하세요.

Realm 오브젝트 서버 는 여러 기기 사이에서 Realm을 동기화하고 Realm을 위한 인증 및 접근 제어 서비스를 제공하며, Realm Functions를 통해 “서버리스” 이벤트 핸들링을 제공합니다.

Realm 오브젝트 서버 설치하기

이미 시작하기에서의 가이드를 따른 경우 Realm 오브젝트 서버의 설치가 끝났으므로 바로 설정 섹션으로 이동하세요.

이 문서는 업그레이드삭제에 대한 가이드 역시 포함합니다.

macOS

macOS에서는 단순하게 파일을 다운로드해서 설치할 수 있습니다.

macOS 번들 다운로드

Realm 오브젝트 서버, Cocoa SDK와 데모 앱

다운로드 폴더로 이동해서 “realm-mobile-platform” 폴더를 여세요. start-object-server.command 파일을 더블 클릭해서 Realm 오브젝트 서버를 시작합니다.

Linux

Linux 환경에서는 PackageCloud가 Realm의 패키지 저장소를 관리합니다. Ubuntu, Red Hat Enterprise Linux, CentOS에 Realm 오브젝트 서버를 설치하고 실행하는 방법은 Linux 설치 페이지를 참조하세요.

클라우드 배포

Amazon EC2, Azure, Digital Ocean에서 Realm 오브젝트 서버를 배포하기 위한 정보는 클라우드 배포 문서를 확인하세요.

서버 실행하기

Realm 오브젝트 서버 서비스는 표준 service 명령을 사용합니다.

sudo service realm-object-server status
sudo service realm-object-server start
sudo service realm-object-server stop
sudo service realm-object-server restart

Realm 오브젝트 서버 서비스의 정의는 표준 systemctl 명령을 사용합니다.

sudo systemctl status realm-object-server
sudo systemctl start realm-object-server
sudo systemctl stop realm-object-server
sudo systemctl restart realm-object-server

서버를 시작하려면 다운로드한 realm-mobile-platform 디렉터리 내의 start-object-server.command 파일을 더블 클릭하세요.

macOS 버전의 서버를 중지하려면 start-object-server.command 파일에 의해 열린 터미널 창에서 CTRL-C를 누르세요.

Realm 대시보드

The Realm Dashboard

대시보드는 Realm 오브젝트 서버를 위한 브라우저 기반의 애플리케이션으로 다음 기능을 제공합니다.

  • 대시보드: 입/출력 데이터 속도, 입/출력 바이트, 활성화된 연결, 활성화된 Realm 등의 시스템 상태
  • Realm: 해당 오브젝트 서버에 동기화되는 Realm의 경로, 권한, 소유 사용자를 드릴 다운 방식으로 보여주고 개별 Realm의 모델과 컨텐츠 표시
  • 사용자: 해당 오브젝트 서버의 사용자 정보와 관리, 어드민 권한 부여 및 삭제
  • Function: Realm Functions 관리 및 접근
  • Log: 선택해서 세부 내용을 볼 수 있는 오브젝트 서버의 시스템 로그

대시보드에 접근하려면 새 브라우저 창을 열고 http://localhost:9080로 이동합니다. 서버가 로컬 머신이 아니라면 localhost를 호스트 이름이나 IP 주소로 대체하세요.

처음 대시보드에 접속하는 경우 이메일과 암호를 입력해서 어드민 사용자를 만들 수 있으며, 이후에는 이 자격 증명을 사용해서 로그인할 수 있습니다.

Realm Studio

Realm Studio is Realm’s GUI console utility for managing and inspecting both local and synchronized Realms. In addition, you can connect to a running Realm Object Server to view logs and manage users.

To get started with Realm Studio download the latest release:

서버 설정

Realm 오브젝트 서버는 개발 환경을 위한 민감한 기본 정보를 포함한 YAML 포맷의 설정 정보 파일인 configuration.yml을 가집니다. 설정 파일은 설치된 상황이나 제품에 맞도록 수정할 수 있습니다.

설정 파일의 기본 위치는 사용하는 플랫폼에 따라 다릅니다.

  • Linux: /etc/realm/configuration.yml
  • macOS: Realm 플랫폼 폴더 내부의 realm-object-server/object-server

설정 파일의 경로는 절대 주소일 수도 상대 주소일 수도 있습니다. 상대 주소를 사용할 때는 현재의 작업 디렉터리에 따라 결정됩니다. 혼란을 피하기 위해 항상 절대 주소를 쓰는 것을 추천합니다.

필수 설정

이 설정은 configuration.yml에 지정하기를 권장하지만, 명령행 인자로도 전달할 수 있습니다.

필수 설정은 다음 내용을 정의합니다.

  1. Realm 오브젝트 서버가 모든 파일을 저장할 기존 디렉터리
  2. Realm 오브젝트 서버에 인증받은 클라이언트만 접근할 수 있도록 보안 접속에 사용할 키 쌍에 대한 경로. 키들은 반드시 PEM 포맷이어야 하고 일치하는 쌍을 갖춰야 합니다.

설정에 대한 요약

설정 키 CLI 인자 설명
storage.root_path --root ROS가 모든 데이터 파일을 저장할 디렉터리 경로
auth.public_key_path --public-key 클라이언트 토큰들 인증에 사용할 (PEM 포맷으로 저장된) 공개 키에 대한 경로
auth.private_key_path --private-key 클라이언트 토큰들 인증에 사용할 (PEM 포맷으로 저장된) 비밀 키에 대한 경로

Realm 오브젝트 서버는 반드시 storage.root_path 설정 또는 --root CLI 인자에 따른 디렉터리에 대한 읽기/쓰기 접근 권한을 가져야 합니다. 이 설정을 변경하는 경우, realm 사용자가 새 저장소 디렉터리(예: chown -R realm:realm /new/storage/path)에 접근할 수 있는지 확인하세요.

네트워크

이 기본 설정에서 내부적인 백엔드 서비스프락시 모듈로 Realm 오브젝트 서버를 동작합니다. 백엔드 서비스는 서버가 실행 중인 호스트로부터만 접근이 가능하며 모든 인터페이스로 응답하는 프락시 모듈을 통해 전체 트래픽을 전달합니다. 아래의 도표에서 기본 설정을 확인하세요.

프락시 설정 도표

백엔드 서비스

Realm 오브젝트 서버는 내부적으로 두 개의 백엔드 서비스를 시작합니다. sync 서비스는 핵심 동기화 기능의 책임을 담당하고 27800 포트로 응답합니다. http 서비스는 인증과 대시보드를 담당하며 포트 27080로 응답합니다. 기본적으로 서비스들은 호스트의 IPv4 루프백 주소(127.0.0.1)로 응답하고 요청은 프락시 모듈을 통해 전달됩니다.

프락시 모듈을 비활성화시키고 IPv4와 IPv6의 모든 인터페이스로 백엔드 서비스가 응답하게 하려면 listen_address를 적절히 ::로 설정해야 합니다. 비슷하게 응답 포트는 listen_port을 적절히 수정해 변경합니다.

설정 키 기본값 설명
network.sync.listen_address 127.0.0.1 sync 서비스가 바인드할 주소
network.sync.listen_port 27800 sync 서비스가 바인드할 포트
network.http.listen_address 127.0.0.1 http 서비스가 바인드할 주소
network.http.listen_port 27080 http 서비스가 바인드할 포트

프락시 모듈

내장된 역방향 프락시 모듈은 모든 입력된 트래픽을 적절한 백엔드 서비스로 보냅니다. 이 프락시는 HTTP, 웹소켓, HTTPS, 보안 웹소켓 트래픽 모두를 담당할 수 있지만 Realm 오브젝트 서버의 트래픽에 독점적이며 범용 프락시는 아닙니다. 기본 설정에서 HTTP 프락시는 모든 IPv4와 IPv6 인터페이스를 포트 9080에서 받습니다. 단, HTTPS 프락시는 비활성화되어 있습니다. 여러 프락시는 동시에 활성화될 수 있습니다.

동기화와 HTTP 서비스는 localhost (기본값)에서 수신하고 프락시는 단순히 외부 접근을 위해 사용하는 것을 권장합니다.

필요시 내장 프락시 모듈을 비활성화하고 독자 프락시 설치로 대체하거나 클라이언트 사용자 호출을 위해 네트워크에 직접 백엔드 서비스를 사용할 수 있습니다.

설정 키 기본값 설명
proxy.http.enable true HTTP 프락시를 비활성화하기 위해 false로 설정합니다
proxy.http.listen_address :: 인터페이스 주소를 제공합니다. 모든 IPv4 인터페이스를 위해서는 0.0.0.0 주소를 제공하고 모든 IPv6 인터페이스를 위해서는 ::를 제공합니다
proxy.http.listen_port 9080 HTTP 프락시를 위한 대체 포트를 제공합니다
proxy.https.enable false HTTPS 프락시를 활성화 하기 위해 true로 설정합니다
proxy.https.listen_address :: 인터페이스 주소를 제공합니다. 모든 IPv4 인터페이스를 위해서는 0.0.0.0 주소를 제공하고 모든 IPv6 인터페이스를 위해서는 ::를 제공합니다
proxy.https.listen_port 9443 HTTPS 프락시를 위한 대체 포트를 제공합니다
proxy.https.certificate_path   PEM 포맷으로 된 HTTPS 프락시용 인증 파일의 경로
proxy.https.private_key_path   PEM 포맷으로 된 HTTPS 프락시용 비밀 키 파일의 경로

HTTPS 프락시를 활성화려면 proxy.https.certificate_path, proxy.https.private_key_path 옵션을 설정해 PEM 포맷으로 된 인증 파일과 비밀 키 파일을 제공해야 합니다. 이 인증은 셀프 인증될 수 없습니다.

기본 HTTPS 포트 443과 같이 1024보다 낮은 숫자의 포트에서 Realm 오브젝트 서버에 연결하려면 Realm 오브젝트 서버가 수신하는 포트로 트래픽을 포워딩합니다.

sudo iptables -A PREROUTING -t nat -p tcp --dport 443 -j REDIRECT --to-port 9443

다음 코드는 HTTPS를 사용하는 작업 프록시 구성 예제입니다.

proxy:
  https:
    enable: true
    listen_address: ‘::'
  http:
    enable: false

로그

Realm 오브젝트 서버는 자체의 상태와 진행에 대해 메시지 정보를 남깁니다. 로그는 콘솔이나 logging.path 설정에 기반한 파일로 작성될 수 있으며 logging.level 옵션으로 세밀한 정도를 변경할 수 있습니다.

logging.path의 기본 값은 플랫폼에 따라 달라집니다.

logging.level의 값은 9 개의 가능한 값 중 하나로 지정합니다.

logging.level 구체적인 수위
all 모든 가능한 메시지
trace 내부 서버 상태와 프로토콜을 추저하기 위해 사용합니다
debug 내부 서버 디버깅 메세지
detail 동기화 트랜잭션 요약을 보여줍니다
info 제품을 위해 좋습니다 (기본)
warn 경고 메시지만 로그합니다
error 에러 메시지만 로그합니다
fatal Realm 오브젝트 서버가 종료될 수 있는 에러
off 출력을 가능한 모두 감춥니다

logging.path 기본값은 플랫폼에 따라 다릅니다.

  • Linux: var/log/realm-object-server-log
  • macOS: Realm 오브젝트 서버를 실행한 터미널의 stdout

업그레이드

Realm 플랫폼 개발자 에디션을 프로페셔널이나 엔터프라이즈 에디션으로 업그레이드하려면 [프로페셔널/엔터프라이즈 에디션][pe] 문서를 참조하세요.

macOS

Realm에서 새로운 macOS 다운로드 번들을 전달받아 macOS 버전의 오브젝트 서버를 업그레이드 합니다.

리눅스

1.0.0-BETA-4.8 이전 버전에서 업그레이드하는 경우 인스톨에 따른 언인스톨 설명을 참조하세요. 독립 서버를 위한 Realm 패키지 서비스의 업그레이드 절차는 매우 간단합니다.

Linux에서 Realm 오브젝트 서버를 업그레이드하려면 Realm 오브젝트 패키지를 업그레이드합니다.

# 업그레이드 전에 서비스를 중단합니다
sudo service realm-object-server stop

# 가능하면 새 버전을 설치합니다
sudo yum -y upgrade realm-object-server-de

# 동작을 재개하기 위해 서버를 재시작합니다
sudo service realm-object-server start
# 업그레이드 전에 서비스를 중단합니다
sudo systemctl stop realm-object-server

# 가능하면 새 버전을 설치합니다
sudo yum -y upgrade realm-object-server-de

# 동작을 재개하기 위해 서버를 재시작합니다
sudo systemctl start realm-object-server
# 패키지 정의를 갱신합니다
sudo apt-get update

# 업그레이드 전에 서비스를 중단합니다
sudo systemctl stop realm-object-server

# 가능하면 새 버전을 설치합니다
sudo apt-get upgrade realm-object-server-de

# 동작을 재개하기 위해 서버를 재시작합니다
sudo systemctl start realm-object-server

프로페셔널이나 엔터프라이즈 에디션으로 업그레이드하기 위한 정보가 필요하면 [PE/EE 문서][pe]를 확인하세요.

제거하기

Realm 오브젝트 서버를 제거하고 싶다면 절차는 매우 간단합니다. 데이터를 백업받고 다음을 실행하세요.

# 제거하기 전에 서비스를 중단합니다
sudo service realm-object-server stop

# 선택적/권고 단계: 데이터를 백업합니다
# cp -a /var/lib/realm{,.backup}

# 패키지를 제거합니다. 데이터는 /var/lib/realm에 보관됩니다.
sudo yum -y erase realm-object-server-developer

# 패키지를 제거합니다 (1.0.0-BETA-4.8 이전 버전 명령어)
sudo yum -y erase realm-object-server-de
# 제거하기 전에 서비스를 중단합니다
sudo systemctl stop realm-object-server

# 선택적/권고 단계: 데이터를 백업합니다
# cp -a /var/lib/realm{,.backup}

# 패키지를 제거합니다. 데이터는 /var/lib/realm에 보관됩니다.
sudo yum -y erase realm-object-server-developer

# 패키지를 제거합니다 (1.0.0-BETA-4.8 이전 버전 명령어)
sudo yum -y erase realm-object-server-de
# 제거하기 전에 서비스를 중단합니다
sudo systemctl stop realm-object-server

# 선택적/권고 단계: 데이터를 백업합니다
# cp -a /var/lib/realm{,.backup}

# 패키지를 제거합니다. 데이터는 /var/lib/realm에 보관됩니다.
sudo apt-get remove realm-object-server-developer

# 패키지를 제거합니다 (1.0.0-BETA-4.8 이전 버전 명령어)
sudo apt-get remove realm-object-server-de
# 제거하기 전에 서비스를 중단합니다
제어중인 터미널 창에서 CTRL-C를 누릅니다

# 패키지를 제거합니다
realm-mobile-platform 폴더를 휴지통으로 이동합니다

Realm Functions

Realm Functions는 현재 베타 버전입니다. 이슈를 발견하면 Github에서 알려주세요.

Realm Functions는 Realm의 변경 사항에 반응하는 “서버리스” 로직을 추가할 수 있도록 합니다. 대시보드를 사용해서 모든 Realm 혹은 /myrealm/를 경로에 포함한 사용자들의 Realm처럼 특정 패턴에 일치하는 Realm의 변경 사항에 반응하는 기능을 생성하거나 편집, 시작, 중지, 삭제할 수 있습니다.

Realm Functions management screen

Realm Functions는 이벤트 핸들링 기능을 사용합니다. Function 자체는 Realm 오브젝트 서버의 글로벌 리스닝 API에 의해 호출되고 changeEvent 객체를 전달하는 Node.js 함수입니다.

Realm Functions 베타 버전은 Realm 플랫폼의 개발자 에디션에서 사용할 수 있지만 활성화된 Function은 세 개로 제한됩니다. 즉, 필요한 수만큼 Function를 만들 수 있지만 동시에 세 개만 사용할 수 있습니다. 프로페셔널과 엔터프라이즈 에디션에는 이런 제한이 없습니다. (Realm 플랫폼 Realm Functions의 전통적인 서버 측 이벤트 핸들링 처리 기능은 이 두 버전에서만 제공합니다.) 개발자 에디션 최종 릴리즈에서 다른 제한 사항이 추가적으로 적용될 수 있습니다.

Function을 만들려면 Realm 오브젝트 서버의 Create New Function 폼에서 다음 세 가지를 작성해야 합니다.

  1. 대시보드에 표시될 Function 스크립트의 이름
  2. 모니터링할 Realm을 지정하는 정규 표현식
  3. Function 본문

Realm URL 경로 지정 정규 표현식

Function이 어떤 Realm에서 변경 알림을 받을 지는 [정규 표현식][regex] (“regex”)에서 정의합니다. [Realm URL][rlurl]이 정규 표현식에 일치하는 Realm만이 Function을 발동합니다. 전체 정규 표현식 튜토리얼은 이 문서에서 다루지 않지만 실제 사용할 수 있는 예제를 몇 가지 보여드리겠습니다. [regex]: http://www.regular-expressions.info [rlurl]: /kr/docs/data-model/#opening-a-realm

  • 모든 Realm: .* (예를 들어 0개 이상 일치)
  • 공용 “catalog” Realm: ^/catalog$
  • 소유주에 상관없이 “settings”를 경로에 포함하는 Realm: ^/([0-9a-f]+)/settings$

기본 정규 표현식인 ^/([0-9a-f]+)/myrealm$은 어느 사용자가 소유했는지에 관계없이 “myrealm”이라는 이름을 가진 모든 Realm을 찾으며, 첫 번째 경로 세그먼트인 사용자 ID를 16진수 문자(0-9 숫자나 a-f 문자)로 제한합니다.

Function 작성

Function 본문을 편집하는 화면은 다음과 같은 코드 조각으로 시작합니다.

console.log("Starting function");
// 초기화 코드를 작성합니다.

module.exports = function(changeEvent) {
	// 이벤트 핸들러 코드를 작성합니다.

	console.log("Changes in realm at:", changeEvent.path);

	var realm = changeEvent.realm;
	
	for (var className in changeEvent.changes) {
	    var changes = changeEvent.changes[className];
	    var objects = realm.objects(className);
	    
	    console.log("Changes in Model:", className);
	    for (let pos of changes.insertions) {
	        console.log("- object inserted at position ", pos, " : ", objects[pos]);
	    }
	    for (let pos of changes.modifications) {
	        console.log("- object modified at position ", pos, " : ", objects[pos]);
	    }
	    for (let pos of changes.deletions) {
	        console.log("- object deleted at position ", pos);
	    }
	}
	console.log("");
};

이 함수가 바로 오브젝트 서버에서 Node.js가 실행할 이벤트 핸들러 입니다. 이벤트 핸들러는 네 개의 키가 있는 changeEvent 객체를 받습니다.

  • path: 변경된 Realm의 경로
  • realm: 변경된 Realm 자체
  • oldRealm: 변경이 적용되기 전 이전 상태의 Realm
  • changes: Realm 변경 객체의 해시 맵을 포함하는 객체

changes 객체 자체는 좀 더 복잡한 구조를 가집니다. 일련의 키/값 쌍으로 키는 객체의 이름, 값은 삽입, 삭제, 수정 목록의 키/값 쌍이 있는 다른 객체입니다. 이들 키에 대한 값은 Realm의 인덱스 값입니다. changeEvent의 전체 구조는 다음과 같습니다.

{
  path: "realms://server/user/realm",
  realm: <realm object>,
  oldRealm: <realm object>,
  changes: {
    objectType1: {
      insertions: [ a, b, c, ...],
      deletions: [ a, b, c, ...],
      modifications: [ a, b, c, ...]
    },
    objectType2: {
      insertions: [ a, b, c, ...],
      deletions: [ a, b, c, ...],
      modifications: [ a, b, c, ...]
    }
  }
}

샘플 코드는 실제로 모든 키에 접근하는 방법을 보여줍니다. 더욱 복잡한 예제는 프로페셔널과 엔터프라이즈 에디션 섹션의 이벤트 핸들링을 참고하세요. 이벤트 핸들러 함수 코드가 본질적으로 동일한 것을 확인할 수 있습니다. (해당 예제 코드의 NOTIFIER_PATH 변수는 Realm URL 경로 정규 표현식을 지정합니다.)

콘솔 로그

각 Realm Function은 편집 창 아래에 자체 콘솔 출력 창을 가집니다. console.log()를 통해 보내진 메시지나 에러를 여기서 볼 수 있습니다. 로그 창의 메시지를 모두 지우려면 Clear 버튼을 사용하세요.

Realm Functions에서 Node 모듈 호출

Function에서 Node 모듈을 사용해야 한다면 Realm 오브젝트 서버의 Node 모듈 디렉터리에서 커맨드 라인으로 해당 모듈을 설치해야 합니다.

개발자 에디션:

sudo -s
cd /usr/lib/node_modules/realm-object-server-developer
PATH=/usr/lib/realm-object-server-developer/node/bin:$PATH npm install <module-name>

프로페셔널 에디션:

sudo -s
cd /usr/lib/node_modules/realm-object-server-professional
PATH=/usr/lib/realm-object-server-professional/node/bin:$PATH npm install <module-name>

엔터프라이즈 에디션:

sudo -s
cd /usr/lib/node_modules/realm-object-server-enterprise
PATH=/usr/lib/realm-object-server-enterprise/node/bin:$PATH npm install <module-name>

개발자 에디션:

sudo -s
cd /usr/lib/nodejs/realm-object-server-developer
PATH=/usr/lib/realm-object-server-developer/node/bin:$PATH npm install <module-name>

프로페셔널 에디션:

sudo -s
cd /usr/lib/nodejs/realm-object-server-professional
PATH=/usr/lib/realm-object-server-professional/node/bin:$PATH npm install <module-name>

엔터프라이즈 에디션:

sudo -s
cd /usr/lib/nodejs/realm-object-server-enterprise
PATH=/usr/lib/realm-object-server-enterprise/node/bin:$PATH npm install <module-name>

터미널을 열고 cd 명령어로 Realm 오브젝트 서버 폴더로 이동한 다음 아래 명령어를 입력하세요.

PATH=.prefix/bin:$PATH
npm install <module_name>

접근 제어

Realm 오브젝트 서버는 허용된 사용자만 Realm 파일에 동기화할 수 있도록 접근 제어 방법을 포함합니다. 두 가지 개념이 있는데 인증과 승인입니다. 어떤 사용자에게 Realm의 접근을 주려면 Realm 오브젝트 서버는 사용자의 정체성을 검증하기 위해 사용자를 인증해야 하고 사용자가 Realm에 접근하기 위한 정확한 권한을 가지고 있는지 승인해야 합니다. 보다 자세한 내용은 다음과 같습니다.

  • Realm 오브젝트 서버는 사용자 인증서를 검증하고 사용자를 인증하기 위해 설정 가능한 인증 제공자를 사용합니다. 사용자는 몇 가지 사용자 인증서를 사용해 서버에 연결하고 검증을 위해 이는 적절한 제공자에 전달됩니다. 인증서가 검증되면 사용자는 Realm 오브젝트 서버에 접근 허가를 받습니다. 기존 계정과 맞지 않는 인증서에는 새 사용자 계정이 생성됩니다.
  • 클라이언트가 사용자로서 접근을 허가받은 후, Realm에 확인된 특정 주소로 읽기나 쓰기 접근을 요청할 수 있습니다. 사용자가 특정 경로에 대해 요청된 접근 권한을 가졌다면 Realm의 접근이 승인되었고 일반 동기화 연산들을 시작할 수 있습니다.

인증

Realm의 사용자/암호 방법 이상으로 Realm 앱에 대해 접근을 제어하는 제3자 인증 방법을 개발자가 활용하기 위해서는 인증 제공자를 사용합니다. Realm은 페이스북, 구글, 애플의 iCloud를 제공합니다.

이 제삼자 인증 제공자들은 현재 단일 서버 수준에서 운영되며 주어진 인증 방법을 사용할 필요가 있는 모든 서버에 설정되어야 합니다. 설정은 인증 방법과 요구된 키/비밀키를 확인하고 키 밸류 쌍을 제공해 완료됩니다.

이 정보는 Realm의 configuration.yml 파일의 auth.providers 부분에서 다룹니다.

아래는 제3자 인증 제공자가 각각 어떻게 통합되는지 각 서비스들을 응용하기 위해 연결할 개발자 페이지들을 보여주는 예입니다. 각 인증 제공자를 위한 전체적인 예제는 Realm 오브젝트 서버 configuration.yml 파일에서 찾을 수 있습니다.

사용자 이름/암호

  • 표준 사용자 이름/암호 인증은 언제나 활성화되어 있습니다.

Google

구글 OAuth 2.0 API 접근을 하고 google 부분에 클라이언트 ID 키를 입력하세요.

google:
  clientId: '012345678901-abcdefghijklmnopqrstvuvwxyz01234.apps.googleusercontent.com'

Facebook

페이스북 인증은 페이스북 제공자를 활성화하기 위해 어떤 설정을 요구하지 않습니다.

facebook: {}

Realm 오브젝트 서버에 수신된 페이스북 클라이언트 토큰은 페이스북 API들에 의해 검증을 확인하게 됩니다.

Azure Active Directory

azuread 공급자의 주석 처리를 제거하고 “Properties” 아래의 Azure Portal에 디렉토리 ID를 추가하세요.

azuread:
  tenant_id: '81560d038272f7ffae5724220b9e9ea75d6e3f18'

iCloud

iCloud는 애플 플랫폼들(iOS, tvOS, watchOS, macOS)에서만 사용 가능합니다.

Realm 오브젝트 서버를 사용해 CloudKit에 접근하려면 공개 키를 설정하고 애플의 CloudKit 웹 대시보드에 접속하고 애플리케이션을 위한 CloudKit 접근 키를 생성해야 합니다. 이 키들은 구체적인 Realm을 위한 Realm 오브젝트 서버의 CloudKit 인증 모듈의 설정을 위해 사용합니다.

  1. 터미널에서 Realm 플랫폼 디렉토리를 엽니다.

  2. 다음 OpenSSL 스크립트를 사용해서 개인 키를 생성하세요. openssl ecparam -name prime256v1 -genkey -noout -out cloudkit_eckey.pem

  3. CloudKit 대시보드에 제출할 공개 키를 생성하세요.

    openssl ec -in cloudkit_eckey.pem -pubout

  1. 개인 키를 생성하세요.

sudo openssl ecparam -name prime256v1 -genkey -noout -out /etc/realm/cloudkit_eckey.pem

  1. CloudKit 대시보드에 제출할 공개 키를 생성하세요.:

openssl ec -in /etc/realm/cloudkit_eckey.pem -pubout

Generating an access key with the CloudKit Dashboard

애플 개발자 계정을 사용하기 위해 Apple’s CloudKit Dashboard에 로그인해서 애플리케이션을 선택합니다. 대시보드의 왼쪽 사이드에서 “API Access”를 선택하고 “Server-to-Server Keys”를 선택합니다. 다음으로 “Add Server-to-Server Key”를 선택합니다. 새 키의 이름을 입력하고 위에서 생성한 공개 키에 붙여넣고 “Save”를 클릭합니다. 몇 초 후에 키가 생성되어 상단의 “Key ID” 섹션에 표시됩니다.

보안 안내: Realm CloudKit 인증에 사용하려면 개별 애플리케이션 용 새로운 비밀키를 만드세요. 비밀 키를 재 사용하는 것은 만약 비밀 키 자체가 위험해지거나 해지해야 할 때 공유된 키를 사용하는 전체 Realm이 위험해질 수 있습니다.

설정 파일에서 cloudkit 제공자의 주석을 제거하고 키 ID, 개인 키 경로, 컨테이너 ID와 환경 정보를 입력하세요.

cloudkit:
  ## CloudKit 키 ID
  key_id: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'

  ## 인증서가 있는 경로
  private_key_path: 'cloudkit_eckey.pem'

  ## 컨테이너 식별자. 도메인 이름 역순 표기.
  container: "iCloud.io.realm.exampleApp.ios"

  ## CloudKit이 사용될 할 환경. 기본은 'development'. 앱 스토어에 제품 배포를 위해서는
  ## 반드시 'production'을 사용해야 합니다.
  environment: 'development'

private_key_path 경로가 정확한지 확인하세요. Linux에서 위 단계를 수행했다면 /etc/realm/cloudkit_eckey.pem과 같아야 합니다.

사용자 정의 인증

Realm 오브젝트 서버는 외부 인증을 사용할 수 있는 기능을 지원합니다. 이를 통해 레거시 데이터베이스 또는 API로 사용자를 인증하거나, Realm 오브젝트 서버에서 즉시 지원되지 않는 공급자와 통합할 수 있습니다. 이 섹션에서는 서드 파티 인증 공급자를 설정하는 과정에 대해 안내합니다.

Realm 오브젝트 서버의 인증 기본 사항은 간단합니다. 클라이언트가 로그인을 시도하면 서버에서 몇 가지 자격 증명을 제공합니다. 서버는 주로 외부 서버 또는 API에 대해 이러한 자격 증명을 확인해서 응답을 기반으로 클라이언트에 권한을 부여합니다.

사용자 정의 인증 제공자는 어디에든 설치할 수 있지만 기본값으로 서버가 /usr/local/lib/realm/auth/providers를 찾도록 설정됩니다. 인증 공급자는 오브젝트 서버의 개발 API인 Node.JS 스크립트 형태를 취합니다.

인증 공급자 작성

Realm 오브젝트 서버를 시작하기 전에 인증 공급자에 필요한 모든 NPM 디펜던시를 설치해야 합니다. 사용자 지정 인증 공급자가 “Expected implementation for [provider name] to be a function, but got object”와 유사한 에러 메시지를 띄우며 실패하는 경우 모든 종속성을 사용할 수 있는지 확인하세요!

위 경로에 디렉터리가 아직 존재하지 않으면 디렉터리를 만들고 .js 확장자로 파일을 만듭니다. 파일 이름을 원하는대로 설정할 수 있지만 구현하고 있는 인증 공급자 유형을 나타낼 수 있는 것으로 명명하는 것을 권장합니다. 예를 들어 github.js와 같은 이름입니다. 이 예제에서는 클라이언트가 제공한 토큰을 외부 서버에 확인하도록 요청하는 FooAuth라는 샘플 공급자를 만들 예정입니다.

// fooauth.js

/**
 * 서버가 시작하면 호출됩니다.
 *
 * 인증 공급자의 생성자를 반환해야 합니다.
 *
 * @param {object} deps - 실행 중인 서버에서 본 구현으로 전달된 디펜던시
 * @param {function} deps.BaseAuthProvider - 사용할 기본 클래스
 * @param {object} deps.problem - 실패 시 던질 예외 집합
 * @param {object} deps.models - admin-Realm 모델
 * @returns {function}
 */
module.exports = function(deps) {
  return class FooAuthProvider extends deps.BaseAuthProvider {
    // 해당 사용자 정의 인증 공급자 이름 반환
    static get name() {
      return 'custom/fooauth';
    }

    // 요구되는 기본 옵션이 설정됐는지 확인 (선택적 기능)
    static get defaultOptions() {
      return {
        server: 'https://my.auth.server.example',
      }
    }

    constructor(name, options, requestPromise) {
      super(name, options, requestPromise);

      this.httpMethod = 'GET';
    }

    // 인증 유효성 검사
    verifyIdentifier(req) {
      // 클라이언트에서 제출한 토큰
      const token = req.body.data;

      // HTTP 요청을 위한 옵션
      const httpOptions = {
        uri: `${this.options.server}/api/auth?token=${token}`,
        method: this.httpMethod,
        json: true,
      };

      // 외부 공급자에게 보내는 요청을 만들고 결과 반환
      return this.request(httpOptions)
        .catch((err) => {
          // 다른 에러의 경우 src/node/services/problem/http_problem.js 확인
          throw new deps.problem.HttpProblem.Unauthorized({
            detail: `Something bad happened: ${err.toString()}`,
          });
        })
        .then((result) => {
          // 사용자 ID 값이 반환되는 `userId` JSON 키에 담긴다고 가정
          return result.userId;
        });
    }
  };
}

가상 인증 공급자, FooAuthProvider를 위해 새 클래스부터 만들겠습니다. FooAuthProviderBaseAuthProvider 클래스를 상속합니다. 이렇게 하면 promise 기반 HTTP 요청에 접근할 수 있습니다. 이제 공급자가 정의해야 하는 메서드를 살펴 보겠습니다.

  • name() 함수는 간단히 인증 공급자의 이름을 반환합니다. 이름은 저희와 서드 파티 공급자가 같은 이름을 사용해서 충돌하지 않도록 custom/으로 시작해야 합니다.

    이 이름을 사용해서 Realm 오브젝트 서버의 configuration.yml 파일에 옵션을 정의할 수 있습니다.

    custom/fooauth:
      server: 'https://newserver.example'

    this.options.server와 같이 this.options 하위의 공급자에게 이들 옵션을 적용할 수 있습니다.

  • defaultOptions() 함수는 선택적입니다. 코드가 정의되지 않은 경우에 대비해 코드에 필요한 모든 설정 파일의 기본 값을 반환합니다.

  • constructor는 이름, 옵션, Promise 요청을 받습니다. 생성자는 인스턴스 변수를 설정하고 설정 파일 값을 확인해서 다른 초기화 작업을 수행할 수 있습니다.

  • verifyIdentifier() 함수는 공급자의 핵심입니다. HTTP 요청과 함께 호출되며 사용자가 이미 시스템에 있으면 기존 사용자에 로그인하거나, 없으면 새 사용자를 만들기 위해 Realm 오브젝트 서버에서 사용할 고유 사용자 ID를 반환해야 합니다.

    이 예제에서는 생성자에 정의된 server 설정 변수와 httpMethod 변수로 httpOptions을 설정한 다음 공급자에게 해당 정보로 HTTP 요청을 합니다. 에러가 발생하면 deps.problem에서 예외를, 성공하면 사용자 ID를 반환합니다.

실제 사례를 보려면 Github에서 저희 AWS Cognito 공급자를 참조하세요.

인증 공급자 설정

사용자 지정 공급자를 작성했으니 서버에 이를 로드하도록 설정을 업데이트해야 합니다. 글로벌 설정 파일에 아래와 같이 코드를 추가합니다.

# configuration.yml
auth:
  providers:
    # 사용자 지정 인증 공급자는 ROS 제공 인증 공급자와 구별하기 위해 `custom/`로 시작해야 합니다.
    custom/fooauth:
      # `fooauth.js` 파일을 참조합니다.
      implementation: fooauth
      # 사용자 지정 인증 공급자에 정의된 옵션입니다.
      auth_server: 'https://another.server.example'

이 설정을 추가하면 ROS가 자동으로 JS 파일을 로딩하고 인증 공급자를 활성화합니다.

클라이언트에서 사용자 정의 공급자 사용

모든 client SDK는 사용자 정의 인증을 기본적으로 지원합니다. 올바른 로그인 기능을 사용해서 올바른 정보를 보내기만 하면 됩니다. 자세한 내용은 각 언어 문서의 “동기화” 하위의 “인증” 섹션을 확인하세요.

승인

Realm 객체 서버에 의해 관리되는 각 Realm에는 _접근 권한_이 설정돼 있습니다. 사용 권한은 서버의 기본적인 권한입니다. 사용 권한은 세 가지 불린 플래그를 사용해서 각 Realm에 설정됩니다.

  • mayRead Realm으로부터 사용자가 읽을 수 있는지를 표기합니다.
  • mayWrite Realm에 사용자가 쓸 수 있는지를 표기합니다.
  • mayManage 사용자가 Realm의 권한을 변경할 수 있는지 여부를 표기합니다.

Realm 권한은 기본 혹은 사용자별 기반으로 설정할 수 있습니다. 사용자가 Realm에 대한 접근을 요청하면 오브젝트 서버는 먼저 해당 Realm에서 해당 사용자에 대해 설정된 사용자별 권한이 있는지 확인합니다. 만약 없으면 Realm에 대한 기본 사용 권한이 사용됩니다. 예를 들어 Realm에 기본적으로 mayRead를 true로 설정하고, 개별 사용자에게 mayWrite 권한을 설정할 수 있습니다.

기본적으로 Realm은 소유자만 접근할 수 있습니다. 소유자는 모든 권한을 가지며 다른 사용자는 어떤 권한도 가지지 못합니다. 다른 사용자는 명시적으로 접근 권한을 받아야 합니다.

mayRead 권한 없이 mayWrite 권한만 설정하는 것과 같은 쓰기-전용 권한은 현재 지원하지 않습니다.

어드민인 사용자는 항상 오브젝트 서버의 모든 Realm에 대한 모든 권한을 가집니다.

관리 Realm

모든 접근 관리 오퍼레이션은 특수한 권한 변경 객체를 관리 Realm(Management Realm) 에 작성하는 것으로 수행됩니다. 관리 Realm은 특수한 Realm으로, 내부에 생성된 객체는 서버가 다른 Realm의 기본 혹은 사용자별 권한을 변경하도록 요청합니다.

관리 Realm에 접근하는 방법은 사용하는 언어에 대한 문서를 참조하세요. Swift의 경우 SyncUser.managementRealm()와 같이, 일반적으로 사용자 객체에 대한 메서드를 호출하는 방식으로 접근합니다.

권한 변경 객체

사용자는 기존 Realm 파일 및 사용자의 권한을 변경하기 위해 매니지먼트 Realm에 PermissionChange를 만들 수 있습니다. 사용자별 권한과 기본 Realm 권한 모두 같은 방식으로 설정합니다. 사용자는 수정을 위해 관리하려는 Realm에 대한 mayManage 권한을 가져야 합니다.

PermissionChange 객체에는 다음 5개의 필드가 있으며, 처음 두 가지는 필수입니다. 나머지 권한 필드는 모두 선택 사항입니다.

  • realmUrl (string): realm의 URL, *의 경우 요청 사용자가 소유한 모든 Realm
  • userId (string): 권한이 수정될 사용자의 ID, *의 경우 Realm 기본 권한
  • mayRead (boolean): Realm 읽기 권한
  • mayWrite (boolean): Realm 쓰기 권한
  • mayManage (boolean): Realm 관리 권한

may* 플래그 중 하나가 PermissionChange 객체에 설정되지 않은 경우 해당 권한은 변경되지 않습니다. 사용자별 사용 권한은 항상 기본 권한보다 우선 순위가 높으므로 Realm에 대한 기본 사용 권한을 변경해도 개별 사용자에 대해 이미 설정된 사용 권한은 제거되지 않습니다.

PermissionChange 객체는 권한을 적용하려고 시도된 후에 Realm 오브젝트 서버에 의해 수정됩니다. 권한 변경이 성공하면 statusCode 필드가 0으로 설정되고 statusMessage 필드에 설정이 추가됩니다. 에러가 발생하면 statusCode0보다 큰 값으로 설정되고 statusMessage 필드에 에러 메시지가 저장됩니다.

PermissionChange 객체를 생성하고 사용하는 자세한 방법은 사용하는 클라이언트 언어 문서를 참고하세요.

권한 보내기와 응답

PermissionOfferPermissionOfferResponse 메커니즘으로 사용자간의 유연한 공유 관리가 가능합니다. PermissionOffer 객체는 PermissionChange와 비슷하게 기능하지만, 다른 사용자에게 권한을 부여하기 위해 보낼 수 있는 토큰을 작성하는 점이 다릅니다. 대략적인 단계는 다음과 같습니다.

  1. PermissionOffer 객체를 생성하고 관리 Realm에 추가합니다.
  2. 서버가 객체를 처리한 후 token 속성을 채웁니다.
  3. 이메일, 채팅, 사용자 API 등의 외부 메서드를 통해 token을 다른 사용자에게 보냅니다.
  4. 받은 사용자가 해당 토큰으로 PermissionOfferResponse 객체를 만들고 자신의 관리 Realm에 추가합니다.
  5. 서버가 객체를 처리한 후 성공 상태를 반환합니다.
  6. 해당 Realm과 동기화하기 위해 realmUrl 속성을 사용해서 PermissionOfferResponse 객체를 채웁니다.

자세한 내용은 사용하는 클라이언트 언어의 문서를 참조하세요.

어드민 Realm

관리 Realm에 의해 변경된 내용은 궁극적으로 Realm 오브젝트 서버 인스턴스가 제어하는 모든 Realm 파일 및 사용자에 대한 완전한 사용 권한 집합을 가지고 있는 신뢰할 수 있는 전역 권한 저장소에 작성됩니다. 이 어드민 Realm은 오로지 오브젝트 서버 자신만이 수정할 수 있으며 Realm 데이터베이스 애플리케이션에서는 접근할 수 없습니다. 즉, 사용 권한을 수정할 수 있는 권한을 Realm 오브젝트 서버가 독점적으로 갖습니다.

고가용성

Realm 플랫폼의 고유한 특성은 오프라인-우선으로 설계됐다는 것입니다. 구조적으로 이는 클라이언트가 데이터의 로컬 복사본을 서버로부터 받고 이를 직접 읽거나 쓴다는 것입니다. 그런 다음 클라이언트 SDK는 네트워크가 연결될 때 비동기적으로 변경 사항을 전송하며, Realm 오브젝트 서버는 이런 변경 사항을 자동으로 통합해서 결정형 방식으로 저장합니다. 이러한 시스템의 결과로 클라이언트 관점에서 본질적으로 높은 가용성을 지니게 됩니다. 네트워크 상태나 서버 작업과 관계없이 항상 로컬에서 읽기 및 쓰기가 가능해집니다.

현재 서비스 손실을 방지할 수 있도록 자동 장애 조치를 지원하는 클러스터링 솔루션을 개발 중으로, 해당 기능은 엔터프라이즈 에디션에서 지원될 예정입니다. 문의하기를 통해 자세한 내용과 미리 사용하는 방법을 알려드립니다.

백업

Realm 오브젝트 서버는 버전에 따라 한 개나 두 개의 백업 시스템을 제공합니다.

  • Realm 플랫폼 버전에 포함된 수동 백업 시스템은 커맨드 라인 유틸리티를 통해 사용할 수 있습니다. 서버 오퍼레이션 중에 오브젝트 서버의 데이터를 사본을 만드는 작업을 트리거할 수 있습니다.

  • 엔터프라이즈 에디션에서만 제공되는 연속 백업 시스템은 Realm 오브젝트 서버의 메인 프로세스와 함께 실행되는 백업 서버입니다. 모든 동기화 Realm의 변경 사항을 지속적으로 감시하며, 하나 이상의 백업 클라이언트에 변경 사항을 보냅니다.

두 시스템 모두 Realm 오브젝트 서버가 장애 이후 재시작할 수 있는 Realm 디렉토리를 생성합니다. 백업된 데이터에는 사용자 Realm, 모든 사용자 계정 정보와 Realm 오브젝트 서버에서 사용하는 모든 메타데이터가 포함됩니다. Realm 오브젝트 서버를 오프라인으로 만들지 않고도 서버 실행 중에 수동 백업이나 연속 백업을 생성할 수 있습니다.

다음 문서는 수동 백업 기능에 대한 것입니다. 연속 백업에 대해서는 엔터프라이즈 에디션 문서의 연속 백업을 참고하세요.

수동 백업은 Realm의 실행 인스턴스를 백업하는 콘솔 명령어입니다. 서버에서 보관을 위해 장기 저장 장치에 저장할 수 있는 백업을 만들기 위해 이 명령어를 서버를 종료하지 않고 몇 번이던지 실행할 수 있습니다. 백업이 지속되는 방식에 대한 작동 시스템에 대한 아무런 지식이 없더라도 기능을 수행할 수 있도록 하기 위해, 이 명령어는 디스크 오류가 발생했을때 서버가 다시 시작하는데 필요한 모든 것을 포함하는 디렉토리 구조를 만듭니다.

결과 디렉토리를 압축해서 Amazon S3이나 Online C14와 같은 오프 사이트 위치로 전송하는 것을 권장합니다.

Realm이 백업 프로세스 중에 수정될 수 있으므로, 백업 명령어는 Realm의 트랜잭션 기능을 사용해서 각 Realm의 일관적인 스냅샷을 만듭니다. 그러나 서버가 지속적으로 실행되고 있으므로 백업된 Realm은 서버의 특정 시간의 인스턴스 상태를 나타내지는 않습니다. 백업이 진행되는 동안 서버에 추가된 Realm은 백업에서 완전히 제외될 수 있고, 이런 경우 다음 백업에 포함됩니다.

커맨드 라인에서 다음 명령어로 realm-backup을 실행할 수 있습니다.

realm-backup SOURCE TARGET
  • SOURCE는 Realm 오브젝트 서버의 데이터 디렉토리입니다. (일반적으로 /etc/realm/configuration.yml내의 storage.root_path에 정의되어있습니다.)
  • TARGET은 백업 파일이 저장될 디렉토리입니다. 안전 상의 이유로 이 디렉토리는 백업이 시작될 때 존재하지 않거나 내부가 비어 있어야 합니다.

백업 명령이 완료되면 TARGETSOURCE와 같은 서브 디렉토리 구조와 모든 개별 Realm의 백업을 가진 디렉토리가 됩니다.

백업에서 서버 복구

Realm 오브젝트 서버의 데이터가 손실되거나 손상된 경우 백업된 데이터로 새로운 Realm 오브젝트 서버를 다시 시작할 수 있습니다. 서버를 중지하고 수동 백업 절차의 최신 백업 디렉토리(예를 들어 TARGET 디렉토리나 연속 백업 클라이언트에서 지정한 storage.root_path 디렉토리 등)를 Realm 오브젝트 서버의 데이터 디렉토리(예를 들어 수동 백업 절차의 SOURCE 디렉토리)에 복사해서 간단히 수행할 수 있습니다. 백업이 Realm 오브젝트 서버의 데이터 디렉토리에 모두 복사 되면 서버를 재시작할 수 있습니다.

백업에서 클라이언트 복구

서버가 해당 백업에서 복원될 경우 가장 최근의 백업 이후에 Realm 오브젝트 서버에 추가된 데이터는 손실됩니다. 하지만 Realm 데이터베이스 클라이언트는 오브젝트 서버와 지속적으로 통신하기 때문에 서버 상에 더이상 존재하지 않는 최신 데이터로 업데이트될 수도 있습니다.

이러한 불일치가 발생하면 Realm 오브젝트 서버는 클라이언트에 에러 메시지를 보내고 데이터 동기화를 거부합니다. 동기화 불일치와 관련된 오류 메시지는 다음과 같습니다.

  • 207 “잘못된 서버 파일 식별자 (INTENT)”
  • 208 “잘못된 클라이언트 파일 식별자 (IDENT)”
  • 209 “잘못된 서버 버전 (IDENT, UPLOAD)”
  • 211 “다른 히스토리 분기 (IDENT)”

클라이언트가 이런 오류 메세지를 받은 이후에는 재시작해야만 서버에서 동기화를 지속할 수 있습니다. 오류를 수신한 Realm의 로컬 복사본에 있는 모든 데이터를 지우고 서버와 다시 동기화합니다. 이렇게 해야 클라이언트가 Realm 오브젝트 서버에 있는 모든 데이터만을 가지고 일관된 상태가 됩니다.

이런 상황이 발생한 경우 클라이언트는 로컬에만 있던 일관성이 없는 데이터를 잃게 됩니다. 즉, Realm 오브젝트 서버가 손상돼고 백업에서 복원되는 시간 동안 추가된 데이터와 같은 데이터입니다. 이런 잠재적 데이터 손실을 최소화하려면 연속 백업 시스템을 사용하는 것을 권장합니다. 만약 연속 백업 시스템을 사용할 수 없다면 수동 백업 시스템을 자주 실행하세요.

문제해결

Realm 대시보드 외부 접근을 위한 방화벽 규칙 확인

어떤 요소들은 Realm 오브젝트 서버의 동기화 요소와 Realm 대시보드에 대한 외부 (localhost이 아닌) 접근에 영향을 줍니다. 접근을 허가하려면 서버에서 9080 포트를 열어야 합니다.

표준 리눅스 도구를 사용한다면 아래 명령어들로 포트를 엽니다.

sudo iptables -A INPUT -p tcp -m tcp --dport 9080 -j ACCEPT
sudo service iptables save

방화벽을 어떻게 설정하는지 더 자세한 정보를 얻으려면 CentOS 6 Documentation을 참고하세요.

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-port=9080/tcp --permanent
sudo firewall-cmd --reload
sudo ufw allow 9080/tcp
sudo ufw reload

만약 사용하는 배포판이 표준 방화벽을 쓰지 않는다면 환경에 맞추어 명령들을 수정해야 합니다.

설정 에러

일반적으로는 기본 설정이 대부분의 설치에 적합합니다. (시스템은 미리 프로그래밍된 기본 값을 가지고 있습니다) Realm 오브젝트 서버 설정 파일 내의 주석 처리된 설정들에서 커스터마이징 방법을 볼 수 있습니다. 커스터마이징된 설정 파일에 에러가 있다면 에러 메시지는 기본 로그 위치에 쓰입니다. (macOS에서는 터미널 창이며 리눅스 시스템에서는 /var/log/realm-sync.log입니다.)

만약 Realm 오브젝트 서버가 시작하지 않는다면 설정 파일의 에러가 원인일 것입니다. 설정 파일을 디버깅하기 위해 터미널에서 시작하는 내장 체커를 다음과 같이 사용할 수 있습니다.

realm-object-server --check-configuration /etc/realm/configuration.yml

macOS에서 실행한다면 configuration.yml의 설정 파일 경로를 바꾸세요.

에러가 발생하면 서버의 파서는 자세한 에러 메시지를 출력합니다. 이 에러메시지는 문제를 표시하며 가능한 에러가 발생한 부분을 하이라이트합니다. 모든 에러를 고친 다음에는 서버를 시작합니다. ^C를 눌러 서버를 중단하고 시스템을 재부팅하거나 Realm 오브젝트 서버를 리눅스의 systemd이나 macOS의 start-object-server.command으로 재시작하세요.

에러 메시지는 대개 자기 설명적이고 여기에 잠재적인 단서가 있습니다.

  • Realm 오브젝트 서버를 동작하기 위해 다음의 내용이 필수적입니다.
    • 저장소 루트 디렉터리: Realm 오브젝트 서버가 모든 파일을 저장하는 곳입니다. storage.root_path을 설정하거나 명령행 인터페이스에서 --root 인자로 주세요. 디렉터리는 반드시 ROS가 시작하기 전에 존재해야 합니다.
    • 인증 키 쌍: Realm 오브젝트 서버에 인증된 클라이언트만 보안 접근을 하게 합니다. auth.private_key_path을 설정하거나 명령행 인터페이스에서 --private-key 인자를 주세요. auth.public_key_path를 설정하거나 명령행 인자 --public-key를 주세요. 이 키들은 반드시 PEM 포맷이어야 하고 쌍이 맞아야 합니다.
  • 응답 포트의 설정은 중복될 수 없습니다. listen_port는 파일에 대해 유일해야 합니다. 추가적으로 포트들은 다른 프로세스에 연결되지 말아야 합니다.

  • HTTPS 프락시는 proxy.https.certificate_pathproxy.https.private_key_path에 유효한 인증과 비밀 키가 주어질 때만 시작됩니다. 인증과 비밀 키는 PEM 포맷이어야 하고 쌍이 맞아야 합니다. 인증서는 셀프 사인이면 안됩니다.

운영시 발생할 수 있는 에러

때때로 Realm 오브젝트 서버 로그를 확인하는 것이 디버깅 용도에 유용합니다. 이는 macOS의 터미널 창이나 리눅스 시스템의 /var/log/realm-sync.log입니다. Realm 오브젝트 서버는 두가지 특별한 종류의 에러와 워닝 진단을 생성합니다. 이는 시스템 관리자와 개발자에 유용합니다.

세션 특화 에러

  • 204 “Illegal Realm path (BIND)” Realm 경로가 해당 사용자에게 유효하지 않습니다.

  • 207 “Bad server file identifier (IDENT)” 로컬 Realm 연결된 서버 사이드 Realm이 존재하지 않습니다. 이는 일반적으로 서버 상태가 완전히 리셋되는 경우에 발생합니다.

  • 211 “Diverging histories (IDENT)” 로컬 Realm이 존재하지 않은 서버 버전을 지정합니다. 이는 일반적으로 서버 상태가 부분적으로 리셋되는 경우에 발생합니다. (예를 들어 백업이 복원된 경우입니다.)

클라이언트 수준 에러

  • 105 “Wrong protocol version (CLIENT)” 클라이언트와 서버가 업그레이드 불일치로 인해 다른 버전의 동기화 프로토콜을 사용합니다.

  • 108 “Client file bound in other session (IDENT)” 같은 시점에 클라이언트 측의 Realm 같은 파일에 여러 동기화 세션이 있습니다.

  • 203 “Bad user authentication (BIND, REFRESH)” 서버가 잘못된 토큰을 생성했거나 SDK가 뭔가 잘못되었습니다.

  • 206 “Permission denied (BIND, REFRESH)” 사용자가 주어진 경로의 Realm에 접근할 권한이 없습니다.

충돌 해결

모바일의 특징 중 하나는 언제나 온라인이라고 기대할 수 없다는 것입니다. 접속이 끊어지는 것은 일상이며 네트워크는 느리며 접속은 불안정합니다. 그럼에도 불구하고 사람들은 여전히 앱이 잘 동작하길 원합니다!

두 명 이상의 사용자가 데이터의 같은 부분을 독립적으로 변경하고 충돌을 만드는 상황을 만날 수 있습니다. 연결이 완전해도 폰과 서버의 소통 대기 시간은 충분히 길 수 있고 같은 시점에 충돌 변경을 만들 수 있습니다.

다른 순서로 변경이 적용되더라도 특정 규칙 적용해 양쪽 모두 같은 결과로 수렴되도록 Realm은 병합을 합니다.

전통적인 데이터베이스에서 할 수 있었던 완벽한 일관성(perfect consistency)은 더 이상 존재하지 않으며 이를 “강한 결과적 일관성 (strong eventual consistency)”이라 부릅니다. 원하는 대로 일관된 결과를 얻으려면 인지해야 하는 규칙이 있다는 단점이 있습니다만 몇 가지 규칙만 따른다면 장비들이 완전히 오프라인으로 동작하더라도 여전히 온라인이 되었을 때 의미 있는 결과로 수렴하게 됩니다.

매우 고수준의 규칙은 다음과 같습니다.

  • 삭제는 언제나 이깁니다. 만약 한쪽에서 객체가 삭제가 되면 다른 쪽에서 뒤에 데이터를 변경하더라도 데이터는 언제나 삭제된 채로 있습니다.

  • 마지막 변경이 이깁니다. 양쪽에서 같은 속성을 변경한다면 마지막에 변경된 것으로 값이 결정됩니다.

  • 목록에 삽입은 시간 순으로 됩니다. 만약 두 요소가 같은 위치에 삽입되었다면, 먼저 들어온 요소가 다른 요소보다 먼저 삽입됩니다. 이 말은 양쪽에서 요소들은 목록의 끝에 삽입했다면 이는 삽입 시점에 따라 나타나게 됩니다.

기본 키가 있는 객체

기존의 관계형 데이터베이스의 기본 키가 테이블의 행을 고유하게 식별하는 필드인 것처럼, _기본 키_는 Realm의 객체를 고유하게 식별하는 값을 같는 등록 정보입니다. Realm에서 기본 키가 필수인 것은 아니지만, 모든 오브젝트 타입에서 기본 키를 활성화할 수 있습니다. Realm 모델 클래스에 id와 같이 기본 키로 사용하려는 속성을 추가한 다음 Realm에 해당 속성이 기본 키임을 알리면 되며, 방법은 사용하는 언어에 따라 다릅니다. Cocoa에서는 primaryKey() 클래스 메서드를 오버라이드하며, Java와 .NET에서는 어노테이션을 사용합니다. 자세한 내용은 각 언어 문서를 참조하세요.

Realm 모델 클래스에 기본 키를 적용하면 Realm은 다른 객체가 Realm에 동일한 키 값을 추가하지 못하게 보장합니다. 기존의 객체를 업데이트 할 수도 있는데, 실제 동작은 Realm의 객체 복사본을 가지고 오지 않고도 특정 객체의 속성 부분집합만을 업데이트할 수 있습니다. 자세한 내용은 각 언어 문서를 참조하세요.

더 많은 내용을 기본 키 튜토리얼(영문)에서 볼 수 있습니다.

문자열

문자열은 아직 클라이언트 API로 공개되지 않았습니다.

문자열은 스칼라 값이며 문자들의 목록으로 볼 수 있어 특별합니다. 문자열은 다른 새 문자열로 설정(전체 문자열이 대치되는)하거나 문자열을 수정 할 수 있습니다. 여러 사용자가 같은 문자열을 수정할 때 (구글 독스와 같은 곳에서 경험하는 것과 같이) 문자 단위로 충돌을 해결할 수 있습니다.

카운터

카운터는 아직 클라이언트 API로 공개되지 않았습니다.

숫자를 세기 위해 쓰는 것은 특이한 경우입니다. 많은 프로그래밍 언어는 (v += 1과 같은) 증가 연산을 구현해 값을 읽어 증가시키고 다시 저장하게 합니다. 이는 여러 당사자가 이를 동시에 하는 경우에 명확하게 동작하지 않습니다. (그들은 동시에 10을 읽고 11을 저장시켜서 의도한 12 대신 11이란 병합된 결과를 얻게 합니다).

이런 기본 동작을 제공하기 위해 값을 증가 (혹은 감소) 시킨다는 의도를 표현하고 병합 과정에 올바른 과정을 찾게 해야 합니다. 위의 문자열과 마찬가지로 전체 값의 갱신을 제공하거나 더 많은 의미를 제공하게 편집하거나 충돌 해결에 대한 더 정확한 제어를 허락해야 합니다.

사용자 정의 충돌 해결

사용자 정의 충돌 해결을 하는 표준적인 방법은 값을 목록으로 변경하는 것입니다. 각자 그들의 갱신을 목록에 올릴 수 있고 데이터 모델에 적용하고 싶은 충돌 해결 모델을 적용하는 것입니다.

이런 방법으로 최대 값, 최소 값, 최초 값 승리, 마지막 값 승리 등의 여러분이 원하는 방법을 구현할 수 있습니다.

여기서 소개하는 기능은 Realm 플랫폼 프로페셔널 및 엔터프라이즈 에디션에서 제공됩니다. 더 자세한 내용을 알아보고 무료 평가판을 시작해보세요.

Note: 이 문서는 엔터프라이즈 및 프로페셔널 에디션에 제한된 기능만 설명합니다. 설정과 일반적인 사용법 및 문제 해결을 포함한 다른 항목에 대해서는 주 오브젝트 서버 문서를 참고하세요.

설치/업그레이드

프로페셔널 에디션과 엔터프라이즈 에디션을 설치하고 기능을 구성, 탐색하는 방법에 대한 자세한 내용은 기술 참고 사항 2017-003, Realm 플랫폼 안내를 참고하세요.

Note: 프로페셔널 및 엔터프라이즈 버전은 현재 Linux에서만 사용할 수 있습니다.

프로페셔널 에디션으로 업그레이드

Realm 플랫폼 프로페셔널 에디션의 14일 무료 평가판을 사용하려면 신청서를 작성하세요. 접근 토큰을 이메일로 보내 드립니다.

Realm 오브젝트 서버를 프로페셔널 에디션으로 업그레이드하는 경우 먼저 개발자 에디션을 삭제해야 합니다. 그 다음 이메일로 보내드린 접근 토큰을 사용해 배포 환경에 맞게 다음과 같은 단계를 따르세요.

# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 설치하기
sudo yum -y install realm-object-server-professional

# 서비스 활성화하고 시작하기
sudo chkconfig realm-object-server on
sudo service realm-object-server start
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 설치하기
sudo yum -y install realm-object-server-professional

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-professional/script.deb.sh | sudo bash

# 저장소 업데이트
sudo apt-get update

# Realm 오브젝트 서버 설치하기
sudo apt-get install realm-object-server-professional

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

엔터프라이즈 에디션으로 업그레이드

Realm 오브젝트 서버를 엔터프라이즈 에디션으로 업그레이드하는 경우 먼저 개발자/프로페셔널 에디션을 삭제해야 합니다. 그 다음 이메일로 보내드린 접근 토큰을 사용해 배포 환경에 맞게 다음과 같은 단계를 따르세요.

# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 설치하기
sudo yum -y install realm-object-server-enterprise

# 서비스 활성화하고 시작하기
sudo chkconfig realm-object-server on
sudo service realm-object-server start
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 설치하기
sudo yum -y install realm-object-server-enterprise

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 패키지 저장소 설정하기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# 저장소 업데이트
sudo apt-get update

# Realm 오브젝트 서버 설치하기
sudo apt-get install realm-object-server-enterprise

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server

로드 밸런싱

이 기능은 프로페셔널과 엔터프라이드 에디션에서만 가능합니다. 이 곳에서 더 많은 기능을 알아보세요.

Realm 오브젝트 서버는 고성능으로 설계됐으며, 단일 인스턴스로도 수만 개 이상의 동시 연결을 처리할 수 있습니다. 그러나 수백만 이상의 동시 접속이 예상되는 대규모의 애플리케이션의 경우, 여러 서버가 필요할 수 있습니다. Realm 플랫폼 엔터프라이즈 에디션은 대규모 애플리케이션을 지원하고 있는 Realm 오브젝트 서버라도 얼마든지 그 수에 관계없이 수평적으로 확장할 수 있는 완벽한 솔루션을 제공합니다.

이 시스템은 클라이언트와 서버에 의해 사용되는 양방향 연결을 유지하는 로드 밸런서에 의해 동작합니다.

설치

각 백엔드 노드는 동일한 클러스터의 다른 백엔드 노드와 독립적으로 동작합니다. 각 백엔드 노드는 realm-sync-worker 바이너리의 인스턴스를 실행하는데, realm-sync-worker란 Realm 오브젝트 서버의 일부분으로 주로 실행되는 동기화 워커의 이름입니다. 설정이 필요하지 않지만 Realm 오브젝트 서버를 실행하는 서버 인스턴스에서 연결할 수 있어야 합니다.

동기화 워커를 설치하려면 아래 설명처럼 엔터프라이즈 저장소를 설정해야 합니다.

# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 엔터프라이즈 저장소 설정하기. 이미 ROS 엔터프라이즈를 설치했다면 건너 뛰세요.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버의 독립형 동기화 워커 설치
sudo yum -y install realm-sync-worker

# /etc/realm/token-signature.pub를 Realm 오브젝트 서버의 것으로 교체합니다

# 서비스 활성화하고 시작하기
sudo chkconfig realm-sync-worker on
sudo service realm-sync-worker start
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 엔터프라이즈 저장소 설정하기. 이미 ROS 엔터프라이즈를 설치했다면 건너 뛰세요.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버의 독립형 동기화 워커 설치
sudo yum -y install realm-sync-worker

# /etc/realm/token-signature.pub를 Realm 오브젝트 서버의 것으로 교체합니다

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-sync-worker
sudo systemctl start realm-sync-worker
# 토큰 변수 설정하기
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm 엔터프라이즈 저장소 설정하기. 이미 ROS 엔터프라이즈를 설치했다면 건너 뛰세요.
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# 저장소 업데이트
sudo apt-get update

# Realm 오브젝트 서버 설치하기
sudo apt-get install realm-sync-worker

# /etc/realm/token-signature.pub를 Realm 오브젝트 서버의 것으로 교체합니다

# 서비스 활성화하고 시작하기
sudo systemctl enable realm-sync-worker
sudo systemctl start realm-sync-worker

설정

Realm 오브젝트 서버의 configuration.yml의 “sync.servers” 섹션은 백엔드 노드의 클러스터를 설명합니다. 로드 밸런싱을 위해 각 백엔드 노드는 고유한 ID로 식별될 수 있어야 합니다. ID는 유효한 파일시스템 경로 구성요소라면 어느 문자열이든 가능합니다.

아래 예시를 참고하세요.

sync:
  servers:
  - id: 'alpha'
    address: '::'
    port: 7800
  - id: 'beta'
    address: 'beta.local'
    port: 7800
  - id: 'delta'
    address: 'delta.local'
    port: 7800

예제 설정 파일은 Realm 오브젝트 서버 설치 과정에서 추가 세부 사항으로 제공됩니다.

주소가 IPv6를 사용하는 경우 “0.0.0.0”나 “::”과 같은 모든 인터페이스를 나타내는 IP 주소를 각 클러스터 백엔드 노드의 “address” 필드에 지정하면 특별히 해석됩니다. 이 경우 로컬 동기화 워커가 “127.0.0.1”나 “::1” 등의 로컬호스트 IP 주소를 수신하기 시작해야 한다고 Realm 오브젝트 서버에 알립니다.

동기화 워커는 별도의 설정 파일인 sync-worker-configuration.yml을 사용합니다. 이 파일은 Realm 오브젝트 서버 파일의 부분 집합으로 기본적으로 워커 시작시 생성됩니다. sync-worker-configuration.ymlnetwork 섹션을 확인하고 listen_address 라인이 주석 처리되지 않고 올바르게 설정됐는지 확안하세요.

network:
  sync:
    listen_address: '0.0.0.0'

0.0.0.0의 주소는 모든 인터페이스를 수신 대기합니다. IP 주소로 특정 인터페이스를 지정할 수도 있습니다. 서버는 Realm 오브젝트 서버 설정 파일의 sync.servers 섹션에 지정돼야 합니다.

예제 설정은 Realm 오브젝트 서버 설치시 함께 제공되므로 추가 정보를 확인해 볼 수 있습니다.

장애 조치(failover)

이 기능은 프로페셔널과 엔터프라이드 에디션에서만 가능합니다. 이 곳에서 더 많은 기능을 알아보세요.

Realm 오브젝트 서버는 수동 장애 조치 를 지원하지만, 자동 장애 조치 는 지원하지 않습니다. 장애 조치를 사용하려면 동기화 워커와 함께 설정된 로드 밸런싱이 있어야 하며, 아래 “필수 구성 요소”에서 설명하는 것처럼 중복 동기화 워커나 Realm 오브젝트 서버가 있어야 합니다.

백업 동기화 워커로 전환

Sync Worker Failover Diagram

필수 구성 요소

연속 백업 클라이언트 섹션의 가이드에 따라 백업 클라이언트가 sync-worker를 실행하는 머신을 가리키도록 설정하세요. 설정 파일(object-server-backup-client.yml)의 network.server_address 설정은 동기화 워커의 IP 주소나 도메인 이름이어야 합니다.

이 백업 클라이언트와 같은 머신에 sync-worker를 설치하고 아직 시작하지 마세요.

동기화 워커를 “로드 밸런싱”의 설정 가이드에 맞게 다음과 같이 설정하세요.

  • 백업 클라이언트가 기록하고 있는 폴더를 가리키도록 storage.root_path를 설정합니다.
  • token-signature.pub 파일이 백업 클라이언트와 실행 중인 동기화 워커 양측에서 동일한지 확인합니다.

장애 조치 작동하기

sync-worker 머신의 동작이 실패한 다음 장애 조치 머신을 온라인 상태로 만들려면, 다음 단계를 따릅니다. (“장애 조치 머신”이란 이전 “필수 구성 요소” 섹션에서 실패한 동기화 워커를 대신하도록 설정한 머신입니다.)

  • 장애 조치 머신에서 백업 클라이언트 프로세스를 중지합니다. (Ubuntu 서버: systemctl stop realm-object-server-backup-client`)
  • 장애 조치 머신에서 동기화 워커를 시작합니다. (systemctl start realm-sync-worker)
  • Realm 오브젝트 서버의 configuration.yml 파일을 열고 실패한 sync-worker의 IP 주소나 호스트 이름을 장애 조치 머신의 IP 주소나 호스트 이름으로 변경합니다.
  • Realm 오브젝트 서버를 재시작합니다. (systemctl restart realm-object-server)

주의: 일부 모니터링 서비스는 기본 머신에 연결할 수 없을 때 장애 조치 머신의 IP 주소로 DNS 레코드를 자동으로 업데이트할 수 있으므로 세 번째 단계가 필요하지 않습니다. 혹은 세 번째 단계 대신 DNS 레코드를 수동으로 업데이트할 수도 있습니다. 두 경우 모두 동기화 워커의 DNS에 TTL (time-to-live)값을 최단 시간으로 지정해야 합니다. configuration.yml를 수정하는 대신 자동이나 수동으로 DNS 레코드를 변경하는 경우 최대 TTL 값의 시간이나 고객의 네임 서버가 이 설정을 따르지 않는 경우 더 오랜 시간 동안 Realm 오브젝트 서버에 연결하지 못할 수 있습니다.

backup 백업 Realm 오브젝트 서버로 전환

이 기능은 하나 이상의 sync-worker가 설정되어 동작하는 로드 밸런싱이 필요합니다.

Object Server Failover Diagram

필수 구성 요소

예비 버신에 Realm 오브젝트 서버를 설치합니다. (이것이 “장애 조치 머신”이 됩니다) 아직 서버를 시작하지 마세요. 클러스터에서는 동시에 하나의 Realm 오브젝트 서버만 실행할 수 있습니다.

실행 중인 Realm 오브젝트 서버와 백업 서버 양측에서 다음 파일이 동일한지 확인하세요.

  • configuration.yml
  • token-signature.pub
  • token-signature.key
  • 커스텀 인증 공급자

장애 조치 작동하기

기본 Realm 오브젝트 서버가 다운되었다면, 장애 조치 머신에서 Realm 오브젝트 서버를 시작하세요. Ubuntu 서버: systemctl start realm-object-server

시작시 장애 조치 머신이 sync-workers로부터 동기화된 데이터를 불러옵니다. 클라이언트 Realm 데이터베이스는 로드 밸런서를 가리키므로 설정을 변경할 필요가 없습니다. Amazon Web Services에서는 기본 Realm 오브젝트 서버에서 실행되는 상태 점검으로 ELB를 설정합니다.

고가용성

Realm 플랫폼의 고유한 특성은 오프라인-우선으로 설계됐다는 것입니다. 구조적으로 이는 클라이언트가 데이터의 로컬 복사본을 서버로부터 받고 이를 직접 읽거나 쓴다는 것입니다. 그런 다음 클라이언트 SDK는 네트워크가 연결될 때 비동기적으로 변경 사항을 전송하며, Realm 오브젝트 서버는 이런 변경 사항을 자동으로 통합해서 결정형 방식으로 저장합니다. 이러한 시스템의 결과로 클라이언트 관점에서 본질적으로 높은 가용성을 지니게 됩니다. 네트워크 상태나 서버 작업과 관계없이 항상 로컬에서 읽기 및 쓰기가 가능해집니다.

현재 서비스 손실을 방지할 수 있도록 자동 장애 조치를 지원하는 클러스터링 솔루션을 개발 중으로, 해당 기능은 엔터프라이즈 에디션에서 지원될 예정입니다. 문의하기를 통해 자세한 내용과 미리 사용하는 방법을 알려드립니다.

연속 백업

이 기능은 프로페셔널과 엔터프라이드 에디션에서만 가능합니다. 이 곳에서 더 많은 기능을 알아보세요.

Realm 오브젝트 서버의 엔터프라이즈 에디션에는 메인 프로세스와 함께 실행되는 백업 서버 가 포함됩니다. 이 서버는 실행 중인 오브젝트 서버의 상태를 모니터링하고 한 대 혹은 여러 대의 백업 클라이언트 에 변경 사항을 비동기적으로 보냅니다. 모든 클래이언트는 약간의 지연 시간을 두고 서버 상태 복사본을 유지합니다.

엔터프라이즈 에디션과 병행하여 메인 오브젝트 서버 문서에서 설명하는 수동 백업 시스템을 계속 사용할 수 있습니다. (수동 백업은 프로페셔널과 개발자 에디션에서 제공하는 유일한 백업 시스템입니다)

연속 백업 시스템은 암호화 및 인증된 접근없이 통신합니다! 보안을 유지하려면 백업 시스템을 방화벽 안에서 실행하세요.

백업 서버

백업 서버는 realm-object-server와 realm-sync-worker와 함께 설치되며, 다음 명령어를 실행해서 활성화합니다.

sudo chkconfig realm-object-server-backup-server on
sudo service realm-object-server-backup-server start
# realm-object-server가 실행될 때 자동으로 함께 실행됩니다
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
sudo systemctl status realm-object-server-backup-server
sudo systemctl enable realm-object-server
sudo systemctl start realm-object-server
sudo systemctl status realm-object-server-backup-server

설정은 백업 섹션 하위의 Realm 오브젝트 서버 YAML 파일(/etc/realm/configuration.yml) 에서 지정합니다. 백업 서버에서 사용하는 키는 다음과 같습니다.

설정 키 기본값 설명
backup.enable true 백업을 비활성화하려면 false로 설정
backup.network.listen_address 127.0.0.1 IP 어드레스/인터페이스
backup.network.listen_port 27810 백업의 리스닝 포트
backup.logging.level info Logging에서 설정한 로그 레벨
backup.logging.path /var/log/realm-object-server-backup-server.log (Linux) 로그 파일 경로, 빈 값인 경우 stderr

동기화 워커 클러스터에서 노드를 백업하는 경우, 백업 서버는 /etc/realm/sync-worker-configuration.yml에 있는 동기화 워커 설정 파일을 대신 읽습니다.

백업 클라이언트

Realm 오브젝트 서버 백업 클라이언트는 백업이 필요한 경우 각 머신에서 시작됩니다. 백업 클라이언트는 별도의 YAML에서 설정합니다.

백업 클라이언트를 설치하려면 앞서 설명한대로 엔터프라이즈 저장소를 설정해야 합니다.

# 토큰 변수 설정
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm의 엔터프라이즈 저장소 설정, 이미 ROS 엔터프라이즈를 설치한 경우 건너 뛰기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 백업 클라이언트 설치
sudo yum -y install realm-object-server-backup-client

# 백업이 설정된 Realm 오브젝트 서버를 가리키도록 설정 편집, 기본 구성에서는 Realm 오브젝트 서버와 백업 서버가 동일한 머신에 있다고 가정
vim /etc/realm/object-server-backup-client.yml

# 서비스를 활성화하고 시작
sudo chkconfig realm-object-server-backup-client on
sudo service realm-object-server-backup-client start
# 토큰 변수 설정
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm의 엔터프라이즈 저장소 설정, 이미 ROS 엔터프라이즈를 설치한 경우 건너 뛰기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.rpm.sh | sudo bash

# Realm 오브젝트 서버 설치
sudo yum -y install realm-object-server-backup-client

# 백업이 설정된 Realm 오브젝트 서버를 가리키도록 설정 편집, 기본 구성에서는 Realm 오브젝트 서버와 백업 서버가 동일한 머신에 있다고 가정
vim /etc/realm/object-server-backup-client.yml

# 서비스를 활성화하고 시작
sudo systemctl enable realm-object-server-backup-client
sudo systemctl start realm-object-server-backup-client
# 토큰 변수 설정
export PACKAGECLOUD_TOKEN=<the token you received via email>

# Realm의 엔터프라이즈 저장소 설정, 이미 ROS 엔터프라이즈를 설치한 경우 건너 뛰기
curl -s https://$PACKAGECLOUD_TOKEN:@packagecloud.io/install/repositories/realm/ros-enterprise/script.deb.sh | sudo bash

# 저장소 업데이트
sudo apt-get update

# Realm 오브젝트 서버 설치
sudo apt-get install realm-object-server-backup-client

# 백업이 설정된 Realm 오브젝트 서버를 가리키도록 설정 편집, 기본 구성에서는 Realm 오브젝트 서버와 백업 서버가 동일한 머신에 있다고 가정
vim /etc/realm/object-server-backup-client.yml

# 서비스를 활성화하고 시작
sudo systemctl enable realm-object-server-backup-client
sudo systemctl start realm-object-server-backup-client

설정 파일은 /etc/realm/object-server-backup-client.yml에 있습니다.

백업 클라이언트 설정에 사용하는 키는 다음과 같습니다.

설정키 기본값 설명
storage.root_path   백업을 저장할 디렉터리, 복구된 Realm 오브젝트 서버는 이 디렉터리를 루트 경로로 시작
network.server_address   백업 서버의 IP 어드레스/인터페이스
network.server_port 27810 백업 서버의 IP 어드레스/인터페이스
network.reconnect_delay 2000 백업 서버에 연결하려는 시도 사이의 지연 시간(밀리 초), 클라이언트는 연결이 끊어진 후에 자동으로 다시 연결
logging.level info Logging에서 설정한 로그 레벨
logging.path /var/log/realm-object-server-backup-client.log (Linux) 로그 파일 경로, 빈 값인 경우 stderr

동기 백업

동기 백업 기능은 Realm 플랫폼 2.0 엔터프라이즈 에디션에서 제공합니다. 2.0 이전의 버전에서는 제공되지 않습니다. 자세한 내용은 Realm 담당자에게 문의하세요!

Realm 오브젝트 서버 엔터프라이즈 에디션에는 로드 밸런싱에서 설명하는 sync-worker 시스템을 사용해서 동기적으로 백업을 유지할 수 있습니다. 두 개의 동기화 워커는 프라이머리(primary)레플리카(replica) 로 작동하며 네트워크를 통해 통신합니다. 레플리카는 프라이머리 복사본이 자체 복사본을 업데이트한 이후에 모든 Realm의 증분 업데이트를 받습니다. 프라이머리 동기화 워커의 동작이 실패하면, 레플리카를 새 프라이머리로 재시작하고 프락시를 리디렉션해서 Realm 오브젝트 서버를 지속할 수 있습니다. 동기 백업을 사용하면 프라이머리에 업로드된 클라이언트 변경 집합이 프라이머리에서 레플리카로 전송됩니다. 레플리카는 복사본을 저장한 후 프라이머리로 확인 응답을 보냅니다. 그러면 클라이언트에 변경 집합 전송 성공에 대한 확인 응답이 전송됩니다.

Note: 동기 백업 대신 엔터프라이즈 에디션과 함께 오브젝트 서버 문서에서 설명된 수동 백업 시스템을 사용할 수 있습니다. (수동 백업은 개발자 에디션과 프로페셔널 에디션에서 제공하는 유일한 백업 시스템입니다.)

동기 백업 시스템의 장점은 프라이머리와 레플리카에서 동시에 데이터 손실이 일어나지 않는 한 클라이언트가 리셋되지 않는다 는 점입니다. 클라이언트의 Realm 로컬 복사본의 버전이, 동기화되고 있는 Realm 오브젝트 서버의 버전보다 높을 때만 클라이언트가 리셋됩니다. 이런 상황은 서버가 손상에서 복원됐지만 로컬 클라이언트가 충돌 후 복원 전에 동기화되지 않은 변경 사항을 만들 때 발생합니다. 이 경우 로컬 Realm은 서버의 복사본으로 완전히 대체됩니다.

클라이언트 Realm 데이터베이스는 성공적인 업로드 확인을 수신할 때까지 변경 집합 데이터를 지우지 않습니다. 따라서 동기 백업 시스템을 사용하는 경우 프라이머리와 레플리카가 동시에 동작에 실패하지 않는 한 데이터가 손실되지 않습니다. 클라이언트는 클라이언트는 프라이머리와 레플리카 양측이 모두 데이터 사본을 받을 때까지 확인 응답을 받지 않습니다.

동기 백업 시스템은 데이터 손실을 방지할 뿐만 아니라 내부 ID와 버전 번호의 일관성을 보장하므로 모든 클라이언트에 영향을 미치지 않고도 프라이머리를 레플리카로 교체할 수 있습니다.

오퍼레이팅 모드

백업 시스템은 별도의 시스템이 아닌 동기화 워커로 구축됩니다. 다음 네 가지 모드 중 하나로 Realm 동기화 워커를 시작할 수 있습니다.

  • 레플리카 없이 프라이머리만: 백업을 수행하지 않는 표준 동기화 워커
  • 비동기 레플리카가 있는 프라이머리: 연결된 레플리카에 데이터를 전달하는 서버와 표준 동기화 워커. 비동기 레플리카가 있는 프라이머리는 해당 레플리카를 기다리지 않으며 클라이언트는 항상 지연 시간이 최소화됩니다. 하지만 클라이언트가 데이터 복제 이전에 데이터 쓰기 확인 응답을 수신하므로 데이터 손실 방지가 보장되지 않습니다.
  • 동기 레플리카가 있는 프라이머리: 클라이언트에 데이터를 다운로드하고 확인 응답을 보내기 전에 데이터가 레플리카에 성공적으로 복사되는 것을 보장하는 동기화 워커. 이 시스템은 비동기 레플리카가 있는 프라이머리보다 지연 시간이 다소 높지만 데이터 손실을 방지합니다.
  • 레플리카: 프라이머리의 동기화 워커를 위한 레플리카로 작동하는 동기화 작업자. 레플리카는 클라이언트에서 연결할 수 없습니다.

프라이머리는 동일한 포트를 사용해서 Realm 오브젝트 서버 연결과 레플리카 연결을 수신합니다. 프라이머리 동기화 워커와는 하나의 레플리카만 연결할 수 있습니다. 기존 레플리카가 연결된 상태에서 새 레플리카가 연결되면, 새 레플리카에 기본 설정이 제공되고 이전 연결은 닫힙니다.

레플리카는 성공할 때까지 지속해서 프라이머리에 연결을 시도합니다. 즉, 연결이 끊어지면 레플리카는 무기한으로 연결을 시도합니다.

프라이머리나 레플리카의 시작 순서는 큰 상관이 없으므로 어느 쪽이라도 먼저 시작할 수 있습니다.

프로토콜

동기화 워커에는 전체 Realm 전송이나 증분 업데이트, 두 가지 방식으로 데이터를 교환할 수 있는 백업 프로토콜이 있습니다. 레플리카가 빈 슬레이트에서 시작되는 경우라면 전체 Realm 전송이 가장 효율적입니다. 레플리카는 매우 길지도 모를 전체 변경 히스토리를 재생하는 대신, 전체 Realm을 한 번에 받습니다. Realm 백업 시스템은 레플리카가 처음부터 시작하는 경우 전체 Realm 전송을 사용합니다. 레플리카와 프라이머리가 동기화되면, 워커는 증분 업데이트를 사용하도록 전환됩니다.

프라이머리에서 Realm이 변경되면 프라이머리가 레플리카로 증분 업데이트를 보냅니다. 이는 충돌이나 네트워크 연결 장애로 업데이트가 손실되는 경우 다시 생성되지 않습니다. 대신 연결이 재설정되면 프라이머리와 레플리카가 각각의 해당 Realm 복사본의 버전 번호를 확인하고 프라이머리가 레플리카보다 높은 번호인 경우 전체 Realm이 다시 전송됩니다. (과도한 네트워크 오류가 발생하는 환경이 아닌 한 이런 경우는 자주 발생하지 않습니다) 동기화 워커는 마이그레이션없이도 언제든지 레플리카가 있는 프라이머리로 재설정될 수 있습니다.

각 Realm은 다른 모든 Realm과 독립적으로 백업되므로 하나의 Realm을 사용하는 동기화 클라이언트의 다운로드로 인해 다른 Realm의 백업 활동이 차단될 염려가 없습니다.

병합과 성능

레플리카에서 변경 집합을 병합하는 방법은 두 가지입니다. 프라이머리가 수행한 병합 연산을 레플리카가 반복하는 방법과, 프라이머리가 수행한 병합 연산 결과를 레플리카가 받는 방법입니다. 전자는 네트워크 대역폭을 덜 사용하며, 후자는 레플리카의 CPU 시간을 덜 사용합니다.

Realm 백업 시스템을 사용하면 병합 연산이 매우 느린 경우가 아니라면 레플리카가 병합을 수행하도록 합니다. 프라이머리가 병합 연산 수행 시간을 측정해서 연산 시간이 긴 경우 느린 병합 연산이 반복되지 않도록 전체 Realm을 전송합니다.

동기화 백업이 되는 프라이머리인 경우 다른 프라이머리 타입보다 지연 시간이 조금 더 걸립니다. 하지만 파이프라이닝을 사용하므로 특정 유스 케이스에서 동기화 프라이머리는 다른 프라이머리 타입보다 쓰기 트랜잭션을 적게 수행합니다. 따라서 다른 타입보다 동기 백업을 하는 프라이머리가 높은 성능을 보일 수 있습니다. (물론 다른 두 타입에도 파이프라이닝을 사용하도록 재작성할 수 있습니다.)

보안

동기화 워커는 기본적으로 암호화되지 않은 TCP를 통해 통신하며, 이를 TCP를 통한 TLS를 사용하도록 설정할 수도 있습니다. TLS를 사용하면 백업 연결이 도청 및 변조 위험이 최소화된 보호되지 않은 네트워크 중개자를 통과할 수 있습니다.

레플리카는 백업 데이터 수신 가능성 증명을 위해 공유 비밀(shared secret)을 프라이머리에 제시해야 합니다. 공유 비밀은 문자열이며 프라이머리와 레플리카를 위한 설정 파일에 저장됩니다. 시스템 관리자는 공유 비밀을 생성하고 이를 프라이머리와 레플리카에 입력해야 합니다.

장애 조치

프라이머리나 레플리카의 동작이 실패하면서 데이터 손실이 일어나면 새 설정으로 시스템을 재시작해야 합니다.

가장 간단한 경우는 레플리카 동작이 실패하는 경우로, 새 레플리카를 시작하고 프라이머리를 가리키도록 해야 합니다. 프라이머리의 동작이 실패하는 경우 레플리카를 프라이머리로 재시작하거나, 레플리카의 루트 디렉터리를 새 프라이머리에 전송해야 합니다. 새 레플리카 역시 시작해야 합니다.

프락시는 항상 프라이머리를 가리키도록 구성해야 합니다.

설정

로드 밸런싱과 마찬가지로, 동기화 워커는 configuration.yml 파일에서 설정됩니다. 설정을 변경하려면 동기화 워커를 새 설정 파일로 재시작해야 합니다.

backup:을 위한 새로운 설정 옵션은 다음과 같습니다.

  • master_slave_shared_secret: 프라이머리와 레플리카 사이에 공유되는 공유 비밀
  • master_addressmaster_port: 레플리카가 프라이머리를 연결하기 위한 정보
  • operating_mode: 위에서 설명한 네 가지 오퍼레이팅 모드로 다음 값 을 사용합니다.
    • master_with_no_slave
    • master_with_asynchronous_slave
    • master_with_synchronous_slave
    • slave

operating_mode가 지정되지 않는 경우 master_with_no_slave를 기본값으로 해서 레플리카가 없는 일반 동기화 워커를 생성합니다.

동기화 워커가 레플리카로 설정된 경우, 설정에서 프라이머리(마스터)의 주소/포트를 지정해야 합니다. 레플리카의 설정 파일에 지정된 프라이머리의 주소/포트는 프라이머리의 수신 대기 주소/포트와 같아야 합니다.

레플리카는 초기 연결 중에 프라이머리에 공유 비밀을 보냅니다. 공유 비밀이 일치하면 프라이머리는가 백업 교환을 진행합니다.

프라이머리와 레플리카를 위한 configuration.yml 파일 예제입니다. 레플리카가 수동으로 승격해서 프라이머리로 전환되는 경우인 복원된 프라이머리와 레플리카의 내용도 포함합니다.

Primary

storage:
  root_path: root-dir-original-primary

network:
  sync:
    listen_address: '1.2.3.4'
    listen_port: '9001'

backup:
  operating_mode: 'master_with_synchronous_slave'

  master_slave_shared_secret: 'A secret'

Replica

storage:
  root_path: root-dir-original-replica

network:
  sync:
    listen_address: '5.6.7.8'
    listen_port: '9002'

backup:
  operating_mode: 'slave'

  master_address: '1.2.3.4'
  master_port: '9001'

  master_slave_shared_secret: 'A secret'

Recovered Primary (a replica promoted to a primary)

storage:
  root_path: root-dir-original-replica

network:
  sync:
    listen_address: '9.10.11.12'
    listen_port: '9003'

backup:
  operating_mode: 'master_with_synchronous_slave'

  master_slave_shared_secret: 'Possibly another secret'

Replica for Recovered Primary

storage:
  root_path: root-dir-new-replica

network:
  sync:
    listen_address: '13.14.15.16'
    listen_port: '9004'

backup:
  operating_mode: 'slave'

  master_address: '9.10.11.12'
  master_port: '9003'

  master_slave_shared_secret: 'Possibly another secret'

주의:

  • 레플리카의 backup.master_addressbackup.master_port는 프라이머리의 network.listen_addressnetwork.listen_port와 같아야 합니다.
  • 레플리카의 root_path는 다음 프라이머리의 root_path가 됩니다. 동기화 워커가 멈춘 동안 전체 디렉터리를 다른 위치로 복사할 수도 있습니다.
  • 레플리카는 동기화 연결을 허용하지 않더라도 들어오는 연결을 수신 대기합니다. /info 엔드 포인트는 레플리카를 포함하여 모든 동기화 워커에 대해 활성화됩니다.
  • 필요한 경우 프락시를 리디렉션해야 합니다.
  • 통신 중인 프라이머리와 레플리카는 같은 공유 비밀을 가져야 하지만, 공유 비밀은 언제든지 변경할 수 있습니다.

모니터링

Realm 오브젝트 서버 워커는 localhost:8125를 수신하는 statsd 에 대한 메트릭 전송을 지원합니다. 이런 메트릭 모니터링을 위해 graphite 등의 시스템에 전달할 수 있습니다.

모든 메트릭 키는 realm.<hostname> 접두어로 시작합니다.

realm.example.com.connection.online
realm.example.com.connection.failed
realm.example.com.realms.open
realm.example.com.protocol.violated
realm.example.com.protocol.bytes.received
realm.example.com.authentication.failed

메트릭

Name Type Description
<prefix>.client.unsyncable counter 클라이언트가 히스토리 불일치로 인해 Realm의 동기화를 시작하지 못할 때마다 작동합니다. 이 경우 클라이언트는 자신의 Realm 파일을 삭제한 다음 서버에서 복구해야 합니다. 서버 동작이 실패하고 백업에서 복구되는 경우에 발생할 수 있습니다.
     
<prefix>.session.started counter 세션이 시작할 때마다 작동합니다. 세션은 인증되기 전에도 시작된 것으로 간주됩니다.
<prefix>.session.online gauge 현재 제공되는 전체 세션 수입니다.
<prefix>.session.failed counter 세션 레벨의 에러가 있을 때마다 작동합니다.
<prefix>.session.terminated counter 세션이 끝날 때마다 동작합니다.
     
<prefix>.connection.started counter 클라이언트가 연결을 열 때마다 작동합니다.
<prefix>.connection.online gauge 현재 열린 전체 연결 수입니다. 하나의 연결에서 다수의 세션이 제공될 수 있습니다.
<prefix>.connection.failed counter 연결에 대한 저수준 에러로 accept(), read(), write() 중에 실패가 발생할 때마다 작동합니다.
<prefix>.connection.terminated counter 연결이 종료될 때마다 동작하며, 실패한 경우에도 동작합니다.
     
<prefix>.realms.open gauge 현재 열린 Realm의 전체 개수입니다.
     
<prefix>.authentication.failed counter 인증이 실패될 때 작동합니다. 예를 들어 토큰이 유효하지 않거나 만료되는 경우입니다. 일반적으로 발생하면 안되는 에러입니다.
<prefix>.permission.denied counter 권한 실패시 작동합니다. 예를 들어 다른 Realm의 토큰으로 어떤 Realm에 접근을 시도하거나 다운로드 전용 토큰으로 업로드를 시도하는 경우입니다. 일반적으로 발생하면 안되는 에러입니다.
<prefix>.protocol.<version>.used counter 프로토콜 버전인 <version>으로 연결이 된 경우마다 동작합니다. 이를 통해 초기화된 각 프로토콜 버전의 연결 수를 파악하고 서버와 앱을 업데이트하는 시간을 최적화할 수 있습니다.
<prefix>.protocol.violated counter 동기화 프로토콜을 위반할 때마다 작동합니다. 애플리케이션이 너무 오래되거나 잘못 작성된 경우에도 발생할 수 있습니다.
     
<prefix>.protocol.bytes.received counter 서버가 업로드 메시지를 받을 때마다 작동합니다.
<prefix>.protocol.bytes.sent counter 서버에 다운로드 메시지가 보내질 때마다 작동합니다.
     
<prefix>.protocol.bytes.received gauge 시작 이후 전송받은 총 바이트
<prefix>.protocol.bytes.sent gauge 시작 이후 전송한 총 바이트

프로페셔널 및 엔터프라이즈 API 활성화

Realm은 현재 Node.js 버전 6만을 지원합니다. Realm 오브젝트 서버는 Node.js 4 이하, 5, 7, 8과 호환되지 않습니다. 권장 버전은 6.10.입니다.

Node.js 애플리케이션에서 이벤트 핸들링, 데이터 접근, 데이터 커넥터 기능을 사용하려면 접근 토큰 을 애플리케이션에 포함해서 API를 활성화해야 합니다. (이 토큰은 평가 버전에 가입하거나 프로페셔널 또는 엔터프라이즈 에디션을 구매하는 시점에 이메일을 통해 전송됩니다.) Node.js 애플리케이션의 시작 부분에서 토큰을 포함하고 오브젝트 서버에 대한 setAccessToken 호출을 만듭니다.

var token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// 프로페셔널 에디션 API 잠금 해제
Realm.Sync.setAccessToken(token);

접근 토큰을 코드에 저장하는 대신 파일에서 불러올 수도 있습니다.

RealmSync.setAccessToken(fs.readFileSync('./access-token', 'utf-8'));

이벤트 핸들링

Realm 대시보드Realm Functions로 이벤트 핸들러를 관리할 수 있는 단순하고 강력한 인터페이스를 제공합니다. Functions를 사용하면 이벤트에 대한 전체 Node.js를 생성하지 않고도 아래처럼 handleChange() 콜백만 다룰 수 있습니다.

Realm 오브젝트 서버의 독점적인 기능은 이벤트 핸들링입니다. 이 기능은 Realm 객체 서버에 걸리는 전역 이벤트 리스너 API를 통해 서버측 Node.js SDK가 제공되므로 Realm 전체의 변경 사항을 관찰할 수 있습니다. 즉, 모든 Realm, 혹은 특정 패턴과 일치하는 Realm의 변화를 수신할 수 있습니다. 예를 들어 사용자 설정 데이터를 가상 경로가 /~/settings인 각 사용자마다 고유한 Realm으로 분리하는 앱 구조라면 모든 사용자의 settings Realm의 변경 사항에 반응하는 리스너를 설정할 수 있습니다.

변경 사항이 서버로 동기화될 때마다 변경 사항에 대한 응답으로 사용자가 정의한 서버측 로직을 실행할 수 있는 알림이 발동됩니다. 이 알림에서 업데이트된 Realm의 가상 경로와 Realm 객체, 변경된 객체에 대한 정밀한 알림이 제공됩니다. 최종으로 동기화된 트랜잭션에서 삽입, 삭제, 수정된 객체의 클래스 이름별로 분류된 객체 색인은 변경 세트에서 볼 수 있습니다.

이벤트 핸들러 생성

Realm의 이벤트 핸들링을 사용하려면 간단한 Node.js 애플리케이션을 만들어야 합니다.

서버 파일을 저장할 디렉터리를 만들고 package.json 파일을 생성합니다. Node.js와 npm, npm 패키지 매니저는 이 JSON 파일로 애플리케이션을 정의하고 외부 디펜던시를 지정합니다.

npm init를 사용해서 대화 형식으로 이 파일을 만들 수도 있습니다. 텍스트 편집기를 사용해서 아래와 같은 간단한 구조 파일을 직접 만들어도 됩니다.

{
    "name": "MyApp",
    "version": "0.0.1",
    "main": "index.js",
    "author": "Your Name",
    "description": "My Cool Realm App",
    "dependencies": {
        "realm": "^1.8.0"
    }
}

Realm 플랫폼을 1.8 버전 이상으로 지정했습니다. 애플리케이션에 다른 의존성이 있다면 dependencies 섹션에 추가합니다.

package.json를 올바르게 설정했다면 아래 명령어를 입력하세요.

npm install

이 명령어는 디펜던시에 있는 모든 모듈을 다운로드하고 압축을 풀어서 설정합니다.

이벤트 핸들러는 어드민 권한으로 오브젝트 서버에 접근해야 하므로 오브젝트 서버의 어드민 토큰이 필요합니다. Linux에서는 다음 명령어로 토큰을 볼 수 있습니다.

cat /etc/realm/admin_token.base64

macOS에서는 Realm 플랫폼 폴더 내의 realm-object-server 폴더에 토큰이 저장돼 있습니다. 해당 폴더로 이동해서 아래 명령어로 토큰을 확인하세요.

cd path-to/realm-mobile-platform
cat realm-object-server/admin_token.base64

샘플 index.js 파일은 아래와 같습니다. 이 예제는 /~/private라는 가상 경로에 위치한 사용자별 개인 Realm에 대한 변경 사항을 수신합니다. 해당 Realm에서 업데이트된 Coupon 객체를 찾아서 쿠폰 코드를 검증합니다. 아직 검증되지 않았다면 검증 결과를 Coupon 객체의 isValid 속성에 넣습니다.

var Realm = require('realm');

var ACCESS_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// 프로페셔널 에디션 API 잠금 해제
Realm.Sync.setAccessToken(ACCESS_TOKEN); 

// 여기에 Realm 어드민 토큰을 입력
//   Linux:  cat /etc/realm/admin_token.base64
//   macOS:  cat realm-object-server/admin_token.base64
var ADMIN_TOKEN = 'ADMIN_TOKEN';

// Realm 오브젝트 서버의 URL
var SERVER_URL = 'realm://127.0.0.1:9080';

// 정규 표현식을 넣으면 관찰할 Realm 파일을 제한합니다.
// 이 작업은 별도의 단계로 수행되므로
// 필요하지 않은 경우 정밀한 변경 세트를 계산하는데 비용이 소비되지 않습니다.
var NOTIFIER_PATH = '/^\/([0-9a-f]+)\/private$/';

// 변경 사항이 있을 때마다 관찰된 모든 Realm 파일에 대해 handleChange 콜백이 호출됩니다.
// 이 필드에는 경로, Realm, 변경 전의 Realm 버전,
// 이 변경에서 추가, 삭제, 수정된 모든 객체를 나타내는 인덱스가 포함됩니다.
function handleChange(changeEvent) {
  // 사용자 개인 Realm에 대한 업데이트만 구독하는 필터를 사용한다고 가정하고
  // 가상 경로에서 사용자 ID를 추출합니다.
  var matches = changeEvent.path.match(/^\/([0-9a-f]+)\/private$/);
  var userId = matches[1];

  var realm = changeEvent.realm;
  var coupons = realm.objects('Coupon');
  var couponIndexes = changeEvent.changes.Coupon.insertions;

  for (var couponIndex of couponIndexes) {
    var coupon = coupons[couponIndex];
    if (coupon.isValid !== undefined) {
      var isValid = verifyCouponForUser(coupon, userId);
      // 주의: 여기에 작성하면 후속 알림이 발동하므로
      // 이로 인해 무한한 변경이 발생하지 않도록 주의하세요!
      realm.write(function() {
        coupon.isValid = isValid;
      });
    }
  }
}

// 어드민 사용자 생성
var adminUser = Realm.Sync.User.adminUser(adminToken);

// 이벤트 핸들러 콜백 등록
Realm.Sync.addListener(SERVER_URL, adminUser, NOTIFIER_PATH, 'change', handleChange);

console.log('Listening for Realm changes');

이벤트 핸들러의 핵심은 changeEvent 객체에 전달되는 handleChange() 함수입니다. 이 객체에는 다음 네 개의 키가 있습니다.

  • path: 변경된 Realm의 경로 (위에서 match를 사용해서 사용자 ID 추출)
  • realm: 변경된 Realm 자신
  • oldRealm: 변경이 적용되기 전 기존 상태인 변경된 Realm
  • changes: Realm에서 변경된 객체의 해시 맵을 포함하는 객체

changes 객체는 좀 더 복잡한 구조를 갖고 있습니다. 일련의 키/값 쌍으로, 키는 객체의 이름(위 코드에서는 Coupon)이며, 값은 또다른 객체로 삽입, 삭제, 수정을 나열하는 키/값 쌍들입니다. 여기서 키는 Realm의 인덱스 값입니다. changeEvent의 전체 구조는 다음과 같습니다.

{
  path: "realms://server/user/realm",
  realm: <realm object>,
  oldRealm: <realm object>,
  changes: {
    objectType1: {
      insertions: [ a, b, c, ...],
      deletions: [ a, b, c, ...],
      modifications: [ a, b, c, ...]
    },
    objectType2: {
      insertions: [ a, b, c, ...],
      deletions: [ a, b, c, ...],
      modifications: [ a, b, c, ...]
    }
  }
}

다음처럼 새로 삽입된 쿠폰의 인덱스와 쿠폰을 얻을 수 있습니다.

var realm = changeEvent.realm;
var coupons = realm.objects('Coupon');
var couponIndexes = changeEvent.changes.Coupon.insertions;

다음으로 for (var couponIndex of couponIndexes) 루프를 사용해서 인덱스를 순회하면서 각각의 변경된 쿠폰을 얻을 수 있습니다.

다른 서비스와 통합

다른 서비스와 이벤트 핸들링 프레임워크를 통합하는 전체 예제는 스캐너 앱 튜토리얼을 참고하세요. 예제의 경우 IBM Watson의 Bluemix와 통합했습니다.

데이터 접근

Realm 오브젝트 서버 프로페셔널 및 엔터프라이즈 에디션을 사용하면 서버를 시작할 때 생성된 관리 토큰을 사용해서 모든 공유 Realm 서버에 접근하고 이를 변경할 수 있습니다. 즉, 해당 Realm의 모든 데이터에 접근할 수 있습니다.

Linux에서 어드민 토큰을 검색하려면 아래 명령어를 사용하세요.

cat /etc/realm/admin_token.base64

macOS에서는 토큰이 zip 파일 내부의 realm-object-server 폴더에 저장돼 있습니다.

cat realm-object-server/admin_token.base64

이 토큰을 Realm.Sync.User 객체를 동기적으로 생성할 수 있습니다. 이렇게 만든 사용자 객체를 Realm 생성자에 넘겨서 서버 측의 모든 Realm과 연결할 수 있습니다.

// 어드민 사용자를 이용해서 Realm 열기
var adminToken = '3x4mpl3T0k3n…';
var adminUser = Realm.Sync.User.adminUser(adminToken);
var realm = new Realm({
  sync: {
    user: admin_user,
    url: 'realm://object-server-url:9080/my-realm',
  },
  schema: [{...}
  }]
});

어드민 사용자를 사용하면 Realm URL은 관리자가 아닌 인증에서 사용자 ID로 해석되는 ~ 문자를 포함하지 않습니다. 어드민 사용자에게는 사용자 ID가 없습니다. 비관리자 인증에 대해서는 오브젝트 서버 접근 제어 문서의 인증 섹션을 확인하세요.

데이터 커넥터

이 기능은 프로페셔널과 엔터프라이드 에디션에서만 가능합니다. 이 곳에서 더 많은 기능을 알아보세요.

Realm 오브젝트 서버 엔터프라이즈 에디션은 모든 하위 오브젝트 서버 작업 및 데이터에 접근할 수 있는 Node.js 기반의 어댑터 API를 제공합니다. 이 API으로 동기화된 Realm을 PostgreSQL와 같은 레거시 데이터베이스와 상호 작용하도록 할 수 있습니다. Realm은 외부 데이터베이스와 실시간으로 동기화됩니다. 클라이언트 애플리케이션에서는 Realm 데이터베이스 API를 사용해서 실시간 네이티브 객체 작업의 이점을 누릴 수 있습니다.

{
    "name": "MyApp",
    "version": "0.0.1",
    "main": "index.js",
    "author": "Your Name",
    "description": "My Cool Realm App",
    "dependencies": {
        "realm": "^1.8.0"
    }
}

다른 의존성을 모두 지정했으면, 모듈을 다운로드하고 압축 해제한 후 설정하는 npm install 명령어를 사용하세요.

이벤트 핸들러 API와 마찬가지로 어드민 권한으로 오브젝트 서버에 접근해야 하므로 오브젝트 서버의 어드민 토큰이 필요합니다. Lunux에서는 다음 명령어로 토큰을 볼 수 있습니다.

cat /etc/realm/admin_token.base64

OmacOS에서는 Realm 플랫폼 폴더 내의 realm-object-server 폴더에 토큰이 저장돼 있습니다. 해당 폴더로 이동해서 아래 명령어로 토큰을 확인하세요.

cd path-to/realm-mobile-platform
cat realm-object-server/admin_token.base64

어댑터 API를 사용하려면 오브젝트 서버에서 명령을 수신하고 외부 데이터베이스의 API를 호출해서 읽고 쓰는 번역기 역할을 해당 Node.js 애플리케이션이 수행해야 합니다. 다음 코드에 샘플 애플리케이션을 소개합니다.

var Realm = require('realm');

var ACCESS_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";

// 엔터프라이즈 에디션 API 잠금 해제
Realm.Sync.setAccessToken(ACCESS_TOKEN); 

var adapterConfig = {
  // 여기에 Realm 어드민 토큰을 입력
  //   Linux:  cat /etc/realm/admin_token.base64
  //   macOS:  cat realm-object-server/admin_token.base64
  admin_token: 'ADMIN_TOKEN',

  // Realm 오브젝트 서버의 URL
  server_url: 'realms://127.0.0.1:9080',

  // 어댑터 API 파일의 로컬 경로
  local_path: './adapter',

  // 관찰할 Realm을 한정할 정규 표현식
  realm_path_regex: '/^\/([0-9a-f]+)\/private$/'
};

class CustomAdapter {
  constructor(config) {
    this.adapter = new Realm.Sync.Adapter(
      config.local_path,
      config.server_url,
      Realm.Sync.User.adminUser(config.admin_token),
      config.realm_path_regex,

      // 이 콜백은 새 트랜잭션을 사용할 수 있을 때마다 지정된 경로를 처리하기 위해 호출됩니다.
      // 인자는 변경 사항을 사용할 수 있는 Realm 경로입니다.
      // realm_path_regex와 일치하는 모든 Realm에 대해 호출됩니다.
      (realm_path) => {
        var current_instructions = this.adapter.current(realm_path);
        while (current_instructions) {
          // 정의된 경우 현재 명령어 배열을 처리합니다
          this.process_instructions(current_instructions);

          // 다음 트랜잭션 진행을 위해 호출됩니다.
          this.adapter.advance(realm_path);
          current_instructions = this.adapter.current(realm_path);
        }
      }
    )
  }

  // Adapter.current(path)에서 반환된 명령어 리스트를 넘깁니다
  process_instructions(instructions) {
    instructions.forEach((instruction) => {
        // 각 유형의 명령어에 대한 연산을 수행합니다
        switch (instruction.type) {
          case 'INSERT':
            insert_object(instruction.object_type, instruction.identity, instruction.values);
            break;
          case 'DELETE':
            delete_object(instruction.object_type, instruction.identity);
            break;
          // ... 다른 모든 관련 명령어 유형에 대한 핸들러를 추가하세요
          default:
            break;
        }
      })
  }
}

Adapter.current에서 반환된 각 명령어 객체는 다음 문자열 중 하나의 type을 가집니다. 명령 처리를 위한 데이터를 포함하는 둘 이상의 다른 속성도 설정됩니다.

  • INSERT: 새 객체 삽입
    • object_type: 삽입되는 객체 타입
    • identity: 객체의 기본 키 값이나 객체의 행 인덱스
    • values: 삽입할 객체의 속성 이름과 속성 값의 맵
  • SET: 기존 객체의 속성 값 설정
    • object_type: 객체 타입
    • identity: 객체의 기본 키 값이나 객체의 행 인덱스
    • values: 객체를 업데이트할 속성 이름과 속성 값의 맵
  • DELETE: 기존 객체 삭제
    • object_type: 객체 타입
    • identity: 객체의 기본 키 값이나 객체의 행 인덱스
  • CLEAR: 주어진 타입의 객체를 모두 삭제
    • object_type: 객체 타입
  • LIST_SET: 주어진 리스트 인덱스의 모든 객체를 다른 객체로 설정
    • object_type: 객체 타입
    • identity: 객체의 기본 키
    • property: 변형할 리스트 속성의 속성 이름
    • list_index: 설정할 리스트 인덱스
    • object_identity: 설정되는 객체의 기본 키나 객체의 행 인덱스
  • LIST_INSERT: 리스트의 주어진 인덱스에 객체 삽입
    • object_type: 객체 타입
    • identity: 객체의 기본 키
    • property: 변형할 리스트 속성의 속성 이름
    • list_index: 삽입할 리스트 인덱스
    • object_identity: 삽입할 객체의 기본 키나 객체의 행 인덱스
  • LIST_ERASE: 주어진 인덱스에서 리스트의 객체 삭제: 리스트에서 객체를 지우지만 Realm에는 존속
    • object_type: 객체 타입
    • identity: 객체의 기본 키
    • property: 변형할 리스트 속성의 속성 이름
    • list_index: 삭제할 리스트 인덱스
  • LIST_CLEAR: 모든 객체를 삭제하고 리스트 제거: 객체는 Realm에 존속
    • object_type: 객체 타입
    • identity: 객체의 기본 키
    • property: 삭제할 리스트 속성의 속성 이름
  • ADD_TYPE: 새 타입 추가
    • object_type: 타입 이름
    • primary_key: 타입의 키 속성 이름
    • properties: Realm.ObjectSchema에 설명된 속성 맵
  • ADD_PROPERTIES: 기존 타입에 속성 추가
  • CHANGE_IDENTITY: 기존 객체의 행 인덕스 변경: 기본 키가 있는 객체에는 호출되지 않음
    • object_type: 객체 타입
    • identity: 객체의 이전 행 값
    • new_identity: 객체의 새로운 행 값

모든 명령어 유형과 전달되는 데이터를 포함한 상세 정보는 Realm.Sync.Adapter 클래스의 API 참조 문서를 확인하세요.

PostgreSQL 데이터 커넥터는 이미 구현됐으며, MongoDB, Microsoft SQL 서버 등 더 많은 작업을 진행하고 있습니다. 모든 데이터 커넥터는 애플리케이션의 특정 요구에 맞게 커스터마이징할 수 있습니다. Realm 엔터프라이즈 고객이시라면 담당자에게 자세한 내용을 문의하세요.