ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AWS] API Gateway, Lambda로 S3 파일 업로드 API 만들기
    Cloud/AWS 2021. 5. 14. 13:54
    728x90
    반응형

    API Gateway, Lambda로 S3 파일 업로드 하기

    저번 글 에서 API gateway를 만들고 해당 API가 호출되었을 때 람다 함수가 호출되는 간단한 예제를 진행해보았습니다.
    이번 글에서는 조금 더 응용해서 API gateway가 호출되었을 때 람다 함수로 S3에 파일 업로드 했을 때 이미지 사이즈를 줄이는 작업도 일어나는 것을 해보겠습니다.(NodeJS Lambda로 이미지 사이즈 줄이기)

     

    저번 글 도 같이 참고해서 보시는 것을 추천합니다. 바로 IAM 설정부터 진행해보겠습니다.

     

     

    IAM 역할 설정

    스크린샷 2021-05-14 오전 9 25 00

    위의 두 권한을 가진 역할 하나를 만들겠습니다.

     

     

     

    Lambda 함수 생성하기

    스크린샷 2021-05-14 오전 9 53 18

     

    스크린샷 2021-05-14 오전 9 54 09

     

    위에서 만들었던 IAM 역할을 선택하고 NodeJS 기반의 Lambda 함수를 생성하겠습니다.

     

     

    그리고 이미지 업로드를 할 수 있는 코드를 작성하고 람다 함수에 zip 형태로 올리겠습니다.

    스크린샷 2021-05-14 오전 10 37 44

    로컬에서 코드를 작성하고 zip으로 압축해서 생성한 Lambda 함수에 올릴 것인데요. 제가 작성하고 하는 프로젝트의 구조는 위와 같습니다. 어떻게 작성하는지 하나씩 알아보겠습니다.

    먼저 모듈을 설치해야 해서 아래의 명령어로 먼저 모듈을 설치하겠습니다.

    npm install aws-sdk parse-multipart bluebird

    그러면 node_modules, package-lock.json이 생길 것입니다. 이제 파일 업로드를 할 수 있는 람다 함수를 만들기 위해서는 index.js에 작성해야 합니다.

     

     

    index.js

    const AWS = require("aws-sdk");
    const multipart = require("parse-multipart");
    const s3 = new AWS.S3();
    const bluebird = require("bluebird");
    
    exports.handler = function (event, context) {
      const result = [];
    
      const bodyBuffer = Buffer.from(event["body-json"].toString(), "base64");
    
      const boundary = multipart.getBoundary(event.params.header["Content-Type"]);
    
      const parts = multipart.Parse(bodyBuffer, boundary);
    
      const files = getFiles(parts);
    
      return bluebird
        .map(files, (file) => {
          console.log(`uploadCall!!!`);
          return upload(file).then(
            (data) => {
              result.push({ data, file_url: file.uploadFile.full_path });
              console.log(`data=> ${JSON.stringify(data, null, 2)}`);
            },
            (err) => {
              console.log(`s3 upload err => ${err}`);
            }
          );
        })
        .then((_) => {
          return context.succeed(result);
        });
    };
    
    const upload = function (file) {
      console.log(`putObject call!!!!`);
      return s3.upload(file.params).promise();
    };
    
    const getFiles = function (parts) {
      const files = [];
      parts.forEach((part) => {
    
        const buffer = part.data
        const fileFullName = part.filename;
    
        const filefullPath = "각자 버킷 URL 적기" + fileFullName;
    
        const params = {
          Bucket: "S3 Bucket 이름",
          Key: fileFullName,
          Body: buffer,
        };
    
        const uploadFile = {
          size: buffer.toString("ascii").length,
          type: part.type,
          name: fileFullName,
          full_path: filefullPath,
        };
    
        files.push({ params, uploadFile });
      });
      return files;
    };

    위의 코드에서 본인의 버킷 이름, 각자 버킷 URL만 적고 index.js에 넣으시면 됩니다.

     

     

     

    프로젝트 압축하기

    zip -r 원하는이름.zip .
    ex) zip -r lambda.zip .

    스크린샷 2021-05-14 오전 10 45 41

    그러면 위와 같이 zip 파일이 생길 것입니다. 이것은 AWS Lambda 함수에 올리겠습니다.

     

     

    스크린샷 2021-05-14 오전 10 46 44

    람다 함수에 들어가면 위와 같이 zip 파일을 업로드 할 수 있는데 클릭하겠습니다.

     

    스크린샷 2021-05-14 오전 10 48 32

     

    그리고 위에서 압축한 파일을 올리면 위와 같이 zip 파일이 업로드가 잘 된 것을 확인할 수 있습니다.



    API Gateway 만들기

    스크린샷 2021-05-14 오전 9 56 46

     

    스크린샷 2021-05-14 오전 9 57 45

     

    REST API 기반으로 사용할 것이기 때문에 위와 같이 선택하고 만들겠습니다.

     

     

    스크린샷 2021-05-14 오전 9 58 44

     

    그리고 리소스를 생성하겠습니다.

     

     

    스크린샷 2021-05-14 오전 10 30 57

    리소스 이름은 원하는 이름으로 아무거나 정하면 됩니다. 저는 image로 하겠습니다.

     

    스크린샷 2021-05-14 오전 10 31 47

     

    그리고 메소드 API 메소드를 생성하겠습니다.

     

     

    스크린샷 2021-05-14 오전 10 34 00

     

    위와 같이 체크하고 POST 메소드를 하나 만들겠습니다.

     

    그리고 파일 업로드를 하기 위해서는 API Gateway이진지원에서 multipart/form-data를 적용해주어야 합니다.

     

    스크린샷 2021-05-14 오전 10 50 46

    이진 미디어를 추가해준 이유는 해당 형식, multipart폼 형식으로 요청을 보낸 파일들을 API Gateway에서 받으면 자체적으로 파일데이터를 이진 바이너리 형식으로 변환하여 처리해준다는 것을 의미합니다.

     

     

    스크린샷 2021-05-14 오전 10 53 28

    multipart/form-data

    이진 미디어 형식에다 위와 같이 multipart/form-data를 넣고 저장하겠습니다.

     

     

     

    S3 정책 추가하기

    스크린샷 2021-05-18 오후 12 23 55

     

    먼저 잠시 정책을 추가할 때만 S3을 액세스 할 수 있도록 하겠습니다.

     

     

    스크린샷 2021-05-18 오후 12 29 42

    위와 같이 잠시 퍼블릭으로 열어놓고 S3 Bucket을 생성한 후에 권한 탭으로 들어가겠습니다.

     

    스크린샷 2021-05-14 오전 10 57 38

     

    그리고 아래에 보면 버킷 정책이 존재하는데요. 여기서 정책을 하나 생성하겠습니다.

     

     

    스크린샷 2021-05-14 오전 10 59 18

    버킷 ARN을 복사한 후에 정책 생성을 누르겠습니다.

     

     

    스크린샷 2021-05-14 오전 11 01 11

    위에서 복사한 S3 ARN 뒤에/*을 넣고 위와 같이 작성하겠습니다.

     

     

    스크린샷 2021-05-14 오전 11 03 18

    위에서 선택했던 대로 잘 선택되었는지 확인하고 Generate Policy를 누르겠습니다.

     

     

    스크린샷 2021-05-14 오전 11 05 02

    생성된 정책을 복사하겠습니다.

     

     

    스크린샷 2021-05-14 오전 11 06 26

     

    복사한 정책을 넣고 저장을 누르겠습니다.

     

     

    스크린샷 2021-05-18 오후 12 31 21

     

    그리고 다시 모든 퍼블릭 엑세스 차단으로 체크하고 저장하겠습니다.



    API Gateway 설정 마무리

    스크린샷 2021-05-14 오전 11 08 33

    다시 API Gateway로 들어간 후에 위에서 만든 POST 메소드를 누르면 오른쪽에 통합 요청이라고 보이는데 이것을 누르겠습니다.

     

    스크린샷 2021-05-14 오전 11 12 17

    그리고 아래에 보면 매핑 템플릿이 존재하는데요. 여기서 위와 같이 선택하고 multipart/form-data를 넣겠습니다.

    multipart/form-data

     

     

    API Gateway 배포

    스크린샷 2021-05-14 오전 11 14 29스크린샷 2021-05-14 오전 11 15 34

    그리고 이름은 자유롭게 입력한 후에 배포를 하겠습니다.

     

    스크린샷 2021-05-14 오전 11 16 07

     

    그러면 위와 같이 호출 URL이 생성되었을 것입니다. 호출 URL을 가지고 PostMan에서 파일 업로드를 해보겠습니다.

     

     

    PostMan 테스트

    스크린샷 2021-05-14 오전 11 18 51

    파일 업로드도 잘 된 것을 확인할 수 있습니다. 이제 S3에 파일이 잘 올라와있는지 확인해보겠습니다.

     

     

    S3 Bucket 확인

    스크린샷 2021-05-14 오전 11 21 13

    위와 같이 파일이 잘 올라와 있는 것을 확인할 수 있습니다. 그동안은 EC2에 API 만든 코드를 올려서 실행을 시켰습니다.(jar를 실행시키던지, pm2로 node 실행시키던지..?) 그런데 이번 글에서는 API-Gateway, Lambda를 이용해서 Serverless 하게 사진 업로드 하는 API를 구축해보았습니다.

     

    저는 아직은 EC2에 코드를 올려서 기존의 방식대로 하는 것이 익숙하지만 앞으로 Serverless로 서버를 구축해보면서 익숙해지는 것도 좋을 거 같습니다.

    반응형

    댓글

Designed by Tistory.