๐Ÿ“Today I Learned

[TIL] nest : Global Exception Filter / ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ service๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ค‘ ์ข…์†์„ฑ ๋ฌธ์ œ / nest : form-data / nest : form-data boolean ์ด ํ•ญ์ƒ true๋กœ ๋ณด๋‚ด์ง€๋Š” ๋ฌธ์ œ

์•„2 2023. 8. 24. 02:32

โœ… ํ•œ ์ผ

-nest : global Catch ์ ์šฉ

-ํšŒ์›๊ฐ€์ž… S3 ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€, ์‚ฌ์šฉ์ž/๊ด€๋ฆฌ์ž ์—ฌ๋ถ€ ํ™•์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€, ํ”„๋ก ํŠธ ์—ฐ๊ฒฐ ์™„๋ฃŒ


โ˜‘๏ธ ๊ธฐ๋ก

๋ชฉ์ฐจ

[nest : Global Exception Filter]
[๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ service๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ค‘ ์ข…์†์„ฑ ๋ฌธ์ œ]
[nest : form-data]
[nest : form-data boolean ์ด ํ•ญ์ƒ true๋กœ ๋ณด๋‚ด์ง€๋Š” ๋ฌธ์ œ]

 


[nest: Global Exception Filter]

์ง€๊ธˆ๊นŒ์ง€๋Š” try, catch๋ฌธ์œผ๋กœ ์—๋Ÿฌ ํ•ธ๋“ค๋ง, ์‘๋‹ต์„ ํ–ˆ๋Š”๋ฐ ํŒ€์›๊ฐ„ ์ฝ”๋“œ ์ผ๊ด€์„ฑ์ด ์—†๊ณ  ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์ ธ์„œ Global Exception Filter์„ ์„ค์ •ํ•ด๋‘๋ ค๊ณ  ํ•œ๋‹ค.

-@Catch() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์™€ ExceptionFilter ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด ์˜ˆ์™ธ ์œ ํ˜•์„ ์บ์น˜ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•จ

-๊ธฐ์กด ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•œ ์—๋Ÿฌ๊ฐ€ ์žˆ์„์‹œ, ํ•ด๋‹น ์—๋Ÿฌ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋งŒ์•ฝ ์—†์„ ์‹œ์—๋Š” 500 ์„œ๋ฒ„์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

// global-catch.exception.ts
import {
  Catch,
  ExceptionFilter,
  ArgumentsHost,
  HttpException,
  HttpStatus,
} from '@nestjs/common';

@Catch()
export class GlobalCatchException implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    const message =
      exception instanceof HttpException
        ? exception.message
        : '์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.';

    const isError: boolean = status <= 400;

    console.error(exception);

    response.status(status).json({
      status: isError,
      statusCode: status,
      message: message,
    });
  }
}

 

// main.ts

  //-- ๊ธ€๋กœ๋ฒŒ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ --//
  app.useGlobalFilters(new GlobalCatchException()); // try, catch๋ฌธ ์ƒ๋žต ๊ฐ€๋Šฅ

[๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ service๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ]

uploads.service ์š”์†Œ๋ฅผ users.service ๋ชจ๋“ˆ์— ๋ถˆ๋Ÿฌ์„œ ์“ฐ๋ ค๊ณ  ํ•จ.

=> ์•„๋ฌด ์ƒ๊ด€๋„ ์—†๋Š” order.module, shop.module ๋“ฑ ๊ณณ๊ณณ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ•จ.

[Nest] 24892  - 08/23/2023, 8:21:56 PM   ERROR [ExceptionHandler] Nest can't resolve dependencies of the OrdersService (OrdersEntityRepository, ?, OrderDetailsEntityRepository). Please make sure that the argument UserService at index [1] is available in the OrdersModule context.

์ข…์†์„ฑ ๋ฌธ์ œ

Order, Shop ๋“ฑ์˜ ๋ชจ๋“ˆ์—์„œ userservice๋ฅผ ์ฐธ์กฐ๋กœ ํ•˜๊ธฐ๋•Œ๋ฌธ์— ์ข…์†์„ฑ์˜ ๋ฌธ์ œ๋กœ ์˜ค๋ฅ˜๋ฐœ์ƒํ•˜๋Š”๊ฒƒ.

=> userservice์™€ ์—ฐ๊ด€๋œ ๋ชจ๋“  ๋ชจ๋“ˆ์˜ providers์— UploadsService๋ฅผ  ๋ถˆ๋Ÿฌ์™€์„œ ํ•ด๊ฒฐํ•จ

 

 

++ ์ข…์†์„ฑ ๊ด€๋ จ ๋‚ด์šฉ ์ถ”๊ฐ€

https://vc-xz.tistory.com/300

 

[TIL] nest ์˜์กด์„ฑ ์ฃผ์ž…์‹œ providers? imports? module?

[์˜์กด์„ฑ ์ฃผ์ž…์‹œ providers? imports? module?] ์ง€๊ธˆ๊นŒ์ง€ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ๋•Œ provider์— ๋„ฃ์–ด์™”๋Š”๋ฐ provider์— ๋„ฃ์œผ๋ฉด "์ธ์Šคํ„ด์Šคํ™”" ๋˜์–ด์„œ ๋ฉ”๋ชจ๋ฆฌ์— ์Œ“์ด๊ฒŒ ๋œ๋‹ค๊ณ  ํ•œ๋‹ค. + ํ•˜๋‹จ ๋‘๋ฒˆ์งธ ์ฐธ๊ณ  ๋งํฌ์™€ ๊ฐ™์€ ์ผ

vc-xz.tistory.com

 

 


[nest form-data ๋‹ค๋ฃจ๊ธฐ]

ํด๋ผ์ด์–ธํŠธ์—์„œ form-data๋กœ ๋ณด๋‚ด๋Š”๋ฐ ValidationPipe์—์„œ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌํ•˜๋ฉด์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จ.

์ฐพ์•„๋ณด๋‹ˆ ํŒŒ์ผ ์—…๋กœ๋“œ์‹œ @UseInterceptors(FilesInterceptor('files')) ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

FilesInterceptor๋Š” ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ธํ„ฐ์…‰ํ„ฐ๊ณ , files๋Š” ์—…๋กœ๋“œ ํ•„๋“œ์˜ ์ด๋ฆ„์ž„

  @UseInterceptors(FilesInterceptor('files'))

=> ๋ฐฐ์—ด์ด๋ƒ ๋‹จ์ˆ˜๋ƒ์— ๋”ฐ๋ผ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๋ช…์ด ๋‹ค๋ฆ„! ๊ผญ ํ™•์ธ..! ์•„๋‹ˆ๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ชป๋ฐ›์•„์˜จ๋‹ค

 

 

// users.controller.ts

  //-- ์ผ๋ฐ˜ ํšŒ์›๊ฐ€์ž… --//
  @Post()
  @UsePipes(ValidationPipe)
  @UseInterceptors(FileInterceptor('files'))
  async signUp(
    @UploadedFiles() files: Express.Multer.File[],
    @Body() createUserDto: CreateUserDto,
  ): Promise<ResultableInterface> {
    console.log(files);
    return await this.userService.signUp(createUserDto, files);
  }

[nest form-data boolean ์ด ํ•ญ์ƒ true๋กœ ๋ณด๋‚ด์ง€๋Š” ๋ฌธ์ œ]

form-data์— false๋กœ ๋ณด๋‚ด๋„ ์„œ๋ฒ„์—์„œ๋Š” ๊ณ„์† true๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค

class-transformer ๋ฌธ์ œ๋ผ๋Š”๋ฐ ์•„๋ž˜ ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๊ธ€์„ ์ฐธ๊ณ ํ•จ

https://stackoverflow.com/questions/59046629/boolean-parameter-in-request-body-is-always-true-in-nestjs-api

 

๋ณดํ†ต form-data ๋ฅผ ํ†ตํ•ด ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์„ ์ „์†กํ•˜๋ฉด ํ•ด๋‹น ๊ฐ’์ด ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ์„œ๋ฒ„์— ๋„๋‹ฌํ•˜๋Š”๋ฐ Nestjs์˜ class-transformer,class-validator ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋ฌธ์ž์—ด์„ ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ๋ชปํ•ด์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊น€

๊ทธ๋ž˜์„œ @Transform ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ˆ˜๋™์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์—ˆ๋‹ค.

 

// create-udser.dto.ts

  @IsOptional()
  @Transform(({ obj, key }) => {
    return obj[key] === 'true' ? true : obj[key] === 'false' ? false : obj[key];
  })
  @IsBoolean()
  readonly seller_flag: boolean;