Node.js/Nest.js

[Nest.js] Controller 라우팅 에러 (url 동적할당/ 정적할당)

후뿡이 2023. 6. 11. 02:11

🐳 문제 코드


 

@Controller('records')
@UseGuards(AuthGuard('jwt'))
@UsePipes(ValidationPipe)
export class RecordsController {
  constructor(private recordsService: RecordsService) {}

  @Get('/:id')
  getRecord(@Param('id') id:number): Promise<Record> {
    console.log("getRecord is routed")
    return this.recordsService.getRecordById(id);
  }

  @Get('/weekly/')
  getWeeklyInfo(@GetUser() user:User):Promise<any>{
    console.log("getWeeklyInfo is routed")
    return this.recordsService.getWeeklyInfo(user);
  }
}

위와 같은 Nest.js의 recordsController 코드를 작성하였다.

 

localhost:3000/records/weekly/로 request를 보내면 getWeeklyInfo가 실행돼야 할 것이다.

 

그런데 이게 무슨 일이지 ??

 

getRecord 함수가 호출 된 것을 console창을 통해 확인할 수 있다 !

 

왜 그런 것일까 .. ? 

 

 

🐳 문제 인식


@Get('/:id') 를 @Get('/id')로 수정하니 weekly가 정상적으로 라우팅 됐다 !

 

하지만 갑자기 잘 되던 localhost:3000/records/31 같은 record 정보를 id로 가지고 오는 것이 동작하지 않았다 !

 

 

 

@Get('/:id') 와 @Get('/id') ....

이 둘 사이에 분명히 차이가 있다 !

 

 

 

🐳 문제 원인


@Get('/:id') 와 @Get('/id') 는 @Get() 의 변수인 path를 사용함에 차이가 있었다.

 

  • @Get('/:id') 은 id를 동적으로 할당한다 !

이 말은 정말 정직하게 "id" 가 path로 들어오는 것이 아니라 유저가 url에 입력한 값을 id로 생각하겠다는 뜻이다 !

 

위에서 우리가 던진 url을 예로 살펴보자 localhost:3000/records/31

여기서 @Get('/:id') 은 id를 동적으로 할당하기 때문에 31이라는 값을 id로 생각한다는 것이다.

 

  • @Get('/id') 은 id를 정적으로 할당한다 !

이 말은 정~~말 정직하게 path 값으로 "id"가 들어 왔을 때 라우팅하겠다는 뜻이다 !

즉 url이 localhost:3000/records/id 인 경우에 !!! routing 하겠다는 뜻이다.

 

 

그렇다면 나의 코드는 왜 문제가 발생한 것일까?

@Controller('records')
@UseGuards(AuthGuard('jwt'))
@UsePipes(ValidationPipe)
export class RecordsController {
  constructor(private recordsService: RecordsService) {}

  @Get('/:id')
  getRecord(@Param('id') id:number): Promise<Record> {
    console.log("getRecord is routed")
    return this.recordsService.getRecordById(id);
  }

  @Get('/weekly/')
  getWeeklyInfo(@GetUser() user:User):Promise<any>{
    console.log("getWeeklyInfo is routed")
    return this.recordsService.getWeeklyInfo(user);
  }
}

 

위의 코드에서 

localhost:3000/records/weekly를 request를 보냈다고 가정하자

 

그러면 @Get('/:id') 이 먼저 있기 때문에

"weekly" 를 id에 동적할당 해 id = weekly 라고 생각하는 것이다 !

그렇기 때문에 위에서 살펴본 것처럼 "getRecord is routed" 라는 log가 출력된다.

 

그렇다면 어떻게 해결할까?

 

🐳 문제 원인


답은 간단하다 !

 

소드의 순서를 바꿔서 "/:id"로 id값을 동적할당 하기 전에 /weekly/를 탐색하는 것이다 !

 

@Controller('records')
@UseGuards(AuthGuard('jwt'))
@UsePipes(ValidationPipe)
export class RecordsController {
  constructor(private recordsService: RecordsService) {}

  @Get('/weekly/')
  getWeeklyInfo(@GetUser() user:User):Promise<any>{
    console.log("getWeeklyInfo is routed")
    return this.recordsService.getWeeklyInfo(user);
  }

  @Get('/:id')
  getRecord(@Param('id') id:number): Promise<Record> {
    console.log("getRecord is routed")
    return this.recordsService.getRecordById(id);
  }
}

 

이렇게 코드를 작성하면

localhost:3000/records/weekly라는 request가 오면 먼저 /'weekly''에 해당하는지 확인하고 '/:id' 에 동적할당하기 때문에

문제가 발생하지 않는다 !