쿠팡이츠 AWS S3에 파일 업로드 하기

shooting star·2024년 5월 10일
1
post-thumbnail

들어가며

NestJS는 Express를 기반으로 만들어진 프레임워크로서, 파일 업로드 기능을 제공하는 내장 모듈을 통해 AWS S3에 손쉽게 파일을 업로드할 수 있습니다. 이 블로그에서는 Multer를 사용하여 파일을 업로드하고, AWS SDK를 활용하여 S3에 파일을 저장하는 방법을 단계별로 안내하겠습니다.

파일 업로드를 위한 NestJS 환경 설정

Multer를 사용한 파일 업로드

NestJS는 Express용 Multer 미들웨어를 내장 모듈로 제공하며, 이 모듈은 multipart/form-data 형식으로 게시된 데이터를 처리합니다. Multer 모듈을 사용하려면 먼저 관련 패키지를 설치합니다.

npm install @nestjs/platform-express
npm install -D @types/multer

FileInterceptor를 사용하여 간단하게 파일을 처리할 수 있습니다. 파일 필터링과 한글 파일 이름 깨짐 방지를 위해 다음과 같이 작성합니다.

@UseInterceptors(
  FileInterceptor('file', {
    fileFilter: (req, file, cb) => {
      file.originalname = Buffer.from(file.originalname, 'latin1').toString(
        'utf8',
      );
      cb(null, true);
    },
  }),
)

S3에 파일을 업로드하는 방법

AWS S3를 통해 파일을 업로드하려면 aws-sdk 패키지를 설치합니다.

npm install aws-sdk

AWS 자격증명을 숨기기 위한 .env 파일 설정

AWS 접근 키와 비밀 키를 안전하게 숨기기 위해 .env 파일을 사용하고 환경 변수를 관리합니다.

.env 파일 작성

.env.dev (예시)

AWS_ACCESS_KEY=YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_ACCESS_KEY

환경 변수 검증을 위한 ConfigModule 설정

환경 변수를 검증하고 불러오기 위해 ConfigModuleJoi를 사용합니다.

npm install @nestjs/config joi

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
import { UploadsModule } from './uploads/uploads.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env.dev',
      validationSchema: Joi.object({
        AWS_ACCESS_KEY: Joi.string().required(),
        AWS_SECRET_ACCESS_KEY: Joi.string().required(),
      }),
    }),
    UploadsModule,
  ],
})
export class AppModule {}

글로벌 모듈에서 PubSub 의존성 주입 및 공유

NestJS의 글로벌 모듈 기능을 사용하여 PubSub 인스턴스를 모든 모듈에서 사용할 수 있도록 공유합니다.

common.module.ts

import { Global, Module } from '@nestjs/common';
import { PubSub } from 'graphql-subscriptions';
import { PUB_SUB } from './common.constants';

const pubsub = new PubSub();

@Global()
@Module({
  providers: [
    {
      provide: PUB_SUB,
      useValue: pubsub,
    },
  ],
  exports: [PUB_SUB],
})
export class CommonModule {}

common.constants.ts

export const PUB_SUB = 'PUB_SUB';
export const NEW_PENDING_ORDER = 'NEW_PENDING_ORDER';

S3 버킷 생성 및 파일 업로드 컨트롤러 구현

S3 버킷 생성

AWS S3에서 버킷을 생성할 때, 버킷 이름은 소문자만 사용해야 합니다. 이를 위해 아래와 같이 버킷을 생성합니다.

const BUCKET_NAME = 'your-bucket-name';

async function createBucket() {
  const s3 = new AWS.S3();
  try {
    const result = await s3.createBucket({ Bucket: BUCKET_NAME }).promise();
    console.log('Bucket Created Successfully:', result);
  } catch (error) {
    console.error('Error Creating Bucket:', error);
  }
}

버킷 이름에 대문자나 특수문자를 사용하면 안됩니다.

AWS SDK 설정 및 파일 업로드 컨트롤러 구현

AWS SDK를 사용하여 S3 버킷에 파일을 업로드하는 컨트롤러를 구현합니다. FileInterceptor를 사용해 파일을 처리하고, 업로드한 파일의 URL을 클라이언트에 반환합니다.

uploads.controller.ts

import {
  Controller,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import * as AWS from 'aws-sdk';

const BUCKET_NAME = 'your-bucket-name';

@Controller('uploads')
export class UploadsController {
  @Post('')
  @UseInterceptors(
    FileInterceptor('file', {
      fileFilter: (req, file, cb) => {
        // 한글 파일 이름 깨짐 방지
        file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8');
        cb(null, true);
      },
    }),
  )
  async uploadFile(@UploadedFile() file: Express.Multer.File) {
    // AWS S3에 접근하기 위해 자격증명과 리전을 설정합니다.
    AWS.config.update({
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      },
      region: 'ap-northeast-2', // 한국 리전
    });

    try {
      const objectName = `${Date.now()}_${file.originalname}`; // 파일 이름에 현재 시간 첨부
      await new AWS.S3()
        .putObject({
          Body: file.buffer, // 파일의 버퍼 데이터를 Body에 지정
          Bucket: BUCKET_NAME, // 버킷 이름
          Key: objectName, // 버킷 내에 저장될 파일 이름
          ACL: 'public-read', // 파일에 대한 공개 읽기 권한 설정
        })
        .promise(); // 비동기 작업을 기다림

      // 파일에 접근할 수 있는 URL 생성
      const url = `https://${BUCKET_NAME}.s3.amazonaws.com/${objectName}`;
      return { url }; // URL을 클라이언트에 반환
    } catch (error) {
      console.error(error);
      return null; // 업로드 실패 시 null 반환
    }
  }
}

코드 설명:

  • @Controller: 이 클래스가 NestJS의 컨트롤러임을 나타냅니다.
  • @Post: HTTP POST 요청을 처리하기 위해 사용됩니다.
  • FileInterceptor: Multer 미들웨어를 사용하여 파일을 처리합니다.
    • fileFilter: 한글 파일 이름이 깨지지 않도록 변환합니다.
  • AWS.config.update: AWS 자격증명과 리전을 설정합니다.
  • putObject:
    • Body: 파일의 버퍼 데이터를 저장합니다.
    • Bucket: 업로드할 버킷 이름을 지정합니다.
    • Key: 버킷 내에 저장될 파일 이름을 지정합니다.
    • ACL: 파일에 대한 접근 권한을 설정합니다.

파일 업로드 모듈 구현

파일 업로드를 위한 모듈을 구현합니다.

uploads.module.ts

import { Module } from '@nestjs/common';
import { UploadsController } from './uploads.controller';

@Module({
  controllers: [UploadsController],
})
export class UploadsModule {}

코드 설명:

  • @Module: NestJS 모듈을 정의합니다.
  • controllers: 이 모듈이 제공하는 컨트롤러를 지정합니다.

참고 사항

  • S3 버킷 권한: 업로드한 파일에 접근하기 위해선 버킷에 대한 권한 설정이 필요합니다.
    • AWS 콘솔에서 퍼블릭 읽기 권한을 활성화해야 합니다.
  • 리전 설정: S3 버킷이 존재하는 리전과 일치해야 합니다.
  • 에러 처리: 업로드 중 발생하는 오류를 정확하게 로깅하고 반환하는 것이 중요합니다.

AWS S3 설정 및 접근 권한 구성

IAM 사용자 생성 및 S3 권한 부여

AWS IAM을 통해 프로그래밍 방식으로 액세스할 수 있는 사용자를 추가하고 필요한 권한을 부여합니다.

  1. AWS IAM 콘솔에서 사용자 추가:

    • 프로그래밍 방식 액세스 체크
    • AmazonS3FullAccess 정책 연결
  2. 액세스 키 및 비밀 키 생성:

    • 생성된 키를 .env.dev에 추가

S3 버킷 설정 및 리전 구성

  1. S3 버킷 생성:

    • 버킷 이름은 모두 소문자로 작성해야 하며, 대문자 및 특수문자 사용 불가
  2. ACL 설정:

    • 버킷 ACL에서 퍼블릭 읽기 권한 활성화

AWS SDK 리전 설정

AWS SDK에서 특정 리전을 설정하려면 아래와 같이 코드를 작성합니다.

AWS.config.update({ region: 'ap-northeast-2' });

마치며

이 글에서는 Multer를 사용하여 파일 업로드를 처리하고, AWS SDK를 통해 S3에 파일을 저장하는 방법을 알아보았습니다. NestJS와 AWS S3를 결합하여 간단하면서도 확장 가능한 파일 업로드 기능을 구현할 수 있습니다.

  1. Multer 설정: FileInterceptor와 함께 Multer를 사용하여 파일 업로드를 처리합니다.
  2. AWS S3 설정: 환경 변수로 접근 자격 증명을 안전하게 저장하고, 버킷을 생성 및 구성합니다.
  3. 파일 업로드: AWS S3에 파일을 업로드하는 로직을 컨트롤러에 구현합니다.

0개의 댓글