본문 바로가기
AWS

AWS Lambda 개발①) S3 트리거를 통한 S3 오브젝트 정보 가져오기 (+txt파일)

by code_yull 2021. 8. 19.

 

현재 해보고있는 프로젝트에서 S3트리거를 사용한 aws 람다를 활용하고 있다.

간단하게 위와 같은 구조를 통해, 사용자가 s3의 첫번째 버킷에 txt파일을 업로드하면, 람다에서 txt 파일의 내용을 읽어와서 수정을 한 후, 새로운 txt 파일을 만들어서 S3의 두번째 버킷에 넣어주는 것이다.

aws의 공식 문서에서, S3트리거를 활용한 썸네일 만들기 튜토리얼을 확인할 수 있지만, 텍스트 파일의 내용을 읽어오는 내용은 잘 찾을 수 없었기 때문에, 결론적으로 찾아보고 정리한 내용을 공유하고자 한다.

 

우선 S3 트리거를 사용하는 람다 코드 작성을 도와주는 블루프린트를 먼저 살펴보자.

람다 서비스 창에서 함수생성을 누르면, 위와 같은 창이 뜬다.

새로 작성은 기본적인 틀만 주고, 주요 기능 코드는 사용자가 스스로 작성해야 하는데,

블루프린트를 사용하면 내가 구현하고자 하는 기능의 기본 코드를 제공해준다.

우리는 가장 상단의 가운데 블루프린트(s3-get-objet-python)를 살펴볼 것이다.

파이썬 언어로, S3 트리거를 통해 이벤트가 발생하면, 해당 파일의 메타데이터를 읽어오는 코드이다.

함수 이름을 작성해주고, 연결할 S3 버킷과 이벤트 유형을 선택해준 뒤 함수를 생성해주면 된다.

이벤트 유형으로는 디폴트값인 '모든 객체 생성 이벤트'를 선택해주었다.

 

그러면 기본적으로 작성되어 있는 코드가 아래와 같다.

import json
import urllib.parse
import boto3

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        print("CONTENT TYPE: " + response['ContentType'])
        return response['ContentType']
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

간단하게 살펴보자면

람다 함수가 먼저 실행되면 'Loading function'을 프린트해주고

이벤트가 발생한 버킷의 이름을 변수 bucket에 저장해주고

업로드된 오브젝트의 파일명을 변수 key에 저장해준 뒤

try블록에서 해당 오브젝트의 content type(파일 유형)을 프린트해주되,

오류가 발생하면 except블록에서 오류 메시지 변수값과 'Error getting object{} ...'문자열을 프린트해주는 것이다.

 

여기서 꼭 가지고 가야하는 것이 bucket과 key이다.

try블록의 첫번째 코드를 보면

우리가 트리거된 s3의 이벤트로부터 해당 오브젝트를 가져올 때 꼭 필요한 것이 bucket과 key이다.

s3.get_object(Bucket = bucket, Key = key)를 통해서 해당 오브젝트에 접근한 후,

그 오브젝트에서 필요한 정보를 빼오는 코드를 작성해주면 되는 것이다.

 

더보기

참고로 bucket과 key는 s3에 객체가 업로드되었을 때, 람다로 날아오는 이벤트에서 읽어오는 것이다.

이벤트의 내용은 위 코드의 테스트 이벤트를 통해 살펴볼 수 있는데,

s3-get-object-python 블루프린트 코드의 디폴트 이벤트 템플릿인 s3-put을 살펴보면 아래와 같다.

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "ap-northeast-2",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "example-bucket",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "arn:aws:s3:::example-bucket"
        },
        "object": {
          "key": "test/key",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

위와같은 json형태의 이벤트를 통해 업로드된 오브젝트가 위치한 버킷 이름, 오브젝트의 이름과 사이즈 등을 알 수 있게 되는 것이다.

 

그렇다면 txt 파일의 내용을 가져오려면 어떻게 해야할까.

똑같이 s3.get_object(Bucket = bucket, Key = key)를 통해서 해당 오브젝트에 접근하고

그 오브젝트의 내용을 불러오는 코드를 작성해주면 된다.

import json
import urllib.parse
import boto3

s3 = boto3.client('s3')


def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    
    response = s3.get_object(Bucket=bucket, Key=key)
    originaltext = response['Body'].read().decode('utf-8')

기본 코드와 동일하게 bucket과 key값을 알아온 후

get_object함수를 통해 해당 오브젝트에 접근해서

오브젝트의 'body'부분을 read해서 utf-8으로 디코딩해주면 되는 것이다.

(참고로 utf-8 디코딩을 해주는 이유는 텍스트 파일을 작성할 때 문자열을 utf-8으로 인코딩을 해준 후 입력하기 때문이다. 다음글에서 텍스트 파일을 작성하는 과정을 통해 한번 더 살펴볼 것이다.)

 

이번 게시글에서는 aws 람다에서 s3트리거로 연결된 경우, 이벤트가 발생한 오브젝트의 정보를 가져오는 방법을 정리해보았다.

만약 업로드한 오브젝트의 파일 유형이 다르거나, 가져오고 싶은 정보가 다른 경우에도, bucket과 key값으로 오브젝트에 접근한다는 가장 기본적인 개념을 알면,

자세한 코드는 구글링을 통해 쉽게 해결할 수 있을 것이다.

 

이번글에서는 이미 업로드된 s3의 오브젝트에서 정보를 가져오는 방법을 정리했다면,

다음글에서는 람다에서 s3 버킷에 새로운 txt 파일을 업로드하는 방법을 정리해보고자 한다.

 

댓글