

# DynamoDB에서 디바이스 상태 업데이트 모니터링
<a name="data-modeling-device-status"></a>

이 사용 사례에서는 DynamoDB를 사용하여 DynamoDB에서 디바이스 상태 업데이트(또는 디바이스 상태 변경)를 모니터링하는 방법을 설명합니다.

## 사용 사례
<a name="data-modeling-schema-device-status-use-case"></a>

IoT 사용 사례(예: 스마트 팩토리)에서는 운영자가 많은 디바이스를 모니터링해야 하며 운영자는 주기적으로 상태 또는 로그를 모니터링 시스템에 전송합니다. 디바이스에 문제가 발생할 경우 디바이스의 상태가 *정상*에서 *경고*로 바뀝니다. 디바이스는 비정상적인 동작의 심각도 및 유형에 따라 다양한 로그 수준 또는 상태를 갖게 됩니다. 시스템에서는 운영자를 배정하여 디바이스를 점검하도록 하며, 필요한 경우 운영자가 감독자에게 문제를 에스컬레이션할 수 있습니다.

이 시스템의 몇 가지 일반적인 액세스 패턴은 다음과 같습니다.
+ 디바이스에 대한 로그 항목 생성
+ 특정 디바이스 상태에 대한 모든 로그 가져오기(최근 로그 먼저 표시)
+ 두 날짜 사이의 지정된 운영자에 대한 모든 로그 가져오기
+ 지정된 감독자에게 에스컬레이션된 모든 로그 가져오기
+ 지정된 감독자에게 에스컬레이션되고 특정 디바이스 상태가 포함된 모든 로그 가져오기
+ 특정 날짜에 지정된 감독자에게 에스컬레이션되고 특정 디바이스 상태가 포함된 모든 로그 가져오기

## 엔터티 관계 다이어그램
<a name="data-modeling-schema-device-status-erd"></a>

다음은 디바이스 상태 업데이트를 모니터링하는 데 사용할 엔터티 관계 다이어그램(ERD)입니다.

![\[디바이스 상태 업데이트의 ERD. 여기에는 엔터티(디바이스 및 운영자)가 표시됩니다.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-1-ERD.jpg)


## 액세스 패턴
<a name="data-modeling-schema-device-status-access-patterns"></a>

디바이스 상태 업데이트를 모니터링하는 데 고려할 액세스 패턴은 다음과 같습니다.

1. `createLogEntryForSpecificDevice`

1. `getLogsForSpecificDevice`

1. `getWarningLogsForSpecificDevice`

1. `getLogsForOperatorBetweenTwoDates`

1. `getEscalatedLogsForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisorForDate`

## 스키마 설계 진화
<a name="data-modeling-schema-device-status-design-evolution"></a>

**1단계: 액세스 패턴 1(`createLogEntryForSpecificDevice`) 및 2(`getLogsForSpecificDevice`) 처리**

디바이스 추적 시스템의 규모 조정 단위는 개별 디바이스입니다. 이 시스템에서는 `deviceID`가 디바이스를 고유하게 식별합니다. 따라서 `deviceID`는 파티션 키로 적합한 후보입니다. 각 디바이스는 주기적으로(예: 5분마다) 추적 시스템에 정보를 전송합니다. 이렇게 정렬하면 날짜가 논리적인 정렬 기준이 되므로 정렬 키도 됩니다. 이 경우 샘플 데이터는 다음과 같습니다.

![\[여러 디바이스의 상태를 저장하는 테이블. DeviceID는 프라이머리 키이고 상태 업데이트 날짜는 정렬 키입니다.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-2-Step1.png)


특정 디바이스에 대한 로그 항목을 가져오려는 경우 파티션 키 `DeviceID="d#12345"`를 사용하여 [쿼리](Query.md) 작업을 수행할 수 있습니다.

**2단계: 액세스 패턴 3(`getWarningLogsForSpecificDevice`) 처리**

`State`는 키가 아닌 속성이므로 현재 스키마로 액세스 패턴 3을 처리하려면 [필터 표현식](Query.FilterExpression.md)이 필요합니다. DynamoDB에서는 키 조건 표현식을 사용하여 데이터를 읽은 후 필터 표현식이 적용됩니다. 예를 들어 `d#12345`에 대한 경고 로그를 가져오는 경우, 파티션 키 `DeviceID="d#12345"`를 사용한 쿼리 작업은 위 테이블에서 4개 항목을 읽은 다음 *경고* 상태가 없는 1개 항목을 필터링합니다. 이 접근 방식은 규모가 커지면 효율적이지 않습니다. 제외된 항목의 비율이 낮거나 쿼리가 자주 수행되지 않는 경우 필터 표현식은 쿼리되는 항목을 제외하는 좋은 방법이 될 수 있습니다. 하지만 테이블에서 많은 항목이 검색되고 대부분의 항목이 필터링되는 경우에는 테이블 설계를 계속 발전시켜 더 효율적으로 실행되도록 할 수 있습니다.

[복합 정렬 키](data-modeling-blocks.md#data-modeling-blocks-composite)를 사용하여 이 액세스 패턴을 처리하는 방법을 변경해 보겠습니다. 정렬 키가 `State#Date`로 변경된 [DeviceStateLog\$13.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_3.json)에서 샘플 데이터를 가져올 수 있습니다. 이 정렬 키는 `State`, `#` 및 `Date` 속성으로 구성됩니다. 이 예에서는 `#`이 구분 기호로 사용됩니다. 데이터는 이제 다음과 같습니다.

![\[복합 정렬 키 State#Date를 사용하여 가져온 디바이스 d#12345 상태 업데이트 데이터.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-3-Step2.png)


디바이스에 대한 경고 로그만 가져오려는 경우 이 스키마를 사용하면 쿼리의 대상이 더욱 명확해집니다. 쿼리의 키 조건은 파티션 키 `DeviceID="d#12345"` 및 정렬 키 `State#Date begins_with “WARNING”`을 사용합니다. 이 쿼리는 *경고* 상태의 관련 항목 3개만 읽습니다.

**3단계: 액세스 패턴 4(`getLogsForOperatorBetweenTwoDates`) 처리**

예제 데이터와 함께 `Operator` 속성이 `DeviceStateLog` 테이블에 추가된 [DeviceStateLog\$14.jsonD](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_4.json)를 가져올 수 있습니다.

![\[특정 날짜 사이의 운영자 로그를 가져오기 위해 운영자 속성을 사용한 DeviceStateLog 테이블 설계.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-4-Step3.png)


`Operator`는 현재 파티션 키가 아니므로 `OperatorID`를 기반으로 이 테이블에서 직접 키-값 조회를 수행할 수 있는 방법이 없습니다. `OperatorID`에 대한 글로벌 보조 인덱스를 사용하여 새 [항목 컬렉션](WorkingWithItemCollections.md)을 생성해야 합니다. 액세스 패턴에는 날짜를 기반으로 한 조회가 필요하므로 Date는 [글로벌 보조 인덱스(GSI)](GSI.md)의 정렬 키 속성입니다 현재 GSI는 다음과 같습니다.

![\[특정 운영자의 로그를 가져오기 위해 OperatorID와 Date를 파티션 키와 정렬 키로 사용한 GSI 설계.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-5-Step3.png)


액세스 패턴 4(`getLogsForOperatorBetweenTwoDates`)의 경우 `2020-04-11T05:58:00`과 `2020-04-24T14:50:00` 사이로 파티션 키 `OperatorID=Liz` 및 정렬 키 `Date`를 사용하여 이 GSI를 쿼리할 수 있습니다.

![\[두 날짜 사이의 운영자 관련 로그를 가져오기 위해 OperatorID 및 Date를 사용한 GSI 쿼리.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-6-GSI1_1.png)


**4단계: 액세스 패턴 5(`getEscalatedLogsForSupervisor`), 6(`getEscalatedLogsWithSpecificStatusForSupervisor`), 7(`getEscalatedLogsWithSpecificStatusForSupervisorForDate`) 처리**

이러한 액세스 패턴을 처리하기 위해 [희소 인덱스](data-modeling-blocks.md#data-modeling-blocks-sparse-index)를 사용합니다.

글로벌 보조 인덱스는 기본적으로 희소 인덱스이므로 인덱스의 프라이머리 키 속성을 포함하는 기본 테이블의 항목만 실제로 인덱스에 표시됩니다. 이는 모델링되는 액세스 패턴과 관련이 없는 항목을 제외하는 또 다른 방법입니다.

예제 데이터와 함께 `EscalatedTo` 속성이 `DeviceStateLog` 테이블에 추가된 [DeviceStateLog\$16.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_6.json)을 가져올 수 있습니다. 앞서 언급했듯이 모든 로그가 감독자에게 에스컬레이션되는 것은 아닙니다.

![\[특정 감독자에게 에스컬레이션된 모든 로그를 가져오기 위해 EscalatedTo 속성을 사용한 GSI 설계.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-7-Step4.png)


이제 파티션 키가 `EscalatedTo`이고 정렬 키가 `State#Date`인 새 GSI를 생성할 수 있습니다. `EscalatedTo`와 `State#Date` 속성이 모두 있는 항목만 인덱스에 표시됩니다.

![\[EscalatedTo 및 State#Date 속성을 가진 모든 항목을 가져오기 위한 GSI 설계.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-8-Step4.png)


나머지 액세스 패턴은 다음과 같이 요약됩니다.

    액세스 패턴 5(getEscalatedLogsForSupervisor)의 경우 파티션 키 EscalatedTo="Sara"를 사용하여 에스컬레이션 GSI에 대한 쿼리를 수행할 수 있습니다.   액세스 패턴 6(getEscalatedLogsWithSpecificStatusForSupervisor)의 경우 파티션 키 EscalatedTo="Sara" 및 정렬 키 State\$1Date Begins\$1with "WARNING"을 사용하여 에스컬레이션 GSI에 대한 쿼리를 수행할 수 있습니다.   액세스 패턴 7(getEscalatedLogsWithSpecificStatusForSupervisorForDate)의 경우 파티션 키 EscalatedTo="Sara" 및 정렬 키 State\$1Date begins\$1with "WARNING4\$12020-04-27"을 사용하여 에스컬레이션 GSI에 대한 쿼리를 수행할 수 있습니다.    

모든 액세스 패턴과 스키마 설계에서 이를 처리하는 방법이 아래 표에 요약되어 있습니다.


| 액세스 패턴 | 기본 테이블/GSI/LSI | 연산 | 파티션 키 값 | 정렬 키 값 | 기타 조건/필터 | 
| --- | --- | --- | --- | --- | --- | 
| createLogEntryForSpecificDevice | 기본 테이블 | PutItem | DeviceID=deviceId | State\$1Date=state\$1date |  | 
| getLogsForSpecificDevice | 기본 테이블 | 쿼리 | DeviceID=deviceId | State\$1Date begins\$1with "state1\$1" | ScanIndexForward = False | 
| getWarningLogsForSpecificDevice | 기본 테이블 | 쿼리 | DeviceID=deviceId | State\$1Date begins\$1with "WARNING" |  | 
| getLogsForOperatorBetweenTwoDates | GSI-1 | 쿼리 | Operator=operatorName | Date between date1 and date2 |  | 
| getEscalatedLogsForSupervisor | GSI-2 | 쿼리 | EscalatedTo=supervisorName |  |  | 
| getEscalatedLogsWithSpecificStatusForSupervisor | GSI-2 | 쿼리 | EscalatedTo=supervisorName | State\$1Date begins\$1with "state1\$1" |  | 
| getEscalatedLogsWithSpecificStatusForSupervisorForDate | GSI-2 | 쿼리 | EscalatedTo=supervisorName | State\$1Date begins\$1with "state1\$1date1" |  | 

## 최종 스키마
<a name="data-modeling-schema-device-status-final-schema"></a>

다음은 최종 스키마 설계입니다. 이 스키마 설계를 JSON 파일로 다운로드하려면 GitHub의 [DynamoDB 예제](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/schema_design/SchemaExamples)를 참조하세요.

**기본 테이블**

![\[디바이스 ID, 상태, 날짜와 같은 디바이스 상태 메타데이터가 포함된 기본 테이블 설계.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-9-Table.png)


**GSI-1**

![\[GSI-1 설계. 프라이머리 키와 속성(DeviceID, State#Date, State)이 표시됩니다.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-10-GSI1.png)


**GSI-2**

![\[GSI-2 설계. 프라이머리 키와 속성(DeviceID, Operator, Date, State)이 표시됩니다.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-11-GSI2.png)


## 이 스키마 설계와 함께 NoSQL Workbench 사용
<a name="data-modeling-schema-device-status-nosql"></a>

이 최종 스키마를 DynamoDB 데이터 모델링, 데이터 시각화, 쿼리 개발 기능을 제공하는 시각적 도구인 [NoSQL Workbench](workbench.md)로 가져와서 새 프로젝트를 추가로 탐색하고 편집할 수 있습니다. 시작하려면 다음 단계를 따릅니다.

1. NoSQL Workbench 다운로드 자세한 내용은 [DynamoDB용 NoSQL Workbench 다운로드](workbench.settingup.md) 섹션을 참조하세요.

1. 위에 나열된 JSON 스키마 파일을 다운로드합니다. 이 파일은 이미 NoSQL Workbench 모델 형식으로 되어 있습니다.

1. JSON 스키마 파일을 NoSQL Workbench로 가져옵니다. 자세한 내용은 [기존 데이터 모델 가져오기](workbench.Modeler.ImportExisting.md) 섹션을 참조하세요.

1. NOSQL Workbench로 가져온 후 데이터 모델을 편집할 수 있습니다. 자세한 내용은 [기존 데이터 모델 편집](workbench.Modeler.Edit.md) 섹션을 참조하세요.