프로젝트를 진행하면서 Multer를 이용해 이미지를 다루고 해당 이미지를 S3에 업로드하는 기능을 구현했는데 복습하면서 정리해 보도록 하겠다
AWS S3를 먼저 설정하자
AWS에 접속해서 S3를 찾아 들어가서 버킷을 생성하자
버킷 이름을 지정하고 AWS 리전을 잘 선택하자
객체 소유권은 기본설정에서 건드리지 말자
퍼블릭 엑세스 차단을 풀어준다 따로 버킷 정책에서 접근 제한을 걸기 때문에 걱정하지 말자
생성한 버킷을 선택하고 권한을 설정해 보자
버킷 정책을 생성해 보자
버킷 ARN을 복사해 두시고 정책 생성기로 이동하자
1, 2, 3을 설정하고 4번 Actions에서 PutObject와 GetObject를 선택한다 읽기 권한, 수정 권한을 허용할 수 있게 해 준다
선택 사항들을 확인하고 정책을 만들자
정책이 만들어지면 복사해 두자
Resource에서다가 /*을 꼭 추가해 주자
버킷 내의 모든 객체에 대한 엑세스 권한이 적용된다는 설정이다
이제 IAM을 만들자 사용자를 들어가서 사용자를 추가하자
이름을 정하고 사용자 지정 암호를 지정하자
직접 정책 연결을 선택하고 S3Full을 검색해 선택한다
검토하고 넘어간다
.CSV파일을 꼭 챙겨두자
만든 사용자를 선택하고 보안 자격 증명 탭에서 엑세스 키를 만들자
aws-sdk를 사용하기 위해 엑세스 키가 필요하다
CSV 파일을 꼭 챙기도록 하자
AWS S3를 이용하기 위한 세팅은 끝이 났다
이제 코드에 적용시켜보자
aws-sdk를 사용하기 위해서 패키지를 설치한다
npm install @aws-sdk/client-s3 --save
s3를 사용하기 위해 class를 만들자
import { ConfigService } from '@nestjs/config';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { Injectable } from '@nestjs/common';
import sharp from 'sharp';
import * as _ from 'lodash';
@Injectable()
export class S3Service {
private readonly client: S3Client;
private readonly region: string = this.configService.get<string>('AWS_BUCKET_REGION') || '';
private readonly bucket: string = this.configService.get<string>('AWS_BUCKET_NAME') || '';
constructor(private readonly configService: ConfigService) {
this.client = new S3Client({
region: this.region,
credentials: {
accessKeyId: this.configService.get<string>('AWS_ACCESS_KEY_ID') || '',
secretAccessKey: this.configService.get<string>('AWS_SECRET_ACCESS_KEY') || '',
},
});
}
async putObject(image: any) {
const sharpImage = sharp(image.path);
let {width, height} = await sharpImage.metadata();
if (_.isUndefined(width)) {
width = 1;
}
if (_.isUndefined(height)) {
height = 1;
}
const maxWidth = 800;
const maxHeight = 600;
const ratio = Math.min(maxWidth / width, maxHeight / height);
await this.client.send(
new PutObjectCommand({
Bucket: this.bucket,
Key: image.filename,
Body: await sharpImage.resize(Math.round(width * ratio), Math.round(height * ratio)).toBuffer(),
ContentType: image.mimetype,
})
);
return `https://${this.bucket}.s3.${this.region}.amazonaws.com/${image.filename}`;
}
}
생성했던 버켓정보와 IAM 엑세스 키를 환경변수에 지정해 두고 가져다가 사용한다
생성한 client에 send 메서드를 사용해서 버킷에 객체를 업로드하는 명령 PutObjectCommand를 호출한다
그리고 속성을 채워 넣으면 S3에 업로드가 된다
photospot.module로 가서 S3Service를 사용할 수 있게 의존성 주입을 한다
@Module({
imports: [
MulterModule.registerAsync({
imports: [ConfigModule],
useFactory: multerOptionsFactory,
inject: [ConfigService],
}),
TypeOrmModule.forFeature([Photospot, Collection, Photo, PhotoKeyword]),
],
controllers: [PhotospotController],
providers: [PhotospotService, S3Service, GoogleVisionService],
})
photospot.service로 가보자
async createPhotospot(
createPhtospotDto: CreatePhotospotDto,
files: Express.Multer.File[],
userId: number,
collectionId: number
): Promise<void> {
const collection = await this.collectionRepository.findOne({ where: { id: collectionId } });
if (_.isNil(collection)) {
throw new NotFoundException('해당 콜렉션을 찾을 수 없습니다.');
}
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const { title, description, latitude, longitude }: CreatePhotospotDto = createPhtospotDto;
const photospot = await queryRunner.manager
.getRepository(Photospot)
.insert({ title, description, latitude, longitude, userId, collectionId });
for (const file of files) {
try {
const image = await this.s3Service.putObject(file);
const photo = await queryRunner.manager
.getRepository(Photo)
.insert({ image, userId, photospotId: photospot.identifiers[0].id });
this.createImageKeyword(image, photo.identifiers[0].id);
} catch (error) {
console.log(error);
throw new Error('Photo 입력 실패.');
}
}
await queryRunner.commitTransaction();
this.isSafePhoto(photospot.identifiers[0].id);
} catch (error) {
console.log(error);
await queryRunner.rollbackTransaction();
throw new BadRequestException('요청이 올바르지 않습니다.');
} finally {
await queryRunner.release();
}
}
Multer로 처리한 여러 장의 이미지를 S3에 업로드하고 image주소를 반환받고 DB에 저장한다
'과거공부모음' 카테고리의 다른 글
TypeORM 추진 추천 쿼리 (0) | 2023.04.02 |
---|---|
Nest.js에서 Google Vision API 사용하기 (0) | 2023.04.01 |
Nest.js에서 Multer를 이용해 여러 장의 이미지 파일 관리 (0) | 2023.04.01 |
20230324 TIL - 사진 리사이징 (0) | 2023.03.25 |
20230321 TIL - 구글 비전을 이용한 이미지 라벨링 (0) | 2023.03.21 |