이번 중점 업무는 Storage Gateway를 이용하여 마운트 방식으로 업로드 되고 있는 서비스를 AWS SDK 이용하여 S3로 직접 업로드 할 수 있도록 업로드 방식을 변경하는 작업을 진행하고 있다.
큰 문제가 없을 것으로 생각했지만, 서버에서 직접 S3 버킷에 업로드를 하면 서버 쪽에서 multipart 파일을 쥐고 있어야 하는 리소스 낭비와 CPU 사용량이 많아지는 것을 확인하게 되었다.
만약, 여러 회원이 동시에 파일을 올리게 된다면 서버에 부담될 수 있을 것으로 판단되어
서버리스를 이용하여 S3에 직접 파일 업로드 하도록 작업해보려고 한다.
서버리스 기반으로 S3 업로드 하는 경우 아래 두 개의 단계로 구성이 된다.
사용자가 업로드 시 Amazon API Gateway를 호출, 트리거가 걸린 Lambd를 실행시켜
S3 Presigned URL을 얻는다.
애플리케이션에서 S3 Presigned URL로 파일을 직접 업로드 한다.
우선 Lambda에 API Gateway 트리거를 추가 해보자.
트리거 구성은 '새 API 생성'을 선택한다.
보안은 'AWS IAM'과 'API 키', 그리고 '열기'가 있는데 '열기'는 API 주소만 있으면 누구나 호출 가능하니 웬만하면 하지 않는걸 추천한다.
Presigned UR 은 아래의 코드를 통해 생성하게 된다.
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
accessKeyId: process.env.ACCESS_KEY_ID,
secretAccessKey: process.env.SECRET_ACCESS_KEY,
region: process.env.BUCKET_REGION,
signatureVersion: "v4"
});
const URL_EXPIRATION_SECONDS = 300
exports.handler = async (event) => {
return await getUploadURL(event);
};
const getUploadURL = async function(event) {
const randomID = parseInt(Math.random() * 10000000);
const Key = `${randomID}.jpg`;
const s3Params = {
Bucket: process.env.BUCKET_NAME,
Key,
Expires: URL_EXPIRATION_SECONDS,
ContentType: 'image/jpeg'
}
const uploadURL = await S3.getSignedUrlPromise('putObject', s3Params);
return JSON.stringify({
uploadURL: uploadURL,
Key
})
}
빠르게 기능 테스트를 하기 위하여 Postman을 사용하려고 한다.
서버리스 기법을 통해 파일을 업로드할 수 있도록 함으로써, 서버에 부담을 덜고, 네트워크 부하를 분산시켜 줌으로 애플리케이션을 훨씬 더 안전하게 운영할 수 있을 것으로 생각한다.✌