TIL - [노마드 코더] NestJS로 API 만들기 (2)

MinWoo Park·2021년 4월 19일
0

TIL

목록 보기
36/49
post-thumbnail

Today I Learned

매일 배운 것을 정리하며 기록합니다. NestJS를 통해 Rest API 만들어 보았습니다.


Movies Controller

NestJS로 영화의 Rest API를 만들어 보겠습니다.
가장 먼저 할 일은 url을 가져오고 function을 실행하는 컨트롤러 파일을 만듭니다.

이 프로젝트를 처음 시작할 때 설치했던 Cli가 기억 나시나요?
저희는 프레임워크를 쓰고 있기에 cli를 이용하면 됩니다.
터미널 nest를 입력해 보시면 사용할 수 있는 목록들이 보입니다.

$ nest

generate 키워드

generate 키워드는 cli로 NestJS의 거의 모든 것을 생성할 수 있는 강력한 커맨드입니다.

cli를 통해 controller를 만들어 보겠습니다.

$ nest generate(g) controller(co)


controller를 만드는 순간 파일이 만들어 지면서 app.modules.ts파일에 자동으로 컨트롤러를 import 해 주었습니다.

src/movies/movies/controller.spec.ts 파일이 생성되었는데 spec 파일은 테스트 파일입니다.
테스트는 나중에 할 것이기 때문에 지금은 잠시 지우겠습니다.

이제 컨트롤러에 가서 첫 번째 api 라우터를 만들어 보겠습니다.

movies.controller.ts에 @Get 라우터 작성

@Get 라우터를 만들었으나 브라우저에서는 에러가 발생합니다.
그 이유는 3번 줄 @Controller가 url의 엔트리 포인트를 컨트롤하기 때문입니다.
그래서 http://localhost:3000은 에러가 발생하지만 /movies로 들어가면 정상적으로 출력이 되는 것을 확인하실 수 있습니다.

http://localhost:3000/movies

이러한 이유로 @Controller의 값은 지워주도록 합니다.

최종적인 controller 파일의 모습

이제 6번의 @Get같은 데코레이터들이 express를 사용할 때의 라우터가 됩니다.
새로운 라우터를 추가해 보겠습니다.

@Get에 라우터 매개변수를 추가

9번 줄에 새로 추가한 라우터는 express와 동일한 라우터 매개변수입니다.

브라우저에서의 실행 결과

서버에서는 /1에 해당하는 req.params를 알아야 합니다.
express에서는 정보들이 자동으로 req 객체에 담기지만, NestJS에서는 무언가 필요하면 요청을 해야 합니다.
라우트 매개변수를 요청하는 방법은 다음과 같습니다.

라우터 매개변수 값 알기 위한 요청

먼저 @Param('id')를 통해 url에 있는 id라는 파라미터를 get합니다.
그리고 id라는 파라미터를 argument에 string 타입으로 저장합니다.

@Param와 같이 파라미터에 데코레이터를 붙이면 NestJS는 제가 url에 있는 id 파라미터를 원하는 것을 압니다.
이는 NestJS의 약속이니 형식에 맞춰 작성해야 합니다.

@Get의 라우트 매개변수 id와 @Param의 id는 같아야 하지만 getOne의 인자인 id는 다른 이름으로 작성해도 괜찮습니다.

getOne의 인자 이름 movieId로 교체

콘솔을 보시면 아무 문제가 없음을 알 수 있습니다.

insomenia를 통해 테스트를 해 보겠습니다.

insomenia

@Get처럼 다양한 데코레이터도 작성할 수 있습니다.

@Get, @Post, @Delete, @Patch


More Routes

라우트에 대해 조금 더 살펴 볼건데요, @Post에서 req.body값을 받을 때 body값을 알기 위해서 요청을 보내야 합니다.
이는 @Body()를 사용합니다.

@Post() create()에 @Body 추가

위의 콘솔을 insomenia에서 다음과 같은 body를 보냈기 때문입니다.

insomenia

Patch도 수정을 위해 body를 받아야 하니 코드 수정 후 테스트를 진행해 보겠습니다.

patch에 @Body 추가

insomenia 테스트 결과

insomenia 테스트 결과를 보면 아무것도 설정하지 않았지만 자동으로 JSON을 리턴 받으신 것을 볼 수 있습니다.

express에서는 body를 JSON으로 리턴을 받으려면 미들웨어를 통해 약간의 설정을 했어야 했지만 NestJS에서는 자동으로 처리해 줍니다.

라우터 매개변수를 사용할 때 주의사항이 한 가지 더 있는데요,
아래 18번 줄처럼 새로 라우터를 추가할 때 라우터 매개변수는 일반 라우터보다 뒤에 위치해야 합니다.
그렇지 않으면 NestJS는 search를 id로 판단합니다.

이는 express와 동일한데 라우터 매개변수는 다양한 라우터를 아우르는 와일드카드 역할을 하므로 일반 라우터보다는 뒤에 위치해야 다른 라우터를 방해하지 않습니다.

이번에는 라우터에 쿼리스트링을 사용해 보겠습니다.

@Get('search') search에 @Query 추가

insomenia로 http://localhost:3000/movies/search? year=2000 테스트

이렇게 query parameter와 body decorator를 배워 보았습니다.
NestJS에서는 필요한 것이 있으면 요청을 해야 하며, 20번 줄과 같이 가져오는 변수와 리턴 값을 한 눈에 볼 수 있는 장점이 있습니다.


Movies Service part One

Single-responsibility principle(단일 책임 원칙)을 따라 진행해 보겠습니다.
단일 책임 원칙이란 위키백과에 따르면 다음과 같이 정의됩니다.

객체 지향 프로그래밍에서 단일 책임 원칙(single responsibility principle)이란 모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함을 일컫는다. 클래스가 제공하는 모든 기능은 이 책임과 주의 깊게 부합해야 한다.

즉, 하나의 module, class 혹은 fucntion이 하나의 기능은 꼭 책임져야 한다는 뜻입니다.

이번에 서비스를 만들어 볼겁니다.
앞서 컨트롤러는 ur을 매핑하고 리퀘스트를 받거나 쿼리를 넘기거나 바디나 그 외의 것들을 넘기는 역할을 했습니다.

서비스는 movies의 로직을 관리하는 역할을 맡습니다.

cli를 통해 service를 생성해 봅니다.

$ nest generate(g) service(s)

app.module.ts에 service 자동 셋팅

providers에 서비스가 생긴 것을 볼 수 있습니다.

다음으로 할 건 movie.service.ts에 데이터베이스를 만드는 일입니다.
해당 강의에서는 가짜 데이터베이스를 다루어 범위를 좁혔습니다.
가짜 데이터베이스를 다루지만 movies 컨트롤러가 있고 서비스에서는 쿼리 같은 걸 처리하는 것은 동일합니다.

service에서는 movies 배열을 만들건데 이 배열에 들어갈 값들의 형식을 지정해 줘야 합니다.

movies.service.ts

src/movies/entities/movie.entity.ts 생성

movie.entity.ts에서는 서비스를 보내고 받을 클래스를 export 합니다.
movie를 구성하는 그 자체입니다.

위처럼 Movie 클래스를 만들면 service에서 타입으로 지정해 줍니다.
인터페이스 역할을 하는 겁니다.

참고로 현재는 가짜 데이터베이스를 사용하지만 보통 entities에 실제 데이터베이스를 만듭니다.

이제는 컨트롤러에서 임의로 작성했던 함수들을 service로 옮기는 작업을 할 겁니다.
그리고 service로 부터 import하여 controller에서 사용할 겁니다.

nest new를 통해 처음 만들어진 구조처럼 말입니다.

express에서는 수동으로 import를 하지만 NestJs에서는 그런 식으로 하지 않습니다.

NestJS에서는 필요한 것은 기본적으로 요청을 합니다.
다음과 같은 방법으로 사용합니다.

constructor가 moviesService 클래스를 가짐

컨스트럭터 부분 덕분에 MoviesService를 불러와 사용 가능합니다.

컨트롤러와 서비스 코드를 수정한 결과는 다음과 같습니다.

controller

service

insomenia로 post후 get테스트


Movies Service part two

앞선 테스트로 정상적인 GET 요청이라면 데이터를 잘 받아오는 것을 볼 수 있었습니다.
하지만 잘못된 요청에는 아무런 에러 메시지를 띄우지 않는 점도 볼 수 있습니다.
그렇기에 에러 처리를 해 보겠습니다.

잘못된 GET 요청에 에러 메시지가 응답되지 않는 문제점 발견

movies.service.ts에서 getOne함수를 다음과 같이 수정하겠습니다.

NotFoundException은 보시다시피 NestJS에서 제공하는 예외처리입니다.

HttpException에서 확장된 NestJS의 기능

예외 처리 후 응답 결과는 다음과 같습니다.

잘못된 GET 요청처럼 PATCH 요청에도 잘못된 정보된 넣어 요청하는 경우를 대비하기 위해 유효성 검사를 실시해야 합니다.
현재의 문제점은 다음과 같습니다.
왼쪽의 JSON의 데이터를 PATCH 했을 때 오른쪽에 보이시는 것처럼 데이터가 변형됩니다.

유효성 검사를 위한 작업은 다음 시간에 진행하겠습니다.


Reference : 노마드 코더, 『NestJS로 API 만들기』, #2.0~#2.3

profile
물음표를 느낌표로 바꾸는 순간을 사랑하는 개발자입니다.

0개의 댓글