

# DynamoDB에서 업데이트 표현식 사용
<a name="Expressions.UpdateExpressions"></a>

`UpdateItem` 작업은 기존 항목을 업데이트하거나 기존 항목이 없는 경우 새 항목을 테이블에 추가합니다. 업데이트할 항목의 키를 제공해야 합니다. 또한 수정할 속성과 그러한 속성에 할당할 값을 지정하는 업데이트 표현식도 제공해야 합니다.

*업데이트 표현식*은 `UpdateItem`이 항목의 속성을 수정하는 방법을 지정합니다(예: 스칼라 값 설정 또는 목록이나 맵에서 요소 제거).

다음은 업데이트 표현식에 대한 구문을 요약한 것입니다.

```
update-expression ::=
    [ SET action [, action] ... ]
    [ REMOVE action [, action] ...]
    [ ADD action [, action] ... ]
    [ DELETE action [, action] ...]
```

업데이트 표현식은 하나 이상의 절로 구성됩니다. 각 절은 `SET`, `REMOVE`, `ADD` 또는 `DELETE` 키워드로 시작됩니다. 이러한 절은 업데이트 표현식에 어떤 순서로든 포함할 수 있습니다. 하지만 각 작업 키워드는 한 번만 표시할 수 있습니다.

각 절 내에는 하나 이상의 작업이 쉼표로 구분되어 있습니다. 각 작업은 데이터 수정을 나타냅니다.

이 섹션의 예제는 [DynamoDB에서 프로젝션 표현식 사용](Expressions.ProjectionExpressions.md)의 `ProductCatalog` 항목을 기반으로 합니다.

아래 주제에서는 `SET` 작업의 다양한 사용 사례를 다룹니다.

**Topics**
+ [SET - 항목 속성 수정 또는 추가](#Expressions.UpdateExpressions.SET)
+ [REMOVE - 항목에서 속성 삭제](#Expressions.UpdateExpressions.REMOVE)
+ [ADD - 숫자 및 세트 업데이트](#Expressions.UpdateExpressions.ADD)
+ [DELETE - 세트에서 요소 제거](#Expressions.UpdateExpressions.DELETE)
+ [여러 업데이트 표현식 사용](#Expressions.UpdateExpressions.Multiple)

## SET - 항목 속성 수정 또는 추가
<a name="Expressions.UpdateExpressions.SET"></a>

업데이트 표현식에서 `SET` 작업을 사용하여 하나 이상의 속성을 항목에 추가합니다. 이러한 속성 중 하나가 이미 존재하는 경우에는 새 값이 해당 값을 덮어씁니다. 기존 속성의 덮어쓰기를 방지하려는 경우 `SET` 함수와 함께 `if_not_exists`를 사용할 수 있습니다. `if_not_exists` 함수는 `SET` 작업에 고유하며 업데이트 표현식에서만 사용할 수 있습니다.

`SET`을 사용하여 목록 요소를 업데이트하는 경우 해당 요소의 내용이 사용자가 지정한 새 데이터로 바뀝니다. 요소가 아직 없으면 `SET`은 목록의 끝에 새 요소를 추가합니다.

단일 `SET` 작업에서 여러 요소를 추가하는 경우 요소가 요소 번호에 따라 순서대로 정렬됩니다.

`SET`을 사용하여 `Number` 형식의 속성에서 더하거나 뺄 수도 있습니다. 여러 `SET` 작업을 수행하려면 각 작업을 쉼표로 구분합니다.

다음 구문 요약에서:
+ *path* 요소는 항목의 문서 경로입니다.
+ **피연산자** 요소는 항목의 문서 경로 또는 함수일 수 있습니다.

```
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function

function ::=
    if_not_exists (path, value)
```

항목의 지정된 경로에 속성이 포함되지 않으면 `if_not_exists`가 `value`로 평가됩니다. 그렇지 않으면 `path`로 평가됩니다.

다음 `PutItem` 작업은 예제에서 참조할 샘플 항목을 생성합니다.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

`--item`의 인수는 `item.json` 파일에 저장됩니다. 간소화를 위해 항목 속성 몇 개만 사용됩니다.

```
{
    "Id": {"N": "789"},
    "ProductCategory": {"S": "Home Improvement"},
    "Price": {"N": "52"},
    "InStock": {"BOOL": true},
    "Brand": {"S": "Acme"}
}
```

**Topics**
+ [속성 수정](#Expressions.UpdateExpressions.SET.ModifyingAttributes)
+ [목록 및 맵 추가](#Expressions.UpdateExpressions.SET.AddingListsAndMaps)
+ [목록에 요소 추가](#Expressions.UpdateExpressions.SET.AddingListElements)
+ [중첩 맵 속성 추가](#Expressions.UpdateExpressions.SET.AddingNestedMapAttributes)
+ [수치 속성 증가 및 감소](#Expressions.UpdateExpressions.SET.IncrementAndDecrement)
+ [목록에 요소 추가](#Expressions.UpdateExpressions.SET.UpdatingListElements)
+ [기존 속성의 덮어쓰기 방지](#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites)

### 속성 수정
<a name="Expressions.UpdateExpressions.SET.ModifyingAttributes"></a>

**Example**  
`ProductCategory` 및 `Price` 속성을 업데이트합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET ProductCategory = :c, Price = :p" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":c": { "S": "Hardware" },
    ":p": { "N": "60" }
}
```

**참고**  
`UpdateItem` 작업에서 `--return-values ALL_NEW`를 실행하면 DynamoDB에서 업데이트 후 나타나는 항목을 반환합니다.

### 목록 및 맵 추가
<a name="Expressions.UpdateExpressions.SET.AddingListsAndMaps"></a>

**Example**  
새 목록과 새 맵을 추가합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":ri": {
        "L": [
            { "S": "Hammer" }
        ]
    },
    ":pr": {
        "M": {
            "FiveStar": {
                "L": [
                    { "S": "Best product ever!" }
                ]
            }
        }
    }
}
```

### 목록에 요소 추가
<a name="Expressions.UpdateExpressions.SET.AddingListElements"></a>

**Example**  
새로운 속성을 `RelatedItems` 목록에 추가합니다. 목록 요소는 0부터 시작되므로 [0]은 목록의 첫 번째 요소를 나타내고 [1]은 두 번째 요소를 나타냅니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :ri" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":ri": { "S": "Nails" }
}
```

**참고**  
`SET`을 사용하여 목록 요소를 업데이트하는 경우 해당 요소의 내용이 사용자가 지정한 새 데이터로 바뀝니다. 요소가 아직 없으면 `SET`은 목록의 끝에 새 요소를 추가합니다.  
단일 `SET` 작업에서 여러 요소를 추가하는 경우 요소가 요소 번호에 따라 순서대로 정렬됩니다.

### 중첩 맵 속성 추가
<a name="Expressions.UpdateExpressions.SET.AddingNestedMapAttributes"></a>

**Example**  
일부 중첩 맵 속성을 추가합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
    --expression-attribute-names file://names.json \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
`--expression-attribute-names`의 인수는 `names.json` 파일에 저장됩니다.  

```
{
    "#pr": "ProductReviews",
    "#5star": "FiveStar",
    "#3star": "ThreeStar"
}
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":r5": { "S": "Very happy with my purchase" },
    ":r3": {
        "L": [
            { "S": "Just OK - not that great" }
        ]
    }
}
```

**중요**  
상위 맵이 없는 경우 중첩 맵 속성을 업데이트할 수 없습니다. 상위 맵(`ProductReviews`)이 존재하지 않을 때 중첩 속성(예: `ProductReviews.FiveStar`)을 업데이트하려고 하면 DynamoDB는 *"The document path provided in the update expression is invalid for update"*라는 메시지와 함께 `ValidationException`을 반환합니다.  
나중에 중첩 맵 속성을 업데이트할 항목을 생성할 때는 상위 속성에 대해 빈 맵을 초기화합니다. 예제:  

```
{
    "Id": {"N": "789"},
    "ProductReviews": {"M": {}},
    "Metadata": {"M": {}}
}
```
이렇게 하면 오류 없이 `ProductReviews.FiveStar`와 같은 중첩 속성을 업데이트할 수 있습니다.

### 수치 속성 증가 및 감소
<a name="Expressions.UpdateExpressions.SET.IncrementAndDecrement"></a>

기존 수치 속성에 더하거나 뺄 수 있습니다. 이 작업을 수행하려면 `+`(더하기) 및 `-`(빼기) 연산자를 사용합니다.

**Example**  
항목의 `Price`을 줄입니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```
`Price`을 증가시키려면 업데이트 표현식에서 `+` 연산자를 사용합니다.

### 목록에 요소 추가
<a name="Expressions.UpdateExpressions.SET.UpdatingListElements"></a>

목록 끝에 요소를 추가할 수 있습니다. 이렇게 하려면 `SET` 함수와 함께 `list_append`를 사용합니다. (파일 이름은 대/소문자를 구분합니다.) `list_append` 함수는 `SET` 작업에 고유하며 업데이트 표현식에서만 사용할 수 있습니다. 구문은 다음과 같습니다.
+ `list_append (list1, list2)`

이 함수는 입력으로 두 개의 목록을 가져오고 `list2`의 모든 요소를 ` list1`에 추가합니다.

**Example**  
[목록에 요소 추가](#Expressions.UpdateExpressions.SET.AddingListElements)에서는 `RelatedItems` 목록을 생성하고 목록을 `Hammer` 및 `Nails`라는 두 개의 요소로 채웠습니다. 이제 `RelatedItems`의 끝에 두 개의 요소를 더 추가합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(#ri, :vals)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values file://values.json  \
    --return-values ALL_NEW
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":vals": {
        "L": [
            { "S": "Screwdriver" },
            {"S": "Hacksaw" }
        ]
    }
}
```
마지막으로 `RelatedItems`의 *시작*에 요소 하나를 더 추가합니다. 이렇게 하려면 `list_append` 요소의 순서를 스왑합니다. (`list_append`는 두 개의 목록을 입력으로 가져오고 두 번째 목록을 첫 번째 목록에 추가한다는 점을 기억하세요.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(:vals, #ri)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
    --return-values ALL_NEW
```
이제 결과적으로 생성되는 `RelatedItems` 속성에는 5개의 요소가 `Chisel`, `Hammer`, `Nails`, `Screwdriver`, `Hacksaw` 순서로 포함됩니다.

### 기존 속성의 덮어쓰기 방지
<a name="Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites"></a>

**Example**  
항목에 `Price` 속성이 아직 없는 경우에만 항목의 `Price`를 설정합니다. (`Price`가 이미 있는 경우 아무 동작도 발생하지 않습니다.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW
```

## REMOVE - 항목에서 속성 삭제
<a name="Expressions.UpdateExpressions.REMOVE"></a>

업데이트 표현식에서 `REMOVE` 작업을 사용하여 Amazon DynamoDB에서 하나 이상의 속성을 항목에서 제거합니다. 여러 `REMOVE` 작업을 수행하려면 각 작업을 쉼표로 구분합니다.

다음은 업데이트 식의 `REMOVE`에 대한 구문을 요약한 것입니다. 제거하려는 속성의 문서 경로가 유일한 피연산자입니다.

```
remove-action ::=
    path
```

**Example**  
항목에서 일부 속성을 제거합니다. (이 속성이 없는 경우 아무 동작도 발생하지 않습니다.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE Brand, InStock, QuantityOnHand" \
    --return-values ALL_NEW
```

### 목록에서 요소 제거
<a name="Expressions.UpdateExpressions.REMOVE.RemovingListElements"></a>

`REMOVE`를 사용하여 목록에서 개별 요소를 삭제합니다.

**Example**  
[목록에 요소 추가](#Expressions.UpdateExpressions.SET.UpdatingListElements)에서 다음 5개의 요소가 포함되도록 목록 속성(`RelatedItems`)을 수정합니다.  
+ `[0]`—`Chisel`
+ `[1]`—`Hammer`
+ `[2]`—`Nails`
+ `[3]`—`Screwdriver`
+ `[4]`—`Hacksaw`
다음 AWS Command Line Interface(AWS CLI) 예제에서는 목록에서 `Hammer` 및 `Nails`를 삭제합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
    --return-values ALL_NEW
```
`Hammer`와 `Nails`를 제거한 후에는 나머지 요소가 이동됩니다. 이제 목록에는 다음이 포함됩니다.  
+ `[0]`—`Chisel`
+ `[1]`—`Screwdriver`
+ `[2]`—`Hacksaw`

## ADD - 숫자 및 세트 업데이트
<a name="Expressions.UpdateExpressions.ADD"></a>

**참고**  
일반적으로 멱등성 작업을 위해 `ADD` 대신 `SET`를 사용하는 것이 좋습니다.

업데이트 표현식에서 `ADD` 작업을 사용하여 새로운 속성과 값을 항목에 추가합니다.

속성이 이미 있으면 `ADD`의 동작은 속성의 데이터 형식에 따라 달라집니다.
+ 속성이 숫자이고 추가하려는 값도 숫자이면 값이 산술적으로 기존 속성에 더해집니다. (값이 음수이면 기존 속성에서 차감됩니다.)
+ 속성이 집합이고 추가하려는 값도 집합이면 값이 기존 집합에 추가됩니다.

**참고**  
`ADD` 작업은 숫자 및 집합 데이터 형식만 지원합니다.

여러 `ADD` 작업을 수행하려면 각 작업을 쉼표로 구분합니다.

다음 구문 요약에서:
+ *path* 요소는 속성에 대한 문서 경로입니다. 속성은 `Number` 또는 집합 데이터 형식이어야 합니다.
+ *값* 요소는 속성에 더할 숫자(`Number` 데이터 형식의 경우) 또는 속성에 추가할 세트(집합 형식의 경우)입니다.

```
add-action ::=
    path value
```

아래 주제에서는 `ADD` 작업의 다양한 사용 사례를 다룹니다.

**Topics**
+ [숫자 추가](#Expressions.UpdateExpressions.ADD.Number)
+ [세트에 요소 추가](#Expressions.UpdateExpressions.ADD.Set)

### 숫자 추가
<a name="Expressions.UpdateExpressions.ADD.Number"></a>

`QuantityOnHand` 속성이 존재하지 않는다고 가정합니다. 다음 AWS CLI 예제에서는 `QuantityOnHand`을 5로 설정합니다.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW
```

이제 `QuantityOnHand`가 존재하므로 예제를 다시 실행하여 `QuantityOnHand`를 매번 5씩 증가시킬 수 있습니다.

### 세트에 요소 추가
<a name="Expressions.UpdateExpressions.ADD.Set"></a>

`Color` 속성이 존재하지 않는다고 가정합니다. 다음 AWS CLI 예제는 두 요소가 있는 문자열 집합으로 `Color`을 설정합니다.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
    --return-values ALL_NEW
```

이제 `Color`가 존재하므로 여기에 요소를 더 추가할 수 있습니다.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
    --return-values ALL_NEW
```

## DELETE - 세트에서 요소 제거
<a name="Expressions.UpdateExpressions.DELETE"></a>

**중요**  
`DELETE` 작업은 `Set` 데이터 형식만 지원합니다.

업데이트 표현식에서 `DELETE` 작업을 사용하여 집합에서 하나 이상의 요소를 제거합니다. 여러 `DELETE` 작업을 수행하려면 각 작업을 쉼표로 구분합니다.

다음 구문 요약에서:
+ *path* 요소는 속성에 대한 문서 경로입니다. 속성은 설정된 Set 데이터 형식이어야 합니다.
+ *하위 집합*은 *경로*에서 삭제하려는 하나 이상의 요소입니다. *하위 집합*을 집합 형식으로 지정해야 합니다.

```
delete-action ::=
    path subset
```

**Example**  
[세트에 요소 추가](#Expressions.UpdateExpressions.ADD.Set)에서 `Color` 문자열 집합을 생성합니다. 이 예제에서는 해당 집합에서 일부 요소를 제거합니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "DELETE Color :p" \
    --expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
    --return-values ALL_NEW
```

## 여러 업데이트 표현식 사용
<a name="Expressions.UpdateExpressions.Multiple"></a>

단일 업데이트 표현식에서 여러 작업을 사용할 수 있습니다. 모든 속성 참조는 작업이 적용되기 전에 항목의 상태에 대해 확인됩니다.

**Example**  
`{"id": "1", "a": 1, "b": 2, "c": 3}` 항목이 주어지면 다음 표현식은 `a`를 제거하고 `b` 및 `c`의 값을 이동합니다.  

```
aws dynamodb update-item \
    --table-name test \
    --key '{"id":{"S":"1"}}' \
    --update-expression "REMOVE a SET b = a, c = b" \
    --return-values ALL_NEW
```
결과는 `{"id": "1", "b": 1, "c": 2}`입니다. `a`가 제거되고 `b`가 동일한 표현식으로 재할당되더라도 두 참조 모두 원래 값으로 확인됩니다.

**Example**  
속성 값을 수정하고 다른 속성을 완전히 제거하려면 단일 명령문에서 SET 및 REMOVE 작업을 사용할 수 있습니다. 이 작업을 수행하면 `Price` 값이 15로 감소되고 항목에서 `InStock` 속성이 제거됩니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p REMOVE InStock" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```

**Example**  
목록에 추가하고 다른 속성의 값도 변경하려면 단일 명령문에 두 개의 SET 작업을 사용할 수 있습니다. 이 작업을 수행하면 `RelatedItems` 목록 속성에 'Nails'가 추가되고 `Price` 값도 21로 설정됩니다.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :newValue, Price = :newPrice" \
    --expression-attribute-values '{":newValue": {"S":"Nails"}, ":newPrice": {"N":"21"}}'  \
    --return-values ALL_NEW
```