본문 바로가기

Cloud/AWS

AWS Lambda - API Gateway로 S3 파일 업로드 API 만들기 #1 - Lambda 함수 생성

반응형

안녕하세요. 남산돈가스입니다.

 이번 포스팅에서는 웹을 개발하면서 가장 골칫거리지만 자주 쓰이게 될 수 있는 파일 업로드 기능 구현에 대해서 포스팅하려고합니다.

 하지만 일반적인 파일업로드가 아닌, Lambda로 S3에 파일을 업로드 시키는 함수를 생성하고, 해당 Lambda함수를 API Gateway에 연결하여 multipart-form 형식으로 파일을 업로드하는 Serverless 파일업로드를 구현할 예정입니다.

 이런 방식으로 업로드기능을 구현하게 되면, 추후에 어디든지 파일업로드 기능을 쓸 수 있는 Micro Service가 될 수 있습니다.

포스팅은 다음과 같이 3회에 걸쳐 진행되겠습니다.

#1. Lambda 함수 생성

#2. API Gateway, S3 셋팅

#3. API Gateway - Lambda 연결 및 테스트


그렇다면 지금부터 그 첫번째 단계인 Lambda 함수 생성을 진행해보겠습니다.

먼저 Lambda 서비스에 접속한 뒤 Node.js 기반의 새로운 함수를 생성합니다.



함수를 생성하면 아래와 같이 트리거가 추가되지 않은 날것의 함수가 생성된 것을 확인하실 수 있습니다.
 쥐도 새도 모르게 변하는 AWS 콘솔 덕분에(?) 매번 포스팅할 때마다 Lambdad의 콘솔화면이 다채롭게  변하고있네요...ㅎㅎ



기존의 포스팅에서는 위 사진처럼 인라인으로 편집하는 포스팅만 진행했었는데 금번 포스팅에서는 외부 node_module을 사용하는 경우라 로컬에서 작업한 소스를 ZIP파일 형식으로 업로드하여 함수를 생성해보겠습니다.

로컬 터미널에서 upload라는 폴더를 생성하고 index.js을 생성합니다.

  • index.js
그리고 해당 함수에 필요한 node_module을 install 하기 위해서 npm install 명령어를 사용합니다.

필요 모듈
  • aws-sdk : AWS javascript sdk 모듈
  • parse-multipart : multipart형식으로 들어 온 파일을 데이터 형식으로 변환
  • sha1 : 암호화 모듈
  • bluebird : 비동기 Promise 패턴 매서드 사용 모듈
위의 모듈들을 npm install aws-sdk parse-multipart sha1 bluebird 명령어를 이용해 설치합니다.


gimseongsin-ui-MacBook-Pro:Desktop gimseongsin$ cd upload/
gimseongsin-ui-MacBook-Pro:upload gimseongsin$ npm install aws-sdk parse-multipart
sha1 bluebird
/Users/gimseongsin/Desktop/upload
├─┬ aws-sdk@2.163.0
│ ├─┬ buffer@4.9.1
│ │ ├── base64-js@1.2.1
│ │ ├── ieee754@1.1.8
│ │ └── isarray@1.0.0
│ ├── crypto-browserify@1.0.9
│ ├── events@1.1.1
│ ├── jmespath@0.15.0
│ ├── querystring@0.2.0
│ ├── sax@1.2.1
│ ├─┬ url@0.10.3
│ │ └── punycode@1.3.2
│ ├── uuid@3.1.0
│ ├── xml2js@0.4.17
│ └─┬ xmlbuilder@4.2.1
│ └── lodash@4.17.4
├── bluebird@3.5.1
├── parse-multipart@1.0.4
└─┬ sha1@1.1.1
├── charenc@0.0.2
└── crypt@0.0.2

npm WARN enoent ENOENT: no such file or directory, open '/Users/gimseongsin/Desktop/upload/package.json'
npm WARN upload No description
npm WARN upload No repository field.
npm WARN upload No README data
npm WARN upload No license field.

필요 모듈을 모두 설치하였다면, 앞서 생성한 index.js 에 아래와 같이 작성해줍니다.
(이후에 개인적으로 소스를 사용하신다면, 알맞게 수정하여 사용하시길 바랍니다.)

const AWS = require('aws-sdk');
const multipart = require("parse-multipart");
const s3 = new AWS.S3();
const sha1 = require('sha1');
const bluebird = require('bluebird');

exports.handler = function(event, context) {

let result = []

var bodyBuffer = new Buffer( event[ 'body-json' ].toString(), 'base64' );

var boundary = multipart.getBoundary( event.params.header[ 'Content-Type' ] )

var parts = multipart.Parse( bodyBuffer, boundary )

let 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)
})
}


let upload = function( file ) {
console.log( `putObject call!!!!` )
return s3.upload( file.params ).promise();
};

let getFiles = function( parts ) {
//let fileExt = 'png'
let files = [];
parts.forEach( part => {
let hash = sha1( new Buffer( new Date().toString() ) );

let buffer = part.data

let filePath = hash + '/';

let fileName = part.filename
let fileFullName = filePath + fileName;

let filefullPath = '버킷URL' + fileFullName;

let params = {
Bucket: '버킷명',
Key: fileFullName,
Body: buffer
};

let uploadFile = {
size: buffer.toString( 'ascii' ).length,
type: part.type,
name: fileName,
full_path: filefullPath
};

files.push( { params, uploadFile } )
} );
return files
}

index.js에 모든 소스를 작성했다면, 저장을 한 뒤 upload 폴더 하위에 있는

  • index.js
  • node_modules
들을 zip 형식으로 압축합니다.


압축 후 다시 Lambda 콘솔창으로 이동하여 코드입력유형을 zip파일 형식 업로드를 체크하시고 해당 zip 파일을 업로드 한 뒤 저장하시면 Lamba함수 생성은 모두 완료되었습니다. 

이제 다음 포스팅에서 API Gateway 설정을 마치고 이번 포스팅에서 작성한 Lambda함수를 연결하여 파일업로드를 구현해보겠습니다. 

감사합니다.