Tempo Di Valse

[PHP/AWS] S3 listObject 에서 필요한 값만 가져오기 본문

개발/Web

[PHP/AWS] S3 listObject 에서 필요한 값만 가져오기

TempoDiValse 2022. 7. 27. 18:52

listObject 나 V2 메소드를 사용하게 되면 무수히 많은 JSON 정보들과 함께 내가 사용할 값들을 가져올 수 있다. 다음의 JSON 예시는 공식 API 문서에서 가져온 내용이다.

 

AWS SDK for PHP 3.x

Client: Aws\S3\S3Client Service ID: s3 Version: 2006-03-01 This page describes the parameters and results for the operations of the Amazon Simple Storage Service (2006-03-01), and shows how to use the Aws\S3\S3Client object to call the described operations

docs.aws.amazon.com

[
    'CommonPrefixes' => [
        [
            'Prefix' => '<string>',
        ],
        // ...
    ],
    'Contents' => [
        [
            'ChecksumAlgorithm' => ['<string>', ...],
            'ETag' => '<string>',
            'Key' => '<string>',
            'LastModified' => <DateTime>,
            'Owner' => [
                'DisplayName' => '<string>',
                'ID' => '<string>',
            ],
            'Size' => <integer>,
            'StorageClass' => 'STANDARD|REDUCED_REDUNDANCY|GLACIER|STANDARD_IA|ONEZONE_IA|INTELLIGENT_TIERING|DEEP_ARCHIVE|OUTPOSTS|GLACIER_IR',
        ],
        // ...
    ],
    'ContinuationToken' => '<string>',
    'Delimiter' => '<string>',
    'EncodingType' => 'url',
    'IsTruncated' => true || false,
    'KeyCount' => <integer>,
    'MaxKeys' => <integer>,
    'Name' => '<string>',
    'NextContinuationToken' => '<string>',
    'Prefix' => '<string>',
    'StartAfter' => '<string>',
]

여기서 정작 필요한건 Contents 에 대한 내용이지만, 그 이외에 것은 정작 내가 리스트를 개발하거나 할 때 쓸모가 있는가 에 대해서는 그닥 필요하지 않는 메타데이터로 볼 수 있을 것이다. 또한, Contents 에 대한 묶음들 안에도 쓸모있는 아이들은 많이 없을 것이다.

 

그래서 JSON 데이터를 가져올 때 쉽게 데이터를 필터링하여 가져올 수 있는 방법에 대해 알아보도록 한다. 


listObject 를 통해 파라미터를 입력하고 데이터를 가져오는데, 쿼리를 통해 처음부터 데이터를 필요한 것만 필터링 할 수 있으면 참 좋겠지만 메소드를 실행시키면 일단 데이터는 이미 AWS 에 갔다 오게 된다. 그래서 AWS 에서 받은 결과 값을 가지고 재구성을 하는 수 밖에 없다.

 

그 방법으로는 내가 보기에는 2가지의 방법이 있다. 하나는 원초적으로 Key 값을 통해서 for 문으로 지지고 볶고 하는 쉽게 접근하는 것이고, 다른 하나로는 JMESPath 를 사용하는 것이다. 너무 복잡한 구성을 원한다면 전자가 좋겠지만, 단순한 추출이라면 후자의 방법이 훨씬 효율적이기 때문에 후자의 방법을 알아보도록 한다.

 

우선 JMESPath 란, 다음의 공식 홈페이지를 참조해보도록 하자.

 

JMESPath — JMESPath

Libraries in Multiple Languages Each JMESPath library passes a complete suite of compliance tests to ensure they work as intended. There are libraries in multiple languages including python, php, javascript and lua.

jmespath.org

간략하게, JSON 데이터를 JMESPath 의 규칙에 맞게 작성을 하면 원하는 데이터를 가져올 수 있다 라는 매커니즘(?) 을 가지고 있다.  홈페이지에는 사용하는 방법에 대한 예시가 너무 잘 나와 있어서 조금만 이해하면 금방 익힐 수 있도록 되어 있다.

 

마침, AWS PHP SDK 는 쿼리 메소드에 대한 리턴 값이 Result 형으로 들어오게 되는데 Result 형에는 JMESPath 를 사용하여 값을 가져오는 search 메소드가 있다. 간단하게 [ 파일명. 파일 사이즈, 수정일 ] 에 대한 데이터를 가져오고 싶다면 다음과 같이 작성을 해주면 된다.

$objs = $s3->listObjectV2([
    'Bucket' => ${버킷명},
]);

$objs->search("Contents[*].{name:Key, size: Size, date: LastModified}");

핵심은 "Contents[*].{name: Key, size: Size, date: LastModified}" 라고 할 수 있다. 쿼리의 내용은, Contents 의 모든 배열 값 중에서 Key, Size, LastModified 의 값을 가져와서 각각 새로운 키에 매칭을 시켜준다고 얘기를 풀어서 할 수 있을 것 같다.

 

특이한 점은, Object(또는 Set) 형태의 데이터를 쿼리하게 되면, 원래 가져오고자 하는 Value 의 Key 를 사용할 수 없다는 것이다. 공식문서에서도 내가 못본 것지 모르겠지만 사용할 수 없었고 새로 Key 를 매칭 시켜주어야 데이터를 뽑을 수 있었다. 그래서 파일명을 뜻하는 Key 라는 아이는 name 에 매칭을 시켜주게 된 것이다.

 

만약, 가져오는 목록에서 파일 데이터 만을 가져오고자 한다고 하면 다음과 같은 쿼리를 작성하면 될 것이다

$objs = $s3->listObjectV2([
    'Bucket' => ${버킷명},
]);

$objs->search("Contents[?Size != '0'].{name:Key, size: Size, date: LastModified}");

이번에는 [] 안에 * 대신 ?Size != '0' 을 넣어주었다. S3 에서는 JSON 에서 폴더를 구분하는 값이 없기 때문에 Size 데이터를 통해서 어떤 것이 파일이며, 어떤것이 폴더이며 하는 구분을 할 수 있다. 하지만 이것도 확실한 구분법은 아니기 떄문에 오차가 있을 만한 상황에는 사용하지 않도록 한다.

 

나머지 다른 방법들은 홈페이지의 설명을 보면서 익혀보도록 하면 좀 더 편하게 데이터를 활용 할 수 있을 것이다.

반응형
Comments