NestJS는 Express를 기반으로 만들어진 프레임워크로서, 파일 업로드 기능을 제공하는 내장 모듈을 통해 AWS S3에 손쉽게 파일을 업로드할 수 있습니다. 이 블로그에서는 Multer를 사용하여 파일을 업로드하고, AWS SDK를 활용하여 S3에 파일을 저장하는 방법을 단계별로 안내하겠습니다.
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);
},
}),
)
AWS S3를 통해 파일을 업로드하려면 aws-sdk
패키지를 설치합니다.
npm install aws-sdk
AWS 접근 키와 비밀 키를 안전하게 숨기기 위해 .env
파일을 사용하고 환경 변수를 관리합니다.
.env.dev (예시)
AWS_ACCESS_KEY=YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_ACCESS_KEY
환경 변수를 검증하고 불러오기 위해 ConfigModule
과 Joi
를 사용합니다.
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';
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를 사용하여 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
: 이 모듈이 제공하는 컨트롤러를 지정합니다.AWS IAM을 통해 프로그래밍 방식으로 액세스할 수 있는 사용자를 추가하고 필요한 권한을 부여합니다.
AWS IAM 콘솔에서 사용자 추가:
프로그래밍 방식 액세스
체크AmazonS3FullAccess
정책 연결액세스 키 및 비밀 키 생성:
.env.dev
에 추가S3 버킷 생성:
ACL 설정:
퍼블릭 읽기
권한 활성화AWS SDK에서 특정 리전을 설정하려면 아래와 같이 코드를 작성합니다.
AWS.config.update({ region: 'ap-northeast-2' });
이 글에서는 Multer를 사용하여 파일 업로드를 처리하고, AWS SDK를 통해 S3에 파일을 저장하는 방법을 알아보았습니다. NestJS와 AWS S3를 결합하여 간단하면서도 확장 가능한 파일 업로드 기능을 구현할 수 있습니다.
FileInterceptor
와 함께 Multer를 사용하여 파일 업로드를 처리합니다.