매일 배운 것을 정리하며 기록합니다. NestJS 공부를 시작했습니다.
NestJS는 node.js 프레임워크로 express 기반으로 작동합니다.
기존 node.js의 구조화되지 않은 단점을 해결하기 위해 NestJS를 사용하여 정해진 룰 안에서 코드를 작성해 보려고 합니다.
NestJS를 사용하기 위해 설치를 하겠습니다.
$ npm i -g @nestjs/cli
그리고 원하는 위치로 이동하여 새로운 프로젝트를 만듭니다.
$ nest new project-name
NestJS 사용 시 필요한 파일들을 알아서 만들어 줍니다.
여기서 학습을 위해 잠시 app.controller.spec.ts 파일은 삭제하고 진행하겠습니다.
NestJS 파일들이 잘 작동하는지 테스트를 해 볼 겁니다.
package.json에 들어가보면 scripts에 start와 관련된 스크립트 중 'start:dev'를 실행해 볼겁니다.
package.json
$ npm run start:dev
터미널에 위와 같은 화면이 보인다면 정상적으로 실행이 된 것입니다.
각 문장 맨 마지막을 보시면 Module, Controller 등등이 실행된 것을 볼 수 있습니다.
Nest어플리케이션이 실행되고 있으니 localhost:3000으로 들어가 웹에서도 확인해 보겠습니다.
다음과 같이 Hello World!가 출력될 것입니다.
그렇다면 Hello World!는 어디서 나온 것일까요?
코드를 보며 직접 찾아가 보겠습니다.
NestJS는 main.ts 파일을 가집니다.
무조건 main.ts라는 이름이여야 합니다.
main.ts
main.ts 파일에는 bootstrap이라는 함수를 가지고 있습니다.
보시다시피 await NestFactory.create(AppModule)을 호출하고 3000번 포트를 리스닝하고 있습니다.
아직 Hello World의 시작점으로 보이지 않으니 더 깊숙이 AppModule로 들어가 보겠습니다.
app.modules.ts
app.module.ts를 보면 AppModule은 클래스임을 알 수 있습니다.
그리고 5라인 @Module함수처럼 함수 앞에 '@'가 붙어있는 것을 데코레이터라고 합니다.
NestJS는 데코레이터가 자주 등장하는데 그 이유는 데코레이터는 클래스에 함수 기능을 추가할 수 있기 때문입니다.
클래스를 위해 움직이는 클래스 위의 함수라고 보면 됩니다.
이번에는 @Module 함수의 controllers를 살펴보겠습니다.
app.controllers.ts
컨트롤러에도 @Get 이라는 데코레이터와 getHello 함수가 보입니다.
getHello 함수에서는 app~~의 모양의 appService라는 게 보입니다.
6번 줄 constructor에서 시작된 것으로 보이는 AppService로 또 들어가 봅니다.
app.service.ts
AppService 클래스와 @Injectableg() 데코레이터가 보입니다.
여기서 'Hello World'를 리턴하는 것을 찾을 수 있습니다.
지금 localhost:3000에 렌더되는 건 getHello 함수의 결과라는 것입니다.
확인을 위해 다른 값으로 바꾸어 테스트를 해 보겠습니다.
app.service.ts
웹에 렌더되는 Hello Nest!는 app.service.ts에서 작성된 것을 확인했습니다.
이제는 각 파일들을 자세히 살펴보겠습니다.
컨트롤러는 기본적으로 url을 가져오고 함수를 실행하는 일을 합니다.
express의 라우터같은 존재입니다.
controllers의 @Get이 express의 get 라우터의 역할을 합니다.
app.controllers.ts
만약 /hello 주소에 들어오면 Hello라는 문자를 보여주고 싶으면 다음과 같이 작성하면 됩니다.
데코레이터를 사용할 때 주의할 점은 꾸며주는 함수나 클래스랑 붙어 있어야 합니다.
13번과 14번 코드가 떨어져 있으면 안됩니다.
app.controllers.ts 에 '/hello' 추가
/hello로 접속 시
NestJS가 자동으로 라우팅을 해 주는 덕분에 라우터를 셋팅하지 않아도 된다는 편리함이 생깁니다.
당연히 Get뿐만 아니라 Post도 사용 가능합니다.
Get -> Post 메서드로 변경
Post /hello로 변경 시 자동으로 발생하는 에러
@Post로 변경하니 에러 메시지가 발생하는데 이것도 NestJS가 알아서 처리해 준 것입니다.
낯설게 보였던 데코레이터와 클래스가 express로 해왔던 것과 다름 없다는 것을 알게 되었습니다.
하지만 컨트롤러에서 바로 Hello를 리턴하여 렌더할 수 있는데 왜 appService를 참조하고 있는지는 의문이 풀리지 않았습니다.
이 의문을 풀어 보겠습니다.
app.controllers.ts의 appService?
앞서 보신 것처럼 컨트롤러에서 'Hello'를 리턴하면 브라우저에서 볼 수 있는데 왜 Services가 필요할까요?
이를 이해하기 위해서는 구조와 아키텍처에 대해서 이야기를 해 볼 필요가 있습니다.
NestJS는 컨트롤러와 비지니스 로직을 구분짓고 싶어 합니다.
컨트롤러는 그저 url을 가져오고 함수를 실행하는 역할일 뿐입니다.
나머지는 비지니스 로직으로 갑니다.
서비스는 일반적으로 실제로 함수를 가지는 부분입니다.
서비스 파일에 들어가 보면 클래스와 함수가 보입니다.
app.services.ts
NestJS의 방식을 따른다면 앞서 컨트롤러에서 만들었던 sayHello같은 함수를 app.services.ts에서 만드는 겁니다.
app.services.ts에서 getHi 함수 정의
app.controllers.ts에서 appService에서 만든 함수를 사용
get /hello 실행 결과
이처럼 NestJS방식으로 컨트롤러에 sayHello 함수를 만들고
서비스에 getHi 함수를 만들어 사용해 보았습니다.
NestJS 구조를 이용하게 되면 컨트롤러에 모든 url을 넣어놓고
서비스에서는 비지니스 로직을 실행하는데 필요하다면 데이터베이스에 연락을 취하기도 합니다.
NestJS 구조와 컨트롤러, 서비스의 역할을 알게 되었으니 다음 시간에는 셋팅된 파일들을 삭제하고 처음부터 코드를 작성해 보는 시간을 갖겠습니다.
Reference : 노마드 코더, 『NestJS로 API 만들기』, #0.1~#1.2