파일 서버 s3 사용하기 (aws sdk v2)

Yi Kanghoon·2022년 12월 25일
2

개요

기존의 file.service.ts관련 구조(dynamic module)를 유지하면서 aws s3를 파일 서버로 사용하고자 함.

// /src/config/file/s3/client.module.ts 일부

case FileClientType.S3:
        return {
          module: FileConfigModule,
          providers: [
            {
              provide: FILE_CLIENT_SERVICE,
              useClass: S3ClientService,
            },
          ],
          exports: [FILE_CLIENT_SERVICE],
        };
// /src/config/file/s3/client.service.ts

import { BadRequestException, Injectable } from "@nestjs/common";
import { FileClientService } from "../client.service";
import { ConfigService } from "@nestjs/config";
import * as AWS from "aws-sdk";

@Injectable()
export class S3ClientService implements FileClientService {
  private readonly S3: AWS.S3;
  private readonly bucket: string;

  constructor(private readonly configService: ConfigService) {
    AWS.config.update({
      credentials: {
        accessKeyId: configService.get("S3_ACCESS_KEY"),
        secretAccessKey: configService.get("S3_SECRET_KEY"),
      },
      region: configService.get("S3_BUCKET_REGION"),
    });
    this.S3 = new AWS.S3();
    this.bucket = this.configService.get("S3_BUCKET_NAME");
  }

  async uploadFile(
    key: string,
    file: Buffer,
    size: number,
    createdAt: Date,
    originalName: string,
    mimeType: string
  ) {
    const metaData = {
      "Content-Type": mimeType,
      createdAt: createdAt.toUTCString(),
      originalName: encodeURI(originalName),
    };

    try {
      await this.S3.putObject({
        Bucket: `${this.bucket}/files`,
        Key: key,
        Body: file,
        ContentType: mimeType,
        Metadata: metaData,
      }).promise();
    } catch (err) {
      throw new BadRequestException(err.message);
    }
  }

  async getFile(key: string) {
    try {
      return await this.S3.getObject({
        Bucket: `${this.bucket}/files`,
        Key: key,
      }).createReadStream();
    } catch (err) {
      throw new BadRequestException(err.message);
    }
  }

  async removeFile(key: string) {
    try {
      return await this.S3.deleteObject({
        Bucket: `${this.bucket}/files`,
        Key: key,
      }).createReadStream();
    } catch (err) {
      throw new BadRequestException(err.message);
    }
  }
}

실수했던 부분들

  1. s3관련 method를 사용할때 Bucket 속성의 의미는 파일이 위치할 디렉토리(?)까지를 의미하는데 모두 /files를 빼먹어서 버킷이 존재하지 않는다는 오류를 뱉어냄.
  2. (너무 사소하긴 한데) 파일을 업로드하기 위함 IAM 사용자와 디플로이를 위한 사용자 키, 시크릿 키를 교차해서(...)사용해서 access 문제 발생.
  3. 파일 스트림을 읽기 위한 createReadStream을 추가하지 않아서 타입 에러 발생

후기

aws-sdk v3이 있지만 현재 구조에 어떻게 적용시켜야 할 지 잘 이해가 되지 않아서(...)일단 v2를 사용했는데, v3로 마이그레이션이 가능하면 시도해보는 것도 좋을 듯.

profile
Full 'Snack' Developer

0개의 댓글