โ ํ ์ผ
-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๋ฅผ ๋ถ๋ฌ์์ ํด๊ฒฐํจ
++ ์ข ์์ฑ ๊ด๋ จ ๋ด์ฉ ์ถ๊ฐ
[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 ๋ฌธ์ ๋ผ๋๋ฐ ์๋ ์คํ์ค๋ฒํ๋ก์ฐ ๊ธ์ ์ฐธ๊ณ ํจ
๋ณดํต 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;