[Nestjs] S3 PreSignedUrl 발급

Eden·2023년 11월 14일
0

클라이언트가 앱을 이용해 이미지를 업로드 하게되면 해당 이미지를 s3 buket에 저장해야한다.
앱에서 다이렉트로 s3로 접근하여 데이터를 생성하게 되면 보안에 큰 문제가 될 수 있으며 상대적으로 큰 이미지 데이터를 서버로 보내 처리한다는 것이 내키지않는다.
따라서 클라이언트가 서버에게 일정시간동안 데이터를 쓸 수 있는 권한이 주어진 url을 발급받아 데이터를 업로드하는 방식을 사용하게 되었다. (서버에서 정해준 url이며 유효기간이 만료되면 데이터는 생성되지 않는다)

  1. 클라이언트가 서버에게 이미지 업로드하기 위한 url을 요청합니다.
  2. 서버에서 적당한 url을 정하고 해당 url을 쓰기 권한이 부여된 presignedUrl형태로 클라이언트에게 넘겨준다. 이때 서버에서 정한 url도 함께 넘겨준다.

코드

//aws-config.ts

import { ConfigService } from '@nestjs/config';
import { S3Client } from '@aws-sdk/client-s3';

let s3;
let s3BucketUrl;

//해당 이니셜라이즈를 필자는 app이 구동되는 시점(main.ts)에서 적용하였다.
export function initializeAWS(configService: ConfigService) {
  //s3 관련 필요한 키값
  const awsAccessKey = configService.get('AWS_ACCESS_KEY'); 
  const awsSecretKey = configService.get('AWS_SECRET_KEY');
  s3BucketUrl = configService.get('AWS_S3_BUCKET_URL');
  s3 = new S3Client({
    region: 'ap-northeast-2',
    credentials: {
      accessKeyId: awsAccessKey,
      secretAccessKey: awsSecretKey,
    },
  });
}

export { s3, s3BucketUrl };

AccessKey와 SecretKey는 aws IM에서 사용자를 추가하여 S3 서비스 및 필요한 권한을 등록한 다음 액세스키 생성을 통해 공급받은 값들을 사용하면 된다.

import { s3, s3BucketUrl } from 'src/aws-config'; 
import { UploadImgDto } from 'src/user/dto/upload-image.dto';
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

export const getSignedUrlFunction = async (
  key: string,
): Promise<UploadImgDto> => {
  const params = {
    Bucket: 'xx-xx-bucket', //준비한 bucket

    Key: `${key}`,
    ContentType: 'image/jpeg',
  };

  const command = new PutObjectCommand(params); 
  //put은 쓰기, get은 읽기? 저장?, 공식 문서에 따르면 다양한 기능들이 있다.
  const url = await getSignedUrl(s3, command, { expiresIn: 3600 });

  return new UploadImgDto(url, `${s3BucketUrl}/${key}`);
};

이렇게 준비해주고 적용할 api에 가져다 쓰면된다.

다음과 같은 return값을 보내준다.

PS. ec2에 처음 작성한 코드가 build가 되지 않는 현상이 있어 고생을 했었는데 원인은

import * as AWS from 'aws-sdk'; 

이 코드이다 로컬에서는 발견되지 않지만 ec2에서 위 코드는 문제를 발생시킨다. ec2가 aws서비스라 그런가... 잘 모르겠다...

profile
주섬주섬..

0개의 댓글