항해99/TIL

20230627 TIL Nestjs에서 S3로 이미지 업로드하기

공대루루 2023. 6. 27. 22:36

어제 파일 업로드를 위해 S3로 버켓도 만들고 IAM 사용자와 엑세스키도 발급 받았다!! 그럼 이제 nest js 에서 이미지 업로드를 위한 라이브러리를 설치하고 코드를 작성해야 한다.

npm i @types/multer aws-sdk

1. controller

컨트롤러에서 @UseInterceptors() 데코레이터를 사용해서 요청받은 파일을 받아온다. 이때 요청 파일의 key 값을 FileInterceptor() 안에 넣어준다. 나는 프론트에서 Image라는 키값으로 보내주기 때문에 @UseInterceptors(FileInterceptor('Image')) 라고 작성해주었다. 

@Post()
@UseInterceptors(FileInterceptor('Image'))
async uploadFile(@UploadedFile() Image: Express.Multer.File): Promise<object> {
    //업로드 파일정보
    const bucketName = configService.get('AWS_BUCKET_NAME');
    const key = Image.originalname;
    const fileData = Image.buffer;

    return this.fundingService.createFunding(
      bucketName,
      key,
      fileData,
    );
}

function 이름은 무조건 uploadFile로 해야한다. 다른걸로 해보려고 했는데 바꾸라는 에러 메세지가 발생했다. Image를 콘솔로 찍어보면 여러 데이터가 들어가 있는데 여기서 key값과 buffer 값을 이용해서 s3에 저장할 때 사용할 것이다. 이때 bucketName에 들어가는 값은 S3에서 생성해둔 버켓의 이름이다. 

2. service

서비스 계층에서는 먼저 aws-sdk 에서 S3를 import 해주어야 한다.

import { S3 } from 'aws-sdk';

S3에 저장이 완료되면 db에도 정보를 저장해두어야 하기 때문에 Resource entity를 인젝트 해둔다. constructor 생성자 내부에 AWS 인증 정보를 설정해주어야 한다. 나는 어쩌다보니 S3의 region이 글로벌로 설정이 되어 있어서 region:null로 해두었지만 글로벌로 되어있지 않을 때에는 각 region에 맞는 값을 입력해주어야 한다.

export class FundingService {
  private s3: S3;
  constructor(
    @InjectRepository(Resource)
    private accountRepository: Repository<Resourc>,
  ) {
    // AWS 인증 정보 설정
    this.s3 = new S3({
      accessKeyId: configService.get('AWS_ACCESS_KEY'),
      secretAccessKey: configService.get('AWS_SECRET_KEY'),
      region: null, // AWS S3 버킷이 위치한 리전
    });
  }

이제 모든 설정에 관련된 것들은 다 끝났다!! 실제 S3에 업로드 하는 부분의 코드는 아래에 있다. 컨트롤러 계층에서 입력받은 bucketname과 key, buffer를 객체로 만든 후 upload() 를 사용해서 업로드해주면 끝이다! 

  async createFunding(
    bucketName: string,
    key: string,
    fileData: Buffer,
  ): Promise<object> {
  
    //s3 업로드
    const uploadParams = {
      Bucket: bucketName,
      Key: key,
      Body: fileData,
    };
    const uploadResult = await this.s3.upload(uploadParams).promise();
}

nest.js에서 s3사용하는 방법이 node.js에서 사용하는 방법보다 더 간단한 것 같다.