[Serverless] S3 업로드

홍준·2021년 10월 24일
2
post-thumbnail

서론

이번 중점 업무는 Storage Gateway를 이용하여 마운트 방식으로 업로드 되고 있는 서비스를 AWS SDK 이용하여 S3로 직접 업로드 할 수 있도록 업로드 방식을 변경하는 작업을 진행하고 있다.

큰 문제가 없을 것으로 생각했지만, 서버에서 직접 S3 버킷에 업로드를 하면 서버 쪽에서 multipart 파일을 쥐고 있어야 하는 리소스 낭비와 CPU 사용량이 많아지는 것을 확인하게 되었다.

만약, 여러 회원이 동시에 파일을 올리게 된다면 서버에 부담될 수 있을 것으로 판단되어
서버리스를 이용하여 S3에 직접 파일 업로드 하도록 작업해보려고 한다.


서버리스 파일 업로드 아키텍처

서버리스 기반으로 S3 업로드 하는 경우 아래 두 개의 단계로 구성이 된다.

  1. 사용자가 업로드 시 Amazon API Gateway를 호출, 트리거가 걸린 Lambd를 실행시켜
    S3 Presigned URL을 얻는다.

  2. 애플리케이션에서 S3 Presigned URL로 파일을 직접 업로드 한다.


Lambda 생성하기

API Gateway 트리거 추가

우선 Lambda에 API Gateway 트리거를 추가 해보자.

트리거 구성은 '새 API 생성'을 선택한다.
보안은 'AWS IAM'과 'API 키', 그리고 '열기'가 있는데 '열기'는 API 주소만 있으면 누구나 호출 가능하니 웬만하면 하지 않는걸 추천한다.

Lambda 실행 코드

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을 사용하려고 한다.

1. API Gateway 호출하기

  • 생성한 API Gateway 엔드포인트를 복사하여 호출한다.
  • 요청이 완료되면 Body 섹션에 JSON 응답이 표시되는데 uploadUrl 속성에 서명된 URL이 있다.

2. Presigned URL 로 파일 업로드 하기

  • 호출 메소드를 GET에서 PUT으로 변경 후 앞서 리턴받은 uploadUrl 복사하여 요청 URL 입력 상자에 붙여 넣는다.
  • 업로드할 파일을 선택 후 Send를 클릭한다.
  • 요청 후 200 OK 응답이 나오는지 확인한다.

3. 업로드 파일 확인하기

  • S3 콘솔로 이동하여 Postman을 통해 업로드된 파일이 정상 업로드 되었는지 확인한다.
  • 확인 완료 👏

정리

서버리스 기법을 통해 파일을 업로드할 수 있도록 함으로써, 서버에 부담을 덜고, 네트워크 부하를 분산시켜 줌으로 애플리케이션을 훨씬 더 안전하게 운영할 수 있을 것으로 생각한다.✌

profile
어제의 나를 이기자 🔥

0개의 댓글