본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Node.js/Nestjs (Nest.js)

Nestjs 프레임워크 서버(객체 매핑과 파일 업로드) -5

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2022. 7. 5.

 

#Request 매핑

nestjs에서 사용자의 요청을 받기 위한 방법은 데코레이터를 통해서 받을 수 있습니다.

post나 get 방식에서의 모든 동작에 반응하기 위해서는 Express프레임워크의 Request 타입의 객체에 접근하여 body 또는 query 여부에 따라 확인하면 됩니다.

@All('hello') // http:x.x.x.x:3000/hello 요청에 응답합니다.(get, post 방식 등)
모든요청(@Req() req: Request, @Res() res: Response): void {
    //post 방식 파라미터 받는 방법 : req.body
    //get 방식 파라미터 받는 방법 : req.query
    const param = req?.body?.length ? req.body : req.query;
    res.send({ yourData: param });
}

 

또한 Body나 Query, Param같은 데코레이터를 사용하여 깔끔하게 표현 할 수 있습니다.

Body는 오직 post 방식에서만 작동하며, Query는 get방식에서만 작동 합니다.

* 파일이름 : app.다른컨트롤러.ts

@All('hello') // http:x.x.x.x:3000/hello 요청에 응답합니다.(get, post 방식 등)
모든요청(@Req() req: Request, @Res() res: Response): void {
    //post 방식 파라미터 받는 방법 : req.body
    //get 방식 파라미터 받는 방법 : req.query
    const param = req?.body?.length ? req.body : req.query;
    res.send({ yourData: param });
}

@Get('get') // http:x.x.x.x:3000/get 요청에 응답합니다.(get 방식)
get요청(@Query() req, @Res() res: Response): void {
    res.send({ yourData: req });
}

@Get('get2/:data') // http:x.x.x.x:3000/get2/사용자가보낸값 요청에 응답합니다.(get 방식)
urlMapping요청(@Param('data') req: string, @Res() res: Response): void {
    res.send({ yourData: req });
}

@Post('body') // http:x.x.x.x:3000/body 요청에 응답합니다.(post 방식)
body요청(@Body() req, @Res() res: Response): void {
    res.send({ yourData: req });
}

 

Reqeust를 매핑하는 위 데코레이터들은 파라미터(인수)를 가질 수 있습니다.

데코레이터 내부에 값을 지정하면 해당 값에 대한 키 값으로 동작하여 해당 키 값에 해당하는 값만 매핑합니다.

또한 사용자 지정의 DTO를 만들어서 적용 할 수 있습니다.

Nestjs는 타입스크립트 기반이므로 데코레이터를 만들어 붙여 준 다면 해당 클래스의 메소드의 프로토타입을 변경한 코드가 적용되어 동작하게 합니다.

아래 코드는 "커스텀 데코레이터" 라고 검색하면 나오는 유명한(?) 샘플 데코레이터 입니다.

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: string, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    const user = request.user  //user라는 키 값을 매핑하게 되어 있습니다.
    return data ? user?.[data] : user;
  }
);

 

 

#파일 업로드

nestjs에서 파일 업로드 기능을 붙이는 것은 매우 쉽습니다.

Nestjs 공식 홈페이지에서는 multer라는 라이브러리를 사용하여 파일 업로드 기능을 소개하고 있습니다.

이를 위해서는 역시나 멀터(multer) 라이브러리를 추가하여 줍니다.

npm i -D @types/multer

 

멀터 라이브러리는 Express에서 먼저 사용되었고, Nestjs에서 모듈화가 되지 않는 라이브러리 입니다.

그러므로 해당 라이브러리는 모듈에 추가해서 사용하지 않고 사용하는 컨트롤러에서 직접 import를 추가하여 사용하면 됩니다.

새로운 파일 컨트롤러를 추가하여 주었습니다.

* 파일이름 : 파일컨트롤러.ts

import { Controller, Post, UploadedFiles, UseInterceptors, } from '@nestjs/common';
import { AnyFilesInterceptor } from '@nestjs/platform-express';
import { 멀터옵션 } from './app.멀터옵션';

@Controller()
export class 파일컨트롤러 {
  @Post('upload')
  @UseInterceptors(AnyFilesInterceptor(멀터옵션))
  upload(@UploadedFiles() file: Array<Express.Multer.File>): any {
    console.log(file);  //저장된 파일정보가 출력 됩니다.
    return { succ: true };
  }
}

 

upload 요청에 대해서 동작하는 컨트롤러 입니다.

당연히 post 방식에 multipart 형식을 지켜주어야 하며, UseInterceptors라는 데코레이터가 사용되었습니다.

UseInterceptors 라는 데코레이터는 해당 컨트롤러의 메서드가 실행되기 전에 동작 해야되는 함수(인터셉터)를 정의하는 기능 입니다.

* 인터셉터 : 클래스 또는 함수형식의 기능이며 먼저 동작하는 개념을 의미 합니다.

 

UseInterceptors데코레이터는 upload 요청을 받게되면 먼저 동작하는 데 그때 AnyFilesInterceptor 라는 함수(인터셉터형식)를 실행하게 되고 해당 AnyFilesInterceptor라는 함수는 upload 요청으로 들어온 파일을 저장는 역할을 합니다.

AnyFilesInterceptor 함수는 MulterOptions 인터페이스 옵션을 인수로 받을 수 있습니다.

AnyFilesInterceptor 함수는 전송되는 파일의 키 값 또는 보내는 파일 갯수와 상관없이 전부 저장하는 함수 입니다.

 

위 코드에서 사용되는 옵션파일 입니다.

옵션파일이 없어도 동작하는데 문제되지는 않습니다.

* 파일이름 : app.멀터옵션.ts

import { diskStorage } from 'multer';
import { extname } from 'path';
import { existsSync, mkdirSync } from 'fs';

export const 멀터옵션 = {
  fileFilter: (request, file, callback) => {
    //조건에 따른 필터(저장할지말지)를 설정 할 수 있습니다.
    callback(null, true);  
  },

  storage: diskStorage({
    destination: (request, file, callback) => {  //저장공간을 설정 합니다.
      const uploadPath = './upload';
      if (!existsSync(uploadPath)) {
        mkdirSync(uploadPath);
      }
      callback(null, uploadPath);
    },
    filename: (request, file, callback) => {
      //파일 이름 설정 합니다.
      callback(null, `${Date.now()}${extname(file.originalname)}`);
    },
  }),
  limits: {
    fieldNameSize: 200, // 필드명 최대값 입니다. (기본값 100bytes)
    filedSize: 1024 * 1024, // 필드 사이즈 값 설정 (기본값 1MB)
    fields: 2, // 파일 형식이 아닌 필드의 최대 개수 (기본 값 무제한)
    fileSize: 16777216, //multipart 형식 폼에서 최대 파일 사이즈(bytes) "16MB 설정" (기본 값 무제한)
    files: 10, //multipart 형식 폼에서 파일 필드 최대 개수 (기본 값 무제한)
  },
};

 

옵션을 추가하지 않는다면 파일은 아마 운영체제의 temp 디렉토리에 저장되게 됩니다.

또한 파일이름은 확장자가 제거된 난수화된 값으로 저장되게 됩니다.

 

만약 파일 업로드가 파라미터가 함께 전송되는 경우 라면 간단하게 Req 데코레이터를 추가하면 마찬가지로 쉽게 전송되는 파라미터를 매핑할 수 있습니다.

당연히 Response 객체도 추가할 수 있습니다.

* 파일이름 : 파일컨트롤러.ts

import { Request, Response } from 'express';
import { Controller, Post, UploadedFiles, UseInterceptors, Res, Req, } from '@nestjs/common';
import { AnyFilesInterceptor } from '@nestjs/platform-express';
import { 멀터옵션 } from './app.멀터옵션';

@Controller()
export class 파일컨트롤러 {
  @Post('upload')
  @UseInterceptors(AnyFilesInterceptor(멀터옵션))
  upload(@UploadedFiles() file: Array<Express.Multer.File>, @Req() req: Request, @Res() res: Response): any {
    console.log(file);  //저장된 파일정보가 출력 됩니다.
    return { succ: true };
  }
}

 

Nestjs에서 파일 업로드는 Express 서버에서 multer를 사용한 것과 거의 다른내용이 없습니다.

모듈처럼 사용하는 게 아니라 import해서 사용하는 것만 기억하면 될 것 같습니다.

위 내용에 사용된 소스코드는 제 깃허브에서 받을 수 있습니다.

https://github.com/TaeSeungRyu/NestProject/tree/main/step4

 

GitHub - TaeSeungRyu/NestProject: Nestjs 프로젝트

Nestjs 프로젝트. Contribute to TaeSeungRyu/NestProject development by creating an account on GitHub.

github.com

 


 

* 번외

esLint에 의해서 Delete `␍` prettier/prettier 오류가 간혹 발생하는 경우가 있습니다.

esLint와 prettier 라이브러리간의 설정에 따른 차이로 발생합니다.

해결 방법은 .eslintrc.js 파일에서 rules 부분에 아래 내용을 추가하여 줍니다.

"prettier/prettier": [
    "error",
    {
    	"endOfLine": "auto"
    },
]

이렇게 rules 부분에 추가해주면 됩니다.

 

공부하면 할 수록 재미있고 즐거운 nestjs!!!

다음 포스팅에서는 잠깐 만나본 인터셉터와 관련된 내용을 정리 해 보겠습니다!

궁금한점 또는 틀린부분은 언제든 연락 주세요!

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글