서버리스 - 썸네일로 변환하기

문한성·2023년 5월 11일
0

부트캠프

목록 보기
85/123
post-thumbnail

https://velog.velcdn.com/images/sororiri/post/29d30afd-d47b-4a28-a752-9b0add91ec7a/image.png

목표

저장된 원본 이미지를 썸네일용 이미지로 변환하여 새로운 버킷에 저장하기

step 1 : 버킷 생성

총 두개의 버킷을 생성한다.하나의 버킷은 원본 이미지를 저장할 버킷이고 다른 하나는 원본 이미지가 썸네일 이미지로 변경되어 넣어질 버킷이다.

  1. 두개의 S3 버킷을 생성한다 (원본 이미지 저장용 하나, 썸네일로 변환되어 넣어질 놈 하나)

    필자는 버킷명을 원본이미지용: bk-picture, 썸네일용: bk-thumbnail으로 지었다.

    • ACL 활성화 및 퍼블릭 액세스가 가능하도록 변경
    ![https://velog.velcdn.com/images/sororiri/post/92de122f-f957-44f9-8c5e-faa544524bf0/image.png](https://velog.velcdn.com/images/sororiri/post/92de122f-f957-44f9-8c5e-faa544524bf0/image.png)
    • 버킷 정책 수정 (자신의 s3 arn 리소스로 수정) https://velog.velcdn.com/images/sororiri/post/3bcd9473-ec68-4115-ad06-ae8f78103113/image.png
      {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Sid": "PublicReadGetObject",
               "Effect": "Allow",
               "Principal": "*",
               "Action": "s3:GetObject",
               "Resource": "arn:aws:s3:::bk-pictrue/*"
           }
       ]
      }

      두개의 S3 모두 위와 같이 설정하여 만들어준다.

step 2: 람다 함수 생성

람다함수 역할 : 원본 이미지 버킷에 이미지가 추가되었을 때 이미지 사이즈를 변경하고 썸네일용 버킷에 넣음

선수조건:

1. AWS CLI 자격 증명 이 완료되어야 함.

2. SAM 이 설치되어야 한다.

1. 람다 함수 생성 및 배포

  • sam init 을 통해 초기 세팅을 해준다.
    $ sam init
    ...
      - Which template source would you like to use?
      	=> `1` - AWS Quick Start Templates
      - Choose an AWS Quick Start application template
      	=> `1` - Hello World Example
      - Which runtime would you like to use?
      	=> `15` - nodejs14.x
      - What package type would you like to use?
      	=> `1` - Zip
      - Select your starter template
      	=> `1` - Hello World Example
      - Would you like to enable X-Ray tracing on the function(s) in your application?
      	=> `N` (추적 관련된 내용이나 현재 필요치 않음)
    	- Would you like to enable monitoring using CloudWatch Application Insights?
    For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html
    		=> `N`
      - Project name [sam-app]:
      	=> `thumbnail-app-test`
    
    • 결과:
      sam init
      
      	You can preselect a particular runtime or package type when using the `sam init` experience.
      Call `sam init --help` to learn more.
      
      	Which template source would you like to use?
           1 - AWS Quick Start Templates
           2 - Custom Template Location
      Choice: 1
      
      	Choose an AWS Quick Start application template
           1 - Hello World Example
           2 - Multi-step workflow
           3 - Serverless API
           4 - Scheduled task
           5 - Standalone function
           6 - Data processing
           7 - Hello World Example With Powertools
           8 - Infrastructure event management
           9 - Serverless Connector Hello World Example
           10 - Multi-step workflow with Connectors
           11 - Lambda Response Streaming
           12 - Lambda EFS example
           13 - DynamoDB Example
           14 - Machine Learning
      Template: 1
      
      	Use the most popular runtime and package type? (Python and zip) [y/N]: N
      
      	Which runtime would you like to use?
           1 - aot.dotnet7 (provided.al2)
           2 - dotnet6
           3 - dotnet5.0
           4 - dotnetcore3.1
           5 - go1.x
           6 - go (provided.al2)
           7 - graalvm.java11 (provided.al2)
           8 - graalvm.java17 (provided.al2)
           9 - java17
           10 - java11
           11 - java8.al2
           12 - java8
           13 - nodejs18.x
           14 - nodejs16.x
           15 - nodejs14.x
           16 - nodejs12.x
           17 - python3.9
           18 - python3.8
           19 - python3.7
           20 - python3.10
           21 - ruby2.7
           22 - rust (provided.al2)
      	Runtime: 15
      
      	What package type would you like to use?
           1 - Zip
           2 - Image
      	Package type: 1
      
      	Based on your selections, the only dependency manager available is npm.
      	We will proceed copying the template using npm.
      
      	Select your starter template
           1 - Hello World Example
           2 - Hello World Example TypeScript
      	Template: 1
      
      	Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: N
      
      	Would you like to enable monitoring using CloudWatch Application Insights?
      	For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: N
      
      	Project name [sam-app]: thumbnail-app-test
      
       -----------------------
       Generating application:
       -----------------------
       Name: thumbnail-app-test
       Runtime: nodejs14.x
       Architectures: x86_64
       Dependency Manager: npm
       Application Template: hello-world
       Output Directory: .
       Configuration file: thumbnail-app-test/samconfig.toml
      
       Next steps can be found in the README file at thumbnail-app-test/README.md
      
      	Commands you can use next
      	=========================
      	[*] Create pipeline: cd thumbnail-app-test && sam pipeline init --bootstrap
      	[*] Validate SAM template: cd thumbnail-app-test && sam validate
      	[*] Test Function in the Cloud: cd thumbnail-app-test && sam sync --stack-name {stack-name} --watch
  • sam init 으로 만들어진 폴더thumbnail-app-test 내에서 hellow-world 내 app.js 에 아래의 소스를 붙여넣는다.
    const aws = require('aws-sdk');
    const s3 = new aws.S3({ apiVersion: '2006-03-01' });
    const sharp = require('sharp');
    
    exports.lambdaHandler = async (event, context) => {
    console.log(event);
    console.log(context);
    
    const bucket = event.Records[0].s3.bucket.name;      // 원본 버킷 이름
    const key = event.Records[0].s3.object.key;          // 원본 버킷 키
    
    console.log("bucket: ", bucket);
    console.log("key: ", key);
    
    const dstBucket = process.env.s3resized     // 썸네일 버킷 이름
    console.log(`test  111`);
    // 원본 버킷으로부터 파일 읽기
    const s3Object = await s3.getObject({
           Bucket: bucket,
           Key: key
    }).promise()
    console.log(`test  222`);
    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body)
           .resize(200)
           .jpeg({ mozjpeg: true })
           .toBuffer()
    console.log(`test  333`);
    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
           Bucket: dstBucket,
           Key: key,                                       // 원본 버킷 키와 동일
           ContentType: 'image/jpeg',                      // 컨텐츠 타입
           Body: data,
           ACL: 'public-read'
    }).promise()
    console.log(`test  444`);
    
    return result;
    }

    위의 소스 역할: 원본 이미지 버킷에 추가된 이미지를 가져와 이미지 사이즈를 변경하고 썸네일용 버킷에 넣음

  • sharp 라이브러리 설치
    • hellow-world 폴더 내에서 npm install sharp 실행 https://velog.velcdn.com/images/sororiri/post/19d46179-8566-4a61-9c97-9560299dc875/image.png

window에서 sharp를 사용하려면 에러가 발생한다.
프로젝트폴더/.aws-sam/build 경로에서 아래의 명령어를 통해 sharp를 설치해준다.
빌드를 새로할 때 마다 sharp를 uninstall하고 다시 install하지 않으면 에러가 발생한다.

  • 매번 빌드를 하는 과정에서 새로 수동으로 지우고 설치하는것에 몹시 번거러움을 느꼈지만 해결을 실패하였다. 여유가있을 때 다시한번 시도해보고자 한다.
npm install --platform=linux --arch=x64 --no-save sharp
  • 로컬에서 테스트 방법

람다 함수의 테스트탭에서 s3-put템플릿을 받아와서 aws-region과 s3-bucket-name과 arn을 수정해서 복사한다.

프로젝트 최상위 폴더에 s3-event-log.json이란 파일을 생성해서 그안에 위에서 복사한 내용을 붙여준다.
sam invoke 명령을 통해서 로컬에서 테스트 한다.

sam local invoke -e s3-event-log.json
  • 빌드 및 배포
    • cd ..
    • sam build
    • sam deploy --guided결과: https://velog.velcdn.com/images/sororiri/post/07878654-9cd0-417f-a23f-dbb8cbcc86b0/image.png
      $ sam deploy --guided
         Stack Name [thumbnail-app-test]:
         AWS Region [ap-northeast-2]:
         #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
         Confirm changes before deploy [Y/n]:
         #SAM needs permission to be able to create roles to connect to the resources in your template
         Allow SAM CLI IAM role creation [Y/n]:
         #Preserves the state of previously provisioned resources when an operation fails
         Disable rollback [y/N]:
         HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
         Save arguments to configuration file [Y/n]:
         SAM configuration file [samconfig.toml]:
         SAM configuration environment [default]:
         Deploy this changeset? [y/N]: y
      https://velog.velcdn.com/images/sororiri/post/58df3403-ab63-4ea9-b704-4c6fcdc7fba2/image.png

2. 람다 함수에 원본 버킷 트리거 추가 및 환경 변수 설정

  • 만들어진 람다 페이지로 이동 https://velog.velcdn.com/images/sororiri/post/cb9be03b-fd75-4208-bf3f-e3a561749fdb/image.png
  • 트리거 추가 (API 게이트웨이는 사용하지 않으므로 삭제해도 무방함) https://velog.velcdn.com/images/sororiri/post/e881b86c-473a-4ff5-a2fe-c70c130abbdc/image.png https://velog.velcdn.com/images/sororiri/post/4669c525-22af-4ffb-87c0-633f1b51a4f8/image.png
  • 환경변수 설정
    • 편집으로 이동 https://velog.velcdn.com/images/sororiri/post/77ff23fa-70ac-40cf-a74d-5f4981097a9d/image.png
    • bk-thumbnail 란에 썸네일용 버킷명을 적는다. https://velog.velcdn.com/images/sororiri/post/cc8b2a47-1f8b-4732-a2d3-53ee4d78f718/image.png

step 3: 람다 함수에 버킷 권한 부여

  • IAM 정책 생성
    • 정책 페이지 이동
    • 정책 생성 버튼 클릭
    • JSON 탭을 선택한 후 다음 정책을 붙여 넣음.
      {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "logs:PutLogEvents",
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream"
                ],
                "Resource": "arn:aws:logs:*:*:*"
            },
            {
                "Sid": "AllAccess",
                "Action": "s3:*",
                "Effect": "Allow",
                "Resource": [
                    "*"
                ]
            }
        ]
      }
    • 정책명을 LambdaS3Policy 로 하고 정책 생성
      • 해당 정책은 로그 권한과 S3 에 접근 및 저장 에 대한 권한을 갖고 있음.
  • 실행 역할 생성
    • 역할 페이지 이동
    • 역할 만들기 버튼 클릭
    • 신뢰할 수 있는 엔터티 선택 https://velog.velcdn.com/images/sororiri/post/e6c36c0d-1038-41d3-aa7e-f2d0fd575677/image.png
    • 이전에 만들었던 LambdaS3Policy 정책을 추가
    • 역할명을 lambda-s3-role 로 하여 역할 생성
  • 람다 함수에 역할 할당
    • 역할을 lambda-s3-role 로 변경 https://velog.velcdn.com/images/sororiri/post/0596718a-4e7b-451b-9772-3d8834199b5e/image.png

step 4: 정상 동작 테스트 및 에러 수정

  • 원본 이미지 버킷에 jpeg 파일을 업로드 한다. https://velog.velcdn.com/images/sororiri/post/ee624ea2-9b5b-4b85-9258-145ec18299fb/image.png
  • 썸네일 버킷에 파일 업로드 상태 확인. 실패함. https://velog.velcdn.com/images/sororiri/post/24fcf52e-c195-4239-afcf-ed99d5cfe2d8/image.png
  • 파일이 없다. Cloud Watch 로그 확인
    • 로그로 이동 https://velog.velcdn.com/images/sororiri/post/10cd319a-7c78-47b6-9485-850679467d2b/image.png
    • 타임아웃으로 인해 실패된 것을 확인 https://velog.velcdn.com/images/sororiri/post/ae0097fc-718a-4316-9a57-96cb0c4dd714/image.png
    • 타임아웃을 기존 3초에서 10초로 변경 https://velog.velcdn.com/images/sororiri/post/ad1ae9bc-818e-43f6-b5a8-4d2a40b8cc92/image.png
    • 다시 jpeg 이미지를 넣고 테스트
    • 썸네일 이미지가 변경되지 않은 것 확인 https://velog.velcdn.com/images/sororiri/post/3f7f5610-6c55-4110-ad21-530934e4842f/image.png
    • 로그 확인 https://velog.velcdn.com/images/sororiri/post/01463b6e-848d-4b30-8dc7-01477dde4f85/image.png
    • 로그 결과: 다음의 에러가 뜨면서 죽음 Runtime exited with error: signal: killed Runtime.ExitError
    • 보통 Memory 가 부족할 때 죽는다고 함 (스택오버플로우)
    • 람다 함수 Memory 변경
      • 필자는 128MB -> 500MB로 넉넉히 변경함 https://velog.velcdn.com/images/sororiri/post/01eb3569-2e55-4818-a03c-a87bdd01c1cb/image.png
    • 다시 테스트 진행
    • 정상적으로 넣어지는 것 확인 https://velog.velcdn.com/images/sororiri/post/27ccf228-a81a-46a6-a9fd-3fdcdf78c109/image.png

추후 필자가 알아둬아야할 정보: ACL 이 뭔지 추후 확인이 필요함

참고자료:

1. cks8483님 블로그

2. AWS 자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성

3. AWS 자습서: Hello World 애플리케이션 배포

4. AWS: Lambda 실행 역할

5. 자습서: Amazon S3 트리거를 사용하여 Lambda 함수 호출

6. 상협님 블로그

profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글