nestJS body, param, query, DTO

양진영·2023년 2월 9일
0

nestJs

목록 보기
4/10

사용자가 서버에 데이터를 전달해주는 방식은 몇가지가 있다. 대표적으로는 body로 전달할수있으며 url을 이용한 param 그리고 query로 전달하는 방식이 있다. 이외에도 multipart/form-data라던가 form url encoded방식이라던가 있지만 일단은 대표적인 방식들만 다뤄볼 생각이다.

nestjs에서는 @Body ,@Param, @Query 앞에 @는 데코레이터(어노테이션)이라고 하며 @을 통해 nest가 사용자가 사용하고자하는 기능을 인지하고 nest가 그 기능을 제공해준다.

dm.controller.ts
@Get(':id/chats')
  getChat(
    @Query() query,
    @Query('perPage') perPage: string,
    @Query('page') page: string,
    @Param() param,
    @Param('id') id: string,
    @Param('url') url: string,
  ) {
    console.log(query.perPage, query.page);
    console.log(param.url);
    console.log(param.id);
  }

위에서 언급했어야 하는데 깜빡한게 있다면 body, param, query로 보낼때는 객체 형식으로 보내진다. 그래서 @Param() param을 통해 요청 객체를 받고 param.키 를 이용하여 특정한 데이터에 접근하는것이 가능하다. 하지만 구지 그렇게 하지 않아도 된다. 만약 @Param('키 이름') 키 이름 으로 선언해준다면 모든 객체를 받아오는것이 아닌 특정 하나의 데이터만 골라서 받아올수 있다. 상황에 따라 모든 param(body,query) 데이터를 객체로 받아올지 아니면 특정 키만 받아올지 정할수있다.

DTO

dto란?
data transfer object의 줄인말로 말 그대로 데이터를 전달해주는 객체이다. 어떤 객체를 전달해주느냐는 사용자가 지정할수 있지만 받아야 하는 인자들을 하나하나 보내기보다는 한번에 다 전달해줄수있는 이점이 있다.

request.join.dto.ts
export class JoinRequestDto {
  public email: string;

  public nickname: string;

  public password: string;
}

가입을 할때는 항상 이메일,닉네임,비밀번호를 받을것이고 이것을 따로따로 받지않고 하나의 타입으로서 받기위해 dto를 만들었다.

user.controller.ts
  @Post()
  postUsers(@Body() data: JoinRequestDto) {
    this.userService.postUsers(data);
  }

위와 같은 방법처럼 data라는 변수에 JoinRequestDto라는 class를 타입으로서 사용하여 입혔다. 이후 data를 userService안에 메소드중 하나인 postUsers라는 메소드에 넣어주었다.

interface vs class: interface는 ts에서만 남아있어 build때 까지만 적용이 되고 이후 런타임에서는 날아가 버리지만 class의 경우는 런타임에서도 남아 타입체크를 할수도 있고 js로 바뀌어도 class는 남아있으니까 interface보다는 class로 더 많이 사용한다. => class(dto)로 객체를 주고받거나 type을 지정할수있는데 class validator와 함께 사용한다. 이게 아니면 사실 interface와 다를게 없지만 clas validator와 함께 사용하면서 런타임에서도 계속 지속되고 js환경에서도 유지가능하다는 점이 class가 interface보다 추천되는 이유이다. 그리고 class로 만들어야 swagger로 전달이 쉽다. 마지막으로 Class는 extends를 사용하여 확장이 가능하다.

common/user.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { JoinRequestDto } from 'src/users/dto/request.join.dto';

export class UserDto extends JoinRequestDto {
  @ApiProperty({ required: true, example: 1, description: '아이디' })
  id: number;
}

api만들때 첫설계가 굉장히 중요하다... 왜냐하면 한번 잘못만들고 그걸 실서비스로 올렸을때 바꾸기가 너무 힘들기 때문 ㅜ

사담으로 처음에는 왜 dto랑 body를 나눠야하는지 이해가 안갔다. 어차피 dto도 json방식으로 넘겨줄거고 body도 비슷한데 왜 나눠? 라고 생각했지만 지금 생각해보면 dto는 class로 만들어 type을 붙일수 있는것과 동시에 class validator로 검사할수 있어서 body보다 타입이 더 엄격해야하고 반복되는것에 사용되지 않을까 싶다.

profile
왜? 라는 질문을 중요시하는 서버 개발자입니다

0개의 댓글