본문 바로가기

과거공부모음

20230227 TIL - 최종프로젝트 (찰칵), nestjs-form-data

Today I learned

팀프로젝트 찰칵 포토스팟 등록 작업

포토스팟 등록하는 작업을 진행했다

S3에 이미지를 업로드 해야하기 때문에 S3 Client 세팅을 먼저 진행하는데 문제가 발생했다

configService를 이용하면 string 또는 undefinde가 반환이 되는데 accessKeyId와 secretAccessKey는 string 타입만 허용한다 위에 내가 지정한 타입은 ?:를 이용해서 해결하면 되는 부분이지만 저 두가지는 S3Client에서 지정해둔 타입이라서 사용할 수 없었다 이 문제를 해결하는 방법은

tsconfig.js에 가서 "strictNullChecks": false 옵션을 사용하면 해결이 가능하다

// tsconfig.js
{
  "compilerOptions": {
			// 생략
     "strictNullChecks": false
  }
}

하지만 이번에는 팀 프로젝트이기 때문에 최대한 기본 프로젝트 환경을 바꾸려고 하지 않는다

그래서 해결 방법으로 사용한 방식을 보자

// s3.service.ts
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') || '',
      },
    });
  }

|| 연산자를 사용해서 configService에서 반환값이 undefinde가 반환이 되면 빈 문자열을 넣어주어 해결했다

S3를 세팅하고 이제 formdata를 받아와서 이미지는 업로드 하고 나머지 정보들은 데이터베이스에 넣어보도록 하자 formdata를 받을 때 유효성 검사를 먼저 진행해보자

import { FileSystemStoredFile } from 'nestjs-form-data/dist/classes/storage';
import { IsNotEmpty, IsNumberString, IsString } from 'class-validator';
import { IsFile, HasMimeType } from 'nestjs-form-data/dist/decorators';

export class CreatePhotospotDto {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsNotEmpty()
  @IsString()
  description: string;

  @IsNotEmpty()
  @IsNumberString()
  latitude: number;

  @IsNotEmpty()
  @IsNumberString()
  longitude: number;

  @IsNotEmpty()
  @IsFile()
  @HasMimeType(['image/jpeg', 'image/png'])
  image: FileSystemStoredFile;
}

IsFile과 HasMimeType을 이용해서 이미지의 유효성 검사를 진행한다 그렇게 하기 위해서

formdata를 multer를 이용해서 이미지를 처리하지 않고 nestjs-form-data 패키지를 이용해서

이미지를 처리하도록 하자

npm install -save nestjs-form-data

photospot.controller로 가보자

@Post()
@FormDataRequest()
createPhotospot(@Body() createPhtospotDto: CreatePhotospotDto): void {
  this.photospotService.createPhotospot(createPhtospotDto)
}

photospot.service로 가보자

async createPhotospot({ title, description, latitude, longitude, image }: CreatePhotospotDto): Promise<void> {
    const imagePath = await this.s3Service.putObject(image);
    this.photospotRepository.insert({ title, description, latitude, longitude, imagePath, userId: 1, collectionId: 1 });
  }

이런식으로 진행을 했다

코드를 작성하고 테스트를 진행하는데 문제가 발생했다

nestjs-form-data를 이용해서 임시로 저장한 이미지가 찾을 수 없다는 에러가 발생했다

이 문제를 해결하기 위해서 photospot.module로 가보자

NestjsFormDataModule.config({
      storage: FileSystemStoredFile,
      autoDeleteFile: false,
    }),

autoDeleteFile이 true일 경우 s3Service에서 S3로 저장하기 전에 이미지가 자동으로 삭제가 되어버린다 그래서 이미지를 찾을 수 없던 것이다 그래서 false로 바꾸면 자동 삭제가 취소되기 때문에 문제없이 이미지가 S3로 업로드 진행한다 그리고 반환 받은 imagePath를 이용해서 데이터베이스에 photospot정보를 insert하면 정상적으로 작동한다!