이 문서는 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 브라우저

개발자는 Realm 브라우저로 Realm을 관찰하고 편집할 수 있습니다. Realm 브라우저는 Realm 오브젝트 서버의 macOS나 Linux 인스턴스에 연결될 수 있습니다. 주의: Realm 브라우저는 현재 macOS에서만 사용할 수 있습니다.

Realm 브라우저의 Connect to Object Server 옵션을 사용하려면 자동으로 생성된 어드민 토큰을 받아와야 합니다.

  1. 어드민 계정의 사용자 이름/이메일 주소 및 암호 지정
  2. Realm 오브젝트 서버가 생성한 어드민 토큰 제공

어드민 토큰은 서버의 텍스트 파일에 저장됩니다. 리눅스의 경우에는 다음 명령어로 토큰을 볼 수 있습니다.

cat /etc/realm/admin_token.base64

macOS 토큰은 realm-object-server 폴더에 저장되어 있습니다.

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

macOS에서 Realm 브라우저로 Realm들을 살펴보기

서버 설정

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 모바일 플랫폼 개발자 에디션을 프로페셔널이나 엔터프라이즈 에디션으로 업그레이드하려면 프로페셔널/엔터프라이즈 에디션 문서를 참조하세요.

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 문서를 확인하세요.

제거하기

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이란 병합된 결과를 얻게 합니다).

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

사용자 정의 충돌 해결

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

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