Code States/TIL

[0511] (페어) 마이크로서비스 작성 - 서버리스 애플리케이션

ki1111m2 2023. 5. 11. 13:37

Advanced Challenge

  • 과제를 달성하면, S3 이벤트가 SQS로 전송되게 만들고, SQS로부터 이벤트를 받아 람다가 실행하게 만들어봅시다.
  • 썸네일 생성이 완료되면, 메일로 해당 썸네일 URL과 함께 전송이 되게 만들어봅시다.
    • Amazon SNS를 활용합니다.
  • S3의 Pre-signed URL 기능을 이용하여, 업로드 전용 URL을 획득하고, 이를 통해 이미지를 S3 업로드할 수 있게 만들어봅시다.

S3 이벤트가 SQS로 전송되게 만들고, SQS로부터 이벤트를 받아 람다가 실행하도록 만들기

람다 함수의 역할에 SQS Full Access 권한을 추가한다

SQS를 생성한다

S3 버킷에 이벤트 알림으로 SQS를 연결한다

람다 함수에 트리거로 SQS를 추가한다

람다 함수의 코드를 수정한다

SQS로 이벤트 내용을 넘기고, 거기서 버킷 명과 키 이름을 가져온다

const AWS = require('aws-sdk')
const util = require('util')
const sharp = require('sharp')

const s3 = new AWS.S3()
const sns = new AWS.SNS()

exports.helloFromLambdaHandler = async (event, context) => {
  console.log("event", event)
  //const bucket = event.Records[0].s3.bucket.name
  //const key = event.Records[0].s3.object.key

    const sqsBody = JSON.parse(event.Records[0].body)
      
    const bucket = sqsBody.Records[0].s3.bucket.name
    const key = sqsBody.Records[0].s3.object.key

    const s3Object = await s3.getObject({
      Bucket: bucket,
      Key: key
    }).promise()
          
    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body)
        .resize(200)
        .jpeg({ mozjpeg: true })
        .toBuffer()
          
    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
      Bucket: 'ks-serverless-photo-image-bucket', 
      Key: key,
      ContentType: 'image/jpeg',
      Body: data,
      ACL: 'public-read'
    }).promise()
  

}

 

빌드 디플로이 후 테스트를 진행한다

버킷에 이미지를 올린다

정상적으로 로그가 생성된다

대상 버킷에 리사이징된 사진이 정상적으로 올라간다


썸네일 생성이 완료되면 해당 썸네일 URL이 메일로 전송되게 하기

 

SNS 주제를 생성한다

구독을 생성한다

람다 함수에 SNS 트리거를 추가한다

람다 함수 코드를 수정한다

const AWS = require('aws-sdk')
const util = require('util')
const sharp = require('sharp')

const s3 = new AWS.S3()
const sns = new AWS.SNS()

exports.helloFromLambdaHandler = async (event, context) => {
  console.log("event", event)
  //const bucket = event.Records[0].s3.bucket.name
  //const key = event.Records[0].s3.object.key

    const sqsBody = JSON.parse(event.Records[0].body)
      
    const bucket = sqsBody.Records[0].s3.bucket.name
    const key = sqsBody.Records[0].s3.object.key

    const s3Object = await s3.getObject({
      Bucket: bucket,
      Key: key
    }).promise()
          
    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body)
        .resize(200)
        .jpeg({ mozjpeg: true })
        .toBuffer()
          
    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
      Bucket: 'ks-serverless-photo-image-bucket', 
      Key: key,
      ContentType: 'image/jpeg',
      Body: data,
      ACL: 'public-read'
    }).promise()
    
    await sns
      .publish({
        Subject: 'New file is uploaded',
        TopicArn: 'arn:aws:sns:ap-northeast-2:477644685304:photo-sns',
        Message: `https://ks-serverless-photo-image-bucket.s3.ap-northeast-2.amazonaws.com/${key}`
      }).promise()
 

}

 

AuthorizationError

인증 에러가 발생했다

람다 함수에 SNS 권한을 안넣어줘서 발생

람다 함수 역할에 SNS Full Access 권한을 넣어준다

Unexpected token u in JSON at position 0

정상적으로 올라가지만 오류가 발생

해당 오류를 검색해 보았을 때 parse로 변환하고자 하는 내용이 비어있어서 그렇다고 한다

구독을 확인했더니 확인 대기중이라고 한다

이메일에서 구독 확인을 했어야 했다

그러나 여전히 같은 오류 발생

try catch 문으로 코드를 수정했다

const AWS = require('aws-sdk')
const util = require('util')
const sharp = require('sharp')

const s3 = new AWS.S3()
const sns = new AWS.SNS()

exports.helloFromLambdaHandler = async (event, context) => {
  console.log("event", event)
  //const bucket = event.Records[0].s3.bucket.name
  //const key = event.Records[0].s3.object.key
  try{
    const sqsBody = JSON.parse(event.Records[0].body)
      
    const bucket = sqsBody.Records[0].s3.bucket.name
    const key = sqsBody.Records[0].s3.object.key

    const s3Object = await s3.getObject({
      Bucket: bucket,
      Key: key
    }).promise()
          
    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body)
        .resize(200)
        .jpeg({ mozjpeg: true })
        .toBuffer()
          
    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
      Bucket: 'ks-serverless-photo-image-bucket', 
      Key: key,
      ContentType: 'image/jpeg',
      Body: data,
      ACL: 'public-read'
    }).promise()
    
    await sns
      .publish({
        Subject: 'New file is uploaded',
        TopicArn: 'arn:aws:sns:ap-northeast-2:477644685304:photo-sns',
        Message: `https://ks-serverless-photo-image-bucket.s3.ap-northeast-2.amazonaws.com/${key}`
      }).promise()
  } catch (e) {
    console.log("error", e)
  }

}

 

이번엔 메일까지 정상적으로 오는 것을 확인했다

그러나 여전히 같은 오류 발생..

event 객체로 들어온 내용을 보니 sns의 객체를 받고있었다

람다 함수의 트리거로 SNS까지 넣어놔서 발생했던 문제..

지운 후 해결됐다

트리거로 넣은 것들마다 핸들러를 실행하는 거라고 한다

sns는 코드에 넣는 것만으로도 동작!