[AWS] Serverless 사진첩 서비스

Numberbeen·2023년 2월 6일
0

AWS

목록 보기
10/13
post-thumbnail

주요 기능

우리가 만들려는 서버리스 사진첩 서비스는, 여느 클라우드 사진 저장 서비스들처럼 단순히 사진을 업로드하는 것 외에도, 인증 기능과 썸네일 생성 기능을 제공한다.

시작


sam init 명령을 이용해 Quick Start Template 으로부터 Standalone function을 하나 생성합니다. (nodejs14.x 버전으로 진행)

X-Ray 기능 사용 X, Application Insights 기능 사용 X Project name = serverless-album 으로 설정.

exports.helloFromLambdaHandler = async (event, context) => {
    console.log(event)

    console.log(context)

    return 'Hello from Lambda!';
}

폴더에 파일들이 생성되고 src/handlers 폴더 안에 있는 hello-from-lambda.js 파일에 코드를 위와 같이 작성한다. lambda 함수의 파라미터를 정의한다. 이는 이벤트 소스로부터 트리거가 발생했을 때 이벤트의 형태를 확인하기 위함이다.

sam build 명령어로 빌드하고 sam deploy --guided 명령어로 배포한다.

중간에 y 를 눌러 배포한다.

성공.

콘솔에서 Lambda 에 배포된 걸 확인 할 수 있다.

우린 여기서 S3 에 사진 파일이 업로드 되면 작동되게 할 예정이므로 트리거 추가를 눌러 S3 버킷을 추가하자. 나는 미리 serverless-album-src-s3 라는 이름으로 S3 버킷을 만들어 놨다.

제일 하단의 영어는 번역하면

입력 및 출력 모두에 동일한 S3 버킷을 사용하는 것이 권장되지 않으며 이 구성으로 인해 재귀 호출, 람다 사용량 증가 및 비용 증가가 발생할 수 있음을 인정합니다.

위와 같은데 내가 이해하기론 동일한 버킷을 하면 무한루프? 가 되기때문에 사용한만큼 비용을 내기 때문에 돈이 더 나올 수 있으니 입력과 출력은 다른 버킷으로 하라는 뜻으로 이해했다.

추가 완료.

그러면 S3 에 사진파일이 올라가게 되면 위에서 입력한 함수가 실행되어야 한다. 확인 해보자. 버킷으로 가서 업로드하고 다시 lambda콘솔로 와서 확인 하는 것 보다 lambda 콘솔에서 테스트하는 방법으로 진행하자.

하단으로 내리게 되면 테스트를 할 수 있는 화면이 나온다. 거기서 템플릿은 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": "serverless-album-src-s3",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "s3 arn 주소"
        },
        "object": {
          "key": "coding.jpeg",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

위처럼 테스트 코드에 region 값과 bucket name, bucket arn 에는 내가 생성한 버킷을 적어주면 되고.
object key 값은 내가 올릴 사진파일 이름을 입력해준다.

상단에 test 를 누르면 성공한다. 실패하면 로그가 출력되므로 로그를 보고 확인하면서 디버깅을 해보자.

최소한의 준비는 마쳤다. 이제 본격적으로 아래의 작업을 해보자.

  • 이미지가 업로드되면, 원본과 별도로 썸네일을 생성하고, 이를 별도의 버킷에 저장해야 한다.
    • 썸네일 이미지는 가로 200px의 크기를 가진다.

우선 별도의 버킷을 생성해주자 serverless-album-resize-src-s3 라는 버킷을 만들었다.

코드 작성.

참고 하여 hello-from-lambda.js 수정했다. 나는 여기서 네다섯시간? 걸린 것 같다... 작성한 후 빌드하고 배포했다.

배포가 완료되고 원본 s3 버킷에 사진파일을 올렸다.

제대로 작동되려면 원본에 S3 버킷에 사진파일이 올라가고 lambda 함수가 실행되어 대상 S3 버킷으로 200 픽셀로 조절된 사진이 들어갈 것이다.

첫번째 트러블

에러가 떳다... CloudWatch 에서 확인해보자.

런타임 에러가 떳고 에러 메시지를 유심히 보니 Error: Cannot find module 'sharp'

그렇다. sharp 모듈을 못찾는단다... ?? 로컬에서 내가 설치 안했나... 설치해보자 npm install 설치 안했네... 설치 한 후 빌드 하고 다시 배포해보자.

또 난다. 그런데 뭔가 아까랑 다르다? sharp 에러긴 sharp 에런데... 제대로 설치가 안된거 같다... 검색했다.
그래서 예제를 보다 보디. M1 Mac을 사용하는 경우, package.json 구성을 다음과 같이 설정해야 제대로 설치가 된단다.

"dependencies": {
  "aws-sdk": "^2.1111.0"
}

"scripts": {
  "preinstall": "npm install --platform=linux --arch=x64 --no-save sharp"
}

수정 후 혹시 몰라 node_modules 폴더와 package-lock.json 파일을 삭제한 후 npm install 을 하고 빌드 배포 하였다.

원본 버킷에다 사진파일을 올려서 되는지 확인했다. 해당 에러는 이제 보이지 않는다. 하지만....

두번째 트러블

진짜 AWS 공부하면서 Acess Denied 몇백번은 보는거 같다. 권한 권한 권한 권한 권한!!!! 인데... 무슨 권한이 필요한건가... 검색하던중.. 크루분께서 답장해주신 게시글을 보고 해결했다.

람다 실행 역할에 s3 관련 권한이 필요하다.
s3의 object를 읽어올 수 있어야 하기 때문에, 람다 실행역할에 s3 권한을 연결해주셔야 합니다. (최소한, s3:GetObject는 있어야 합니다.)

실행권한 줘보자. (난 S3Full 권한을 줬다.)

역활 이름을 클릭

기존 권한 AWSLambdaBasicExecutionRole 이거만 있었고 내가 AmazonS3FullAccess 권한을 추가해줬다.

다시 원본버킷에 사진파일을 올려보자.

해당 에러는 보이지 않았다. 그리고...

세번째 트러블

이번엔 또 뭐냐... 로그를 보다보니 이건 좀 확신할 수 있는 글을 발견했다. "errorMessage": "The bucket does not allow ACLs" 버킷에서 ACL 을 허용하지 않는다란다. 버킷에 ACL 을 허용으로 바꿔주러 가자.
원본 버킷에서 다음과 같이 설정해주고 다시 사진파일 올려보자.

또 같은 에러가 뜬다...

네번째 트러블

혹시 대상 버킷에도 설정해줘야되나... 해보자.

우이씨 된다. 대상버킷 원본버킷 다 ACL 허용해줘야 된다.

대상 버킷에도 잘 들어오는걸 확인했다.

Amazone SNS 활용 메일 전송.

이건 또 어떻게 하는거지... 구글링하다가. 어떤 귀인께서 대상 추가를 하면 된다고 하였다. 해보자.
뭐 아무것도 안뜨는데...

ㅜㅜ 검색하니 Amazon sns 에서 주제를 생성하고 구독 설정을 해줘야 한다고 한다. 콘솔을 이용해 Amazon SNS 로 이동해서 주제를 생성해주자.

주제 생성을 클릭

유형을 난 표준으로 하였다. 그 이유는 구독 프로토콜에 Lambda 가 있기에 바로 픽 했다. 이름은 serverless-album-sns 를 입력해서 생성하였다.

구독 생성해보자.

다양한 프로토콜이 많은데 나는 이메일로 받을꺼니까 이메일로 설정하고 엔드포인트는 내 이메일 주소를 입력했다.

확인 대기중이라는데 내 메일로 인증 메일을 보낸거 같다. 확인하자.


역시 와있다 바로 눌러서 인증완료 하자.

정상적으로 확인된다.

그럼 이제 다시 lambda 콘솔로 이동해서 대상추가를 진행해봏자.

비동기식 호출로 설정하고 조건은 사진파일이 정상적으로 리사이즈 되고 그 리사이즈한 파일의 url 을 보내야하니 성공으로 설정하고 유형은 SNS 주제 대상은 방금 생성한 sns 를 선택했다.

뭔가 착착 되는 느낌? 원본버킷에 사진 올려서 메일이 가나 확인하자.

원본 버킷에 올렸고...

로그도 깨끗하고 ~

대상 버킷에도 resize 되서 들어갔고 ~

이제 메일만 오면되는데 오긴 왔다. 그런데

이건 뭔말이냐... 이건 또 어떻게 해결해줘야 하나...

다섯번째 트러블

내가 원하는건

메일로 리사이즈된 사진의 URL이 전송이 되어야 한다.

이거다. 이걸 어떻게 하는건가... Amazone SNS. 콘솔을 다 눌러보아도 이렇타할 기능은 없고 구글링하여도 나는 못 찾았다...

그렇게 시간을 보내고 있는 중 귀인이 올린 글을 보게되었고, 코드로 처리한걸 보고 그대로 배껴서 내 코드에 맞게 수정했다. (감사합니다.)

  const sns = new AWS.SNS(region);
  const massage = await sns.publish({
      Message: "URL : " + `https://${rebucket}.s3.${region}.amazonaws.com/${rekey}`,
      Subject: "썸네일",
      TopicArn: "sns arn 주소"
  }).promise()

  return massage;

hello-from-lambda.js 제일 하단에 위와 같이 추가해줬다. 저기서 TopicArn 주소는 Amazon SNS 주제 만든거에 ARN 주소다.

코드를 수정했으니 새로 빌드하고 배포하자.

배포 끝났으니 원본 버킷에 사진 올리고 메일로 가보자..

오오오오오오오 뭔가 주소처럼 URL 이 있다 눌르자 두구두구

내가 올린 사진이 짠 하고 나온다. 됬다 성공이다.

이로써 최소 요구사항에 모든 사항을 컴플릿 했다. 추가로 고급 과정이 있는데 이건 기회가 되면 시도해볼 예정이다.

profile
내기 이해한 것을 보관하는 곳

0개의 댓글