캡스톤디자인(1)/공부

캡스톤디자인(1) - NestJS 공부2

ludvbg (이지현) 2022. 10. 14. 02:31

컴퓨터공학과 5584977 이지현
캡스톤디자인(1) TEAM 우연한 인연

 

#1.2 Services

@Get()
getHello(): string {
	return this.appService.getHello();
}

위의 코드에서 getHello()를 통해 string만 리턴해도 잘 실행되는데 왜 appService가 필요할까?

(이것을 위해서 Structure와 Architecture에 대하여 알아야 한다.)

 

NestJS는 컨트롤러에서는 url만 실행(연결)시키고 나머지 비즈니스 로직은 서비스로 이동시킨다.

컨트롤러에 모든 url을 다 넣어놓고 서비스에서 (필요하다면) 데이터베이스와 통신하는 것이다.

 

여기서 서비스는 실제로 function을 가지는 부분이다.

app.module.ts = AppModule에서 모든 import문이 들어간다.

 

그리고 기본적으로 만들어져 있었던 AppService와 AppController를 지우고 우리의(나의) 모듈을 만들 준비를 하자.

 

 

 

#2 REST API

#2.0 Movies Controller

 

- 영화의 Rest api를 만들어보자

 

1. terminal에서 nest g(enerator) co(ntroller) 명령어를 사용

 

이름을 'movies'로 정하였다.

 

그러면 자동으로 MoviesController가 import 되었고, 폴더(movies)가 생성된 것을 볼 수 있다.

movies.controller.spec.ts파일도 생겼는데, spec 파일은 테스트 파일이다. 강의에서는 파일을 지우고 나중에 살펴보는 것으로 하였다.

 

 

 

2. movies 컨트롤러에서 첫 번째 api 라우터 만들기

localhost:3000/movies 링크 요청시와 /movies/:id 링크 요청시 return 내용, :id는 임의의 값이다.

 

insomnia로 /movies 요청했을 때 실행되는 화면
id parameter에 1을 넣고 실행한 화면

 

:id 값에 꼭 숫자를 넣지 않아도 되는 것 같다.

 

 

이번에는 @Param 데코레이터를 이용해 url의 id값을 string인 movieId 변수로 받아오고 그 값을 출력할 수 있는 코드로 바꾸었다.

 

id 값이 정상적으로 출력됨

 

 

마지막으로 movie를 Create하기 위해 @Post 방식으로 요청을 주는 함수를 만들고

Delete, Update하는 함수를 @Delete와 @Patch 데코레이터를 사용해 만들어주었다.

Update하는 데코레이터에는 @Put과 @Patch가 있다.

둘 다 Update를 위한 데코레이터인데, @Put은 모든 리소스를 업데이트하고 @Patch는 리소스의 일부분만 업데이트해준다.

 

 

 

* 갑자기 REST API가 정확히 어떤건지 궁금해져서 검색해봄

REST(RESTful) API

- REST 아키텍처의 제약 조건을 준수하는 애플리케이션 프로그래밍 인터페이스

  REST: Representation State Transfer

- 월드 와이드 웹(WWW)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식

 

 

#2.1 More Routes

 

 

- NestJS에서 사용할 수 있는 모든 decorator에 대하여 알기

 

 

1. movie를 생성할 때 body를 가져오고 싶다.

 

 

내 movie가 name, director의 body를 가진다. (insomnia에서 JSON으로 body 작성)

이걸 데코레이터를 활용하여 내 API로 보내려면 어떻게 해야 할까?

 

 

@Body 데코레이터를 사용하여 movieData로 받고 insomnia에서 url을 요청한다음 console을 살펴보았다.

 

 

정상적으로 내가 입력한 body가 출력되었다.

 

여기서 NestJS는 별도의 설정 없이도 JSON을 return할 수 있다는 것을 알 수 있다.

 

Patch에도 똑같이 사용해주었다.

 

updatedMovie 값으로 movieId를 주고, updateData의 데이터 오브젝트를 리턴시켜주었다.

이런식으로 return에 {}를 쓰는 건 처음 본 것 같다.

그리고 ...으로 데이터 오브젝트를 사용하는 것도 처음보는데, 데이터 오브젝트의 사용방법이 ...으로 사용하는 것인지는 확실하지 않다.

 

Patch를 수정하고 다시 insomnia에서 요청하여 출력된 결과이다.

 

 

 

 

그리고 search?를 통해 query를 받아오고 싶어서 search 함수도 만들어주었다.

여기서 @Get("search") 데코레이터가 @Get("/:id")보다 밑에 있으면, 'search'를 id값으로 인식해서 'search'를 @Get("/:id")보다 위에 작성하여야 한다. search 이외에도 @Get("/:id") 밑에는 다른 @Get이 작동하지 않는다고 한다.

id값을 넣는 코드는 가장 아래에 써야할 것 같다.

 

search?year=2000으로 요청하였고, 값을 잘 읽어와서 출력한 모습이다.

 

 

 

 

#2.2 Movies Service part One

 

 

1. Single-responsibility principle을 따르자!

- 하나의 module, class, 혹은 function이 하나의 기능은 꼭 책임져야 한다는 것

- #2.2에서는 서비스를 만드는데, 서비스는 movies의 로직을 관리하는 역할을 맡는다.

* Controller는 url을 매핑하고, 리퀘스트를 받고, Query를 넘기거나 Body나 그 외의 것들을 넘기는 역할을 한다.

 

 

 

- nest g(enerator) s(ervice) 명령어를 사용

 

 

마찬가지로 이름은 movies로 하였다.

 

 

movies 폴더에 movies.service.ts와 movies.service.spec.ts 파일이 생성되었다. spec 파일은 역시 테스트용이고, 이번에는 삭제는 하지 않았다. (사용하지도 x)

 

 

app.module.ts에 자동으로 MoviesService가 import된 것을 확인할 수 있다.

 

 

 

2. service에 데이터베이스를 만들 것이다.

- 진짜 데이터베이스를 연결하지는 않고, javascript object를 사용해서 가짜 데이터베이스로 이용한다.

- 진짜 데이터베이스를 사용할 때는 entities에 실제로 데이터베이스 모델을 만들어야 한다.

 

 

movies 폴더에 entities 폴더를 생성하고, entities 폴더 안에 movie.entity.ts 파일을 생성하였다.

그리고 위의 사진처럼 서비스로 보내고 받을 클래스(인터페이스)를 export 해주었다.

Movie class는 movie를 구성하는 것들이다.

 

 

 

그리고 service에서 movies의 타입을 Movie array로 지정해주었다.

 

 

 

controller의 function을 service에 작성해주었다. 함수의 이름은 같아도 상관없다.

진짜 데이터베이스라면 데이터베이스에 대한 Query를 작성하는 것이다.

 

 

(* filter(movie => movie.id !== +id) 이해하기)

 

 

 

service에 접근하기 위하여 controller에 constructor를 만들어주었다.

그리고 최종 코드는 아래와 같다.

 

movies.controller.ts의 전체 코드

 

 

 

(* 자동 import가 될 때도 있고 안될 때도 있어서 한 번 알아보기)