

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

# Amazon QLDB의 저널 콘텐츠
<a name="journal-contents"></a>

**중요**  
지원 종료 공지: 기존 고객은 07/31/2025에 지원이 종료될 때까지 Amazon QLDB를 사용할 수 있습니다. 자세한 내용은 [Amazon QLDB 원장을 Amazon Aurora PostgreSQL로 마이그레이션](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)을 참조하세요.

Amazon QLDB에서 *저널*은 데이터의 모든 변경 사항에 대한 완전하고 검증 가능한 기록을 저장하는 변경 불가능한 트랜잭션 로그입니다. 저널은 추가만 가능하며, 커밋된 데이터 및 기타 시스템 메타데이터를 포함하는 순서화된 해시 체인 *블록* 세트로 구성됩니다. QLDB는 트랜잭션의 저널에 체인 블록 하나를 기록합니다.

이 섹션에서는 샘플 데이터가 포함된 저널 블록의 예를 제공하고 블록의 내용을 설명합니다.

**Topics**
+ [블록 예제](#journal.block-example)
+ [블록 콘텐츠](#journal.block-contents)
+ [수정된 개정](#journal.redacted-revisions)
+ [샘플 애플리케이션](#journal.sample)
+ [다음 사항도 참조하세요.](#journal.see-also)

## 블록 예제
<a name="journal.block-example"></a>

저널 블록에는 트랜잭션에서 커밋된 문서 개정 및 이를 커밋한 [PartiQL](ql-reference.md) 문을 나타내는 항목과 함께 트랜잭션 메타데이터가 들어 있습니다.

다음은 샘플 데이터가 있는 블록의 예제입니다.

**참고**  
이 블록 예제는 정보 제공 목적으로만 제공됩니다. 표시된 해시는 실제 계산된 해시 값이 아닙니다.

```
{
  blockAddress:{
    strandId:"4o5UuzWSW5PIoOGm5jPA6J",
    sequenceNo:25
  },
  transactionId:"3gtB8Q8dfIMA8lQ5pzHAMo",
  blockTimestamp:2022-06-08T18:46:46.512Z,
  blockHash:{{QS5lJt8vRxT30L9OGL5oU1pxFTe+UlEwakYBCrvGQ4A=}},
  entriesHash:{{buYYc5kV4rrRtJAsrIQnfnhgkzfQ8BKjI0C2vFnYQEw=}},
  previousBlockHash:{{I1UKRIWUgkM1X6042kcoZ/eN1rn0uxhDTc08zw9kZ5I=}},
  entriesHashList:[
    {{BUCXP6oYgmug2AfPZcAZup2lKolJNTbTuV5RA1VaFpo=}},
    {{cTIRkjuULzp/4KaUEsb/S7+TG8FvpFiZHT4tEJGcANc=}},
    {{3aktJSMyJ3C5StZv4WIJLu/w3D8mGtduZvP0ldKUaUM=}},
    {{GPKIJ1+o8mMZmPj/35ZQXoca2z64MVYMCwqs/g080IM=}}
  ],
  transactionInfo:{
    statements:[
      {
        statement:"INSERT INTO VehicleRegistration VALUE ?",
        startTime:2022-06-08T18:46:46.063Z,
        statementDigest:{{KY2nL6UGUPs5lXCLVXcUaBxcEIop0Jvk4MEjcFVBfwI=}}
      },
      {
        statement:"SELECT p_id FROM Person p BY p_id WHERE p.FirstName = ? and p.LastName = ?",
        startTime:2022-06-08T18:46:46.173Z,
        statementDigest:{{QS2nfB8XBf2ozlDx0nvtsliOYDSmNHMYC3IRH4Uh690=}}
      },
      {
        statement:"UPDATE VehicleRegistration r SET r.Owners.PrimaryOwner.PersonId = ? WHERE r.VIN = ?",
        startTime:2022-06-08T18:46:46.278Z,
        statementDigest:{{nGtIA9Qh0/dwIplOR8J5CTeqyUVtNUQgXfltDUo2Aq4=}}
      },
      {
        statement:"DELETE FROM DriversLicense l WHERE l.LicenseNumber = ?",
        startTime:2022-06-08T18:46:46.385Z,
        statementDigest:{{ka783dcEP58Q9AVQ1m9NOJd3JAmEvXLjzl0OjN1BojQ=}}
      }
    ],
    documents:{
      HwVFkn8IMRa0xjze5xcgga:{
        tableName:"VehicleRegistration",
        tableId:"HQZ6cgIMUi204Lq1tT4oaJ",
        statements:[0,2]
      },
      IiPTRxLGJZa342zHFCFT15:{
        tableName:"DriversLicense",
        tableId:"BvtXEB1JxZg0lJlBAtbtSV",
        statements:[3]
      }
    }
  },
  revisions:[
    {
      hash:{{FR1IWcWew0yw1TnRklo2YMF/qtwb7ohsu5FD8A4DSVg=}}
    },
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      hash:{{6TTHbcfIVdWoFC/j90BOZi0JdHzhjSXo1tW+uHd6Dj4=}},
      data:{
        VIN:"1N4AL11D75C109151",
        LicensePlateNumber:"LEWISR261LL",
        State:"WA",
        City:"Seattle",
        PendingPenaltyTicketAmount:90.25,
        ValidFromDate:2017-08-21,
        ValidToDate:2020-05-11,
        Owners:{
          PrimaryOwner:{
            PersonId:"3Ax20JIix5J2ulu2rCMvo2"
          },
          SecondaryOwners:[]
        }
      },
      metadata:{
        id:"HwVFkn8IMRa0xjze5xcgga",
        version:0,
        txTime:2022-06-08T18:46:46.492Z,
        txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
      }
    },
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      hash:{{ZVF/f1uSqd5DIMqzI04CCHaCGFK/J0Jf5AFzSEk0l90=}},
      metadata:{
        id:"IiPTRxLGJZa342zHFCFT15",
        version:1,
        txTime:2022-06-08T18:46:46.492Z,
        txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
      }
    }
  ]
}
```

`revisions` 필드에서 일부 개정 객체에는 `hash` 값만 포함되고 기타 속성은 포함되지 않을 수 있습니다. 이는 사용자 데이터를 포함하지 않는 내부 전용 시스템 수정본입니다. 이러한 개정판의 해시는 저널의 전체 해시 체인의 일부이며, 이는 암호화 검증에 필요합니다.

## 블록 콘텐츠
<a name="journal.block-contents"></a>

저널 블록에는 다음과 같은 필드가 있습니다.

**`blockAddress`**  
저널에서의 블록 위치입니다. 주소는 `strandId` 및 `sequenceNo`라는 두 개의 필드로 구성된 [Amazon Ion](ion.md) 구조입니다.  
예: `{strandId:"BlFTjlSXze9BIh1KOszcE3",sequenceNo:14}`

**`transactionId`**  
블록을 커밋한 트랜잭션의 고유 ID입니다.

**`blockTimestamp`**  
블록이 저널에 커밋된 시점의 타임스탬프입니다.

**`blockHash`**  
블록을 고유하게 나타내는 256비트 해시 값입니다. 이것은 `entriesHash`와 `previousBlockHash`를 연결한 해시입니다.

**`entriesHash`**  
내부 전용 시스템 항목을 포함하여 블록 내의 모든 항목을 나타내는 해시입니다. 이는 리프 노드가 `entriesHashList`의 모든 해시로 구성된 [Merkle 트리](verification.md#verification.how-it-works.merkle-tree)의 루트 해시입니다.

**`previousBlockHash`**  
저널에 있는 이전 체인 블록의 해시입니다.

**`entriesHashList`**  
블록 내 각 항목을 나타내는 해시 목록입니다. 이 목록에는 다음 항목 해시가 포함될 수 있습니다.  
+ `transactionInfo`를 나타내는 Ion 해시입니다. 이 값은 전체 `transactionInfo` 구조의 Ion 해시를 가져와 계산됩니다.
+ 리프 노드가 `revisions`의 모든 해시로 구성된 Merkle 트리의 루트 해시입니다.
+ `redactionInfo`를 나타내는 Ion 해시입니다. 이 해시는 수정 트랜잭션으로 커밋된 블록에만 존재합니다. 이 값은 전체 `redactionInfo` 구조의 Ion 해시를 가져와 계산됩니다.
+ 내부 전용 시스템 메타데이터를 나타내는 해시입니다. 이러한 해시는 모든 블록에 존재하지 않을 수 있습니다.

**`transactionInfo`**  
블록을 커밋한 트랜잭션의 문에 대한 정보가 포함된 Amazon Ion 구조입니다. 이 구조에는 다음 필드가 있습니다.  
+ `statements` - PartiQL 문 목록 및 실행 시작 시점의 `startTime`입니다. 각 명령문에는 `transactionInfo` 구조의 해시를 계산하는 데 필요한 `statementDigest` 해시가 있습니다.
+ `documents` - 명령문에 의해 업데이트된 문서 ID입니다. 각 문서에는 해당 문서가 속한 `tableName` 및 `tableId`와 이를 업데이트한 각 문의 인덱스가 포함됩니다.

**`revisions`**  
블록에서 커밋된 문서 개정 목록입니다. 각 개정 구조에는 개정의 [커밋된 보기](working.metadata.md)에 있는 모든 필드가 포함됩니다.  
여기에는 저널의 전체 해시 체인의 일부인 내부 전용 시스템 개정을 나타내는 해시도 포함될 수 있습니다.

## 수정된 개정
<a name="journal.redacted-revisions"></a>

Amazon QLDB에서 `DELETE` 문은 문서를 삭제된 것으로 표시하는 새 개정본을 생성하여 논리적으로만 문서를 삭제합니다. QLDB는 테이블 기록에서 비활성 문서 개정을 영구적으로 삭제할 수 있는 *데이터 수정* 작업도 지원합니다.

수정 작업은 지정된 수정 버전의 사용자 데이터만 삭제하고 저널 시퀀스와 문서 메타데이터는 변경되지 않습니다. 이렇게 하면 원장의 전체 데이터 무결성이 유지됩니다. 수정 작업에 대한 자세한 내용과 예제는 [문서 개정본 수정하기](working.redaction.md)을 참조하세요.

### 수정된 개정 예제
<a name="journal.redacted-revisions.example"></a>

이전 [블록 예제](#journal.block-example)를 생각해 보세요. 이 블록에서 문서 ID가 `HwVFkn8IMRa0xjze5xcgga`이고 버전 번호가 `0`인 개정을 수정한다고 가정해 보겠습니다.

수정이 완료되면 개정의 사용자 데이터(`data` 구조로 표시됨)가 새 `dataHash` 필드로 교체됩니다. 이 필드의 값은 제거된 `data` 구조의 Ion 해시입니다. 따라서 원장은 전반적인 데이터 무결성을 유지하고 기존 검증 API 작업을 통해 암호화 방식으로 검증 가능한 상태를 유지합니다.

다음 개정 예제는 새 `dataHash` 필드가 *빨간색 기울임꼴*로 강조 표시된 이 수정 결과를 보여줍니다.

**참고**  
이 개정 예제는 정보 제공 목적으로만 제공됩니다. 표시된 해시는 실제 계산된 해시 값이 아닙니다.

```
...
{
  blockAddress:{
    strandId:"4o5UuzWSW5PIoOGm5jPA6J",
    sequenceNo:25
  },
  hash:{{6TTHbcfIVdWoFC/j90BOZi0JdHzhjSXo1tW+uHd6Dj4=}},
  dataHash:{{s83jd7sfhsdfhksj7hskjdfjfpIPP/DP2hvionas2d4=}},
  metadata:{
    id:"HwVFkn8IMRa0xjze5xcgga",
    version:0,
    txTime:2022-06-08T18:46:46.492Z,
    txId:"3gtB8Q8dfIMA8lQ5pzHAMo"
  }
}
...
```

또한 QLDB는 완료된 수정 요청에 대해 저널에 새 블록을 추가합니다. 이 블록에는 다음 예제와 같이 트랜잭션에서 수정된 개정 목록이 포함된 추가 `redactionInfo` 항목이 포함되어 있습니다.

```
...
redactionInfo:{
  revisions:[
    {
      blockAddress:{
        strandId:"4o5UuzWSW5PIoOGm5jPA6J",
        sequenceNo:25
      },
      tableId:"HQZ6cgIMUi204Lq1tT4oaJ",
      documentId:"HwVFkn8IMRa0xjze5xcgga",
      version:0
    }
  ]
}
...
```

## 샘플 애플리케이션
<a name="journal.sample"></a>

내보낸 데이터를 사용하여 저널의 해시 체인을 검증하는 Java 코드 예제는 GitHub 리포지토리 [aws-samples/amazon-qldb-dmv-sample-java](https://github.com/aws-samples/amazon-qldb-dmv-sample-java)를 참조하세요. 이 샘플 애플리케이션에는 다음과 같은 클래스 파일이 포함되어 있습니다.
+ [ValidateQldbHashChain.java](https://github.com/aws-samples/amazon-qldb-dmv-sample-java/blob/master/src/main/java/software/amazon/qldb/tutorial/ValidateQldbHashChain.java) - 원장에서 저널 블록을 내보내고 내보낸 데이터를 사용하여 블록 간 해시 체인을 검증하는 자습서 코드를 포함합니다.
+ [JournalBlock.java](https://github.com/aws-samples/amazon-qldb-dmv-sample-java/blob/master/src/main/java/software/amazon/qldb/tutorial/qldb/JournalBlock.java) - 블록 내의 각 개별 해시 구성 요소를 계산하는 방법을 보여주는 `verifyBlockHash()`라는 메서드가 들어 있습니다. 이 메서드는 `ValidateQldbHashChain.java`의 자습서 코드에서 호출됩니다.

이 전체 샘플 애플리케이션을 다운로드하고 설치하는 방법에 대한 지침은 [Amazon QLDB Java 샘플 애플리케이션 설치](sample-app.java.md)을 참조하세요. 자습서 코드를 실행하기 전에 [Java 자습서](getting-started.java.tutorial.md)의 1\$13단계에 따라 샘플 원장을 설정하고 샘플 데이터를 로드해야 합니다.

## 다음 사항도 참조하세요.
<a name="journal.see-also"></a>

QLDB의 원장에 대한 자세한 내용은 다음 주제를 참조하세요.
+ [Amazon QLDB에서 저널 데이터 내보내기](export-journal.md) - 저널 데이터를 Amazon Simple Storage Service(S3)로 내보내는 방법을 설명합니다.
+ [Amazon QLDB에서 저널 데이터 스트리밍](streams.md) - 저널 데이터를 Amazon Kinesis Data Streams에 스트리밍하는 방법을 알아봅니다.
+ [Amazon QLDB에서의 데이터 확인](verification.md) - 저널 데이터의 암호화 검증에 대해 알아봅니다.