

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 푸시 동기화 구현
<a name="push-sync"></a>

****  
Amazon Cognito Sync를 처음 사용하는 경우 [AWS AppSync](https://aws.amazon.com/appsync/)를 사용하세요. Amazon Cognito Sync와 마찬가지로 AWS AppSync 는 디바이스 간에 애플리케이션 데이터를 동기화하기 위한 서비스입니다.  
앱 기본 설정이나 게임 상태 같은 사용자 데이터를 동기화할 수 있습니다. 또한 이러한 기능을 더욱 확장해, 복수의 사용자가 공유 데이터를 실시간으로 동기화하고 협업할 수 있게 합니다.

Amazon Cognito는 자격 증명과 디바이스 간의 연결 관계를 자동으로 추적합니다. 푸시 동기화 기능을 사용하면 자격 증명 데이터가 변경될 경우 지정한 자격 증명의 모든 인스턴스가 통지되도록 할 수 있습니다. 특정 자격 증명에 대해 동기화 스토어 데이터가 변경될 때마다 푸시 동기화는 해당 자격 증명과 연결된 모든 디바이스가 변경 사항에 대해 알리는 자동 푸시 알림을 받도록 합니다.

**참고**  
푸시 동기화는 JavaScript, Unity 또는 Xamarin에 대해 지원되지 않습니다.

먼저 푸시 동기화에 대한 계정을 설정하고 Amazon Cognito 콘솔에서 푸시 동기화를 활성화해야 푸시 동기화를 사용할 수 있습니다.

## Amazon Simple Notification Service(Amazon SNS) 앱 생성
<a name="create-an-amazon-SNS-app"></a>

[SNS 개발자 가이드](https://docs.aws.amazon.com/sns/latest/dg/SNSMobilePush.html)의 설명에 따라, 지원되는 플랫폼에 대해 Amazon SNS 앱을 생성하고 구성합니다.

## Amazon Cognito 콘솔에서 푸시 동기화 사용
<a name="enable-push-sync-in-the-amazon-cognito-console"></a>

Amazon Cognito 콘솔을 통해 푸시 동기화를 활성화할 수 있습니다. [콘솔 홈 페이지](https://console.aws.amazon.com/cognito/home)에서 다음을 수행합니다.

1. 푸시 동기화를 활성화할 자격 증명 풀 이름을 클릭합니다. 자격 증명 풀에 대한 **대시보드** 페이지가 표시됩니다.

1. **대시보드(Dashboard)** 페이지의 우측 상단 모서리에서 **자격 증명 풀 관리(Manage Identity Pools)**를 클릭합니다. **연동 자격 증명** 페이지가 나타납니다.

1. 아래로 스크롤하고 **푸시 동기화**를 클릭하여 확장합니다.

1. **서비스 역할** 드롭다운 메뉴에서 SNS 알림을 전송할 권한을 Cognito에 부여하는 IAM 역할을 선택합니다. [AWS IAM 콘솔](https://console.aws.amazon.com/iam/home)에서 [**역할 생성(Create role)**]을 클릭하여 자격 증명 풀과 연결된 역할을 생성하거나 수정합니다.

1. 플랫폼 애플리케이션을 선택한 다음 **변경 사항 저장**을 클릭합니다.

1. 애플리케이션에 SNS 액세스 권한 부여

 AWS Identity and Access Management 콘솔에서 전체 Amazon SNS 액세스 권한을 갖도록 IAM 역할을 구성하거나 전체 Amazon SNS 액세스 권한이 있는 새 역할을 생성합니다. 다음 역할 트러스트 정책 예제는 Amazon Cognito Sync에 IAM 역할을 수임할 수 있는 제한적인 권한을 부여합니다. Amazon Cognito Sync는 `aws:SourceArn` 조건의 자격 증명 풀과 `aws:SourceAccount` 조건의 계정을 둘 다 대신하는 경우에만 역할을 수임할 수 있습니다.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "cognito-sync.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceAccount": "123456789012"
                },
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cognito-identity:us-east-1:123456789012:identitypool/us-east-1:177a950c-2c08-43f0-9983-28727EXAMPLE"
                }
            }
        }
    ]
}
```

------

IAM 역할에 대한 자세한 내용은 [역할(위임 및 연동)](https://docs.aws.amazon.com/IAM/latest/UserGuide/WorkingWithRoles.html)을 참조하세요.

## 앱에서 푸시 동기화 사용: Android
<a name="push-sync-1.android"></a>

애플리케이션에서는 Google Play 서비스를 가져와야 합니다. [Android SDK Manager](http://developer.android.com/tools/help/sdk-manager.html)를 통해 최신 버전의 Google Play SDK를 다운로드할 수 있습니다. [Android 구현](https://developers.google.com/instance-id/guides/android-implementation)의 Android 설명서에 따라 앱을 등록하고 GCM으로부터 등록 ID를 받습니다. 등록 ID가 있는 경우 아래 조각에 표시된 대로 Amazon Cognito를 사용하여 디바이스를 등록해야 합니다.

```
String registrationId = "MY_GCM_REGISTRATION_ID";
try {
    client.registerDevice("GCM", registrationId);
} catch (RegistrationFailedException rfe) {
    Log.e(TAG, "Failed to register device for silent sync", rfe);
} catch (AmazonClientException ace) {
    Log.e(TAG, "An unknown error caused registration for silent sync to fail", ace);
}
```

이제 디바이스를 구독하여 특정 데이터 세트에서 업데이트를 받을 수 있습니다.

```
Dataset trackedDataset = client.openOrCreateDataset("myDataset");
if (client.isDeviceRegistered()) {
    try {
        trackedDataset.subscribe();
    } catch (SubscribeFailedException sfe) {
        Log.e(TAG, "Failed to subscribe to datasets", sfe);
    } catch (AmazonClientException ace) {
        Log.e(TAG, "An unknown error caused the subscription to fail", ace);
    }
}
```

데이터 세트에서 푸시 알림을 받는 것을 중지하려면 unsubscribe 메서드를 호출하면 됩니다. `CognitoSyncManager` 객체에서 모든 데이터 세트(또는 특정 하위 집합)를 구독하려면 `subscribeAll()`을 사용하세요.

```
if (client.isDeviceRegistered()) {
    try {
        client.subscribeAll();
    } catch (SubscribeFailedException sfe) {
        Log.e(TAG, "Failed to subscribe to datasets", sfe);
    } catch (AmazonClientException ace) {
        Log.e(TAG, "An unknown error caused the subscription to fail", ace);
    }
}
```

[Android BroadcastReceiver](http://developer.android.com/reference/android/content/BroadcastReceiver.html) 객체의 구현에서 수정된 데이터 세트의 최신 버전을 확인하고 앱에서 다시 동기화해야 하는지 여부를 결정할 수 있습니다.

```
@Override
public void onReceive(Context context, Intent intent) {

    PushSyncUpdate update = client.getPushSyncUpdate(intent);

    // The update has the source (cognito-sync here), identityId of the
    // user, identityPoolId in question, the non-local sync count of the
    // data set and the name of the dataset. All are accessible through
    // relevant getters.

    String source = update.getSource();
    String identityPoolId = update.getIdentityPoolId();
    String identityId = update.getIdentityId();
    String datasetName = update.getDatasetName;
    long syncCount = update.getSyncCount;

    Dataset dataset = client.openOrCreateDataset(datasetName);

    // need to access last sync count. If sync count is less or equal to
    // last sync count of the dataset, no sync is required.

    long lastSyncCount = dataset.getLastSyncCount();
    if (lastSyncCount < syncCount) {
        dataset.synchronize(new SyncCallback() {
            // ...
        });
    }

}
```

다음 키는 푸시 알림 페이로드에서 사용할 수 있습니다.
+ `source`: cognito-sync. 이 키는 알림 간 차별화 요소의 역할을 수행할 수 있습니다.
+ `identityPoolId`: 자격 증명 풀 ID입니다. 수신자의 관점에서 필수가 아닌 경우에도 확인 또는 추가 정보를 위해 이 키를 사용할 수 있습니다.
+ `identityId`: 풀 내의 자격 증명 ID입니다.
+ `datasetName`: 업데이트된 데이터 세트의 이름입니다. openOrCreateDataset 호출을 위해 이 키를 사용할 수 있습니다.
+ `syncCount`: 원격 데이터 세트에 대한 동기화 수입니다. 로컬 데이터 세트가 최신이 아니며 수신되는 동기화가 최신임을 확인하는 방법으로 이 키를 사용할 수 있습니다.

## 앱에서 푸시 동기화 사용: iOS - Objective-C
<a name="push-sync-1.ios-objc"></a>

앱에 대한 디바이스 토큰을 얻으려면 원격 알림 등록의 Apple 설명서를 따르세요. APN에서 NSData 객체로 디바이스 토큰을 받은 경우 아래에 표시된 대로 동기화 클라이언트의 `registerDevice:` 메서드를 사용하여 디바이스를 Amazon Cognito에 등록해야 합니다.

```
AWSCognito *syncClient = [AWSCognito defaultCognito];
    [[syncClient registerDevice: devToken] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to registerDevice: %@", task.error);
        } else {
            NSLog(@"Successfully registered device with id: %@", task.result);
        }
        return nil;
      }
    ];
```

디버깅 모드에서는 디바이스를 APN 샌드박스에 등록하고 릴리스 모드에서는 APN에 등록합니다. 특정 데이터 세트에서 업데이트를 받으려면 `subscribe` 메서드를 사용하세요.

```
[[[syncClient openOrCreateDataset:@"MyDataset"] subscribe] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to subscribe to dataset: %@", task.error);
        } else {
            NSLog(@"Successfully subscribed to dataset: %@", task.result);
        }
        return nil;
      }
    ];
```

데이터 세트에서 푸시 알림을 받는 것을 중지하려면 `unsubscribe` 메서드를 호출하면 됩니다.

```
[[[syncClient openOrCreateDataset:@”MyDataset”] unsubscribe] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to unsubscribe from dataset: %@", task.error);
        } else {
            NSLog(@"Successfully unsubscribed from dataset: %@", task.result);
        }
        return nil;
      }
    ];
```

`AWSCognito` 객체에서 모든 데이터 세트를 구독하려면 `subscribeAll`을 호출하세요.

```
[[syncClient subscribeAll] continueWithBlock:^id(AWSTask *task) {
        if(task.error){
            NSLog(@"Unable to subscribe to all datasets: %@", task.error);
        } else {
            NSLog(@"Successfully subscribed to all datasets: %@", task.result);
        }
        return nil;
      }
    ];
```

`subscribeAll`을 호출하기 전에 각 데이터 세트에 대해 한 번 이상 동기화하여 데이터 세트가 서버에 존재하도록 해야 합니다.

푸시 알림에 대응하려면 앱 위임에 `didReceiveRemoteNotification` 메서드를 구현해야 합니다.

```
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CognitoPushNotification" object:userInfo];
    }
```

알림 핸들러를 사용하여 알림을 게시한 경우 데이터 세트를 처리하는 애플리케이션의 다른 곳에서 알림에 대응할 수 있습니다. 다음과 같이 알림을 구독할 경우

```
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceivePushSync:)
    name: :@"CognitoPushNotification" object:nil];
```

알림에 대해 다음과 같이 작동합니다.

```
- (void)didReceivePushSync:(NSNotification*)notification
    {
        NSDictionary * data = [(NSDictionary *)[notification object] objectForKey:@"data"];
        NSString * identityId = [data objectForKey:@"identityId"];
        NSString * datasetName = [data objectForKey:@"datasetName"];
        if([self.dataset.name isEqualToString:datasetName] && [self.identityId isEqualToString:identityId]){
            [[self.dataset synchronize] continueWithBlock:^id(AWSTask *task) {
                if(!task.error){
                    NSLog(@"Successfully synced dataset");
                }
                return nil;
            }];
        }
    }
```

다음 키는 푸시 알림 페이로드에서 사용할 수 있습니다.
+ `source`: cognito-sync. 이 키는 알림 간 차별화 요소의 역할을 수행할 수 있습니다.
+ `identityPoolId`: 자격 증명 풀 ID입니다. 수신자의 관점에서 필수가 아닌 경우에도 확인 또는 추가 정보를 위해 이 키를 사용할 수 있습니다.
+ `identityId`: 풀 내의 자격 증명 ID입니다.
+ `datasetName`: 업데이트된 데이터 세트의 이름입니다. `openOrCreateDataset` 호출을 위해 이 키를 사용할 수 있습니다.
+ `syncCount`: 원격 데이터 세트에 대한 동기화 수입니다. 로컬 데이터 세트가 최신이 아니며 수신되는 동기화가 최신임을 확인하는 방법으로 이 키를 사용할 수 있습니다.

## 앱에서 푸시 동기화 사용: iOS - Swift
<a name="push-sync-1.ios-swift"></a>

앱에 대한 디바이스 토큰을 얻으려면 원격 알림 등록의 Apple 설명서를 따르세요. APN에서 NSData 객체로 디바이스 토큰을 받은 경우 아래에 표시된 대로 동기화 클라이언트의 registerDevice: 메서드를 사용하여 디바이스를 Amazon Cognito에 등록해야 합니다.

```
let syncClient = AWSCognito.default()
syncClient.registerDevice(devToken).continueWith(block: { (task: AWSTask!) -> AnyObject! in
    if (task.error != nil) {
        print("Unable to register device: " + task.error.localizedDescription)

    } else {
        print("Successfully registered device with id: \(task.result)")
    }
    return task
})
```

디버깅 모드에서는 디바이스를 APN 샌드박스에 등록하고 릴리스 모드에서는 APN에 등록합니다. 특정 데이터 세트에서 업데이트를 받으려면 `subscribe` 메서드를 사용하세요.

```
syncClient.openOrCreateDataset("MyDataset").subscribe().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to subscribe to dataset: " + task.error.localizedDescription)

  } else {
      print("Successfully subscribed to dataset: \(task.result)")
  }
  return task
})
```

데이터 세트에서 푸시 알림을 받는 것을 중지하려면 `unsubscribe` 메서드를 호출하세요.

```
syncClient.openOrCreateDataset("MyDataset").unsubscribe().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to unsubscribe to dataset: " + task.error.localizedDescription)

  } else {
      print("Successfully unsubscribed to dataset: \(task.result)")
  }
  return task
})
```

`AWSCognito` 객체에서 모든 데이터 세트를 구독하려면 `subscribeAll`을 호출하세요.

```
syncClient.openOrCreateDataset("MyDataset").subscribeAll().continueWith(block: { (task: AWSTask!) -> AnyObject! in
  if (task.error != nil) {
      print("Unable to subscribe to all datasets: " + task.error.localizedDescription)

  } else {
      print("Successfully subscribed to all datasets: \(task.result)")
  }
  return task
})
```

`subscribeAll`을 호출하기 전에 각 데이터 세트에 대해 한 번 이상 동기화하여 데이터 세트가 서버에 존재하도록 해야 합니다.

푸시 알림에 대응하려면 앱 위임에 `didReceiveRemoteNotification` 메서드를 구현해야 합니다.

```
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
  fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        NSNotificationCenter.defaultCenter().postNotificationName("CognitoPushNotification", object: userInfo)
})
```

알림 핸들러를 사용하여 알림을 게시한 경우 데이터 세트를 처리하는 애플리케이션의 다른 곳에서 알림에 대응할 수 있습니다. 다음과 같이 알림을 구독할 경우

```
NSNotificationCenter.defaultCenter().addObserver(observer:self,
   selector:"didReceivePushSync:",
   name:"CognitoPushNotification",
   object:nil)
```

알림에 대해 다음과 같이 작동합니다.

```
func didReceivePushSync(notification: NSNotification) {
    if let data = (notification.object as! [String: AnyObject])["data"] as? [String: AnyObject] {
        let identityId = data["identityId"] as! String
        let datasetName = data["datasetName"] as! String

        if self.dataset.name == datasetName && self.identityId == identityId {
          dataset.synchronize().continueWithBlock {(task) -> AnyObject! in
              if task.error == nil {
                print("Successfully synced dataset")
              }
              return nil
          }
        }
    }
}
```

다음 키는 푸시 알림 페이로드에서 사용할 수 있습니다.
+ `source`: cognito-sync. 이 키는 알림 간 차별화 요소의 역할을 수행할 수 있습니다.
+ `identityPoolId`: 자격 증명 풀 ID입니다. 수신자의 관점에서 필수가 아닌 경우에도 확인 또는 추가 정보를 위해 이 키를 사용할 수 있습니다.
+ `identityId`: 풀 내의 자격 증명 ID입니다.
+ `datasetName`: 업데이트된 데이터 세트의 이름입니다. `openOrCreateDataset` 호출을 위해 이 키를 사용할 수 있습니다.
+ `syncCount`: 원격 데이터 세트에 대한 동기화 수입니다. 로컬 데이터 세트가 최신이 아니며 수신되는 동기화가 최신임을 확인하는 방법으로 이 키를 사용할 수 있습니다.