Javascript/Node.js

NestJS를 들어가며

leeeee.yeon 2021. 8. 23. 22:38

노마드코더 'NestJS로 API 만들기' 강의를 들으며 작성하는 글입니다.


 

NestJS란?

 

NestJS는, node.js와 express 위에서 움직이는 프레임워크로 백엔드를 구성할 수 있도록 해준다.

NestJS는 기본에 충실하며, node.js에는 없는 구조를 가지고 있다.

 

Ruby에는 Ruby on Rails가 있으며, 순서와 구조를 가지고 있어 그것을 제대로 따른다면 멋진 ruby 버킷을 만들 수 있게 된다.

Python과 Django, JAVA와 Spring도 마찬가지이다.

이것들은 큰 테마로 작업을 할 때 가능 구조상 실수를 하기 어렵다. NestJS는 그러한 프레임워크의 특징을 가져왔다.

 

Node.js의 장점이자 단점은 프로젝트를 만들 때 따를 룰이 없다는 것이다. (ex. 컨트롤러와 미들웨어를 어디 둘지 등등 ....)

하지만 NestJS에는 구조와 순서, 룰이이 있어 큰 규모의 프로젝트를 만들 때 도움이 된다.

 

Typescript를 기반으로 하며, OOP(Object Oriented Programming), FP(Functional Programming), FRP(Functional Reactive Programming) 등등을 사용한다.

 

Setting

 

이번 강의에서는 NestJS로 API를 만들고, 이 API를 테스트하는 법을 배운다. 

기본적으로 강의에 앞서 node.js 사용 경험, typescript에 대한 지식이 필요하며

REST API를 사용하기 때문에 insomnia도 설치되어 있어야 한다...라고 하지만, 댓글을 보니 postman으로 insomnia를 대체할 수 있다! 나는 postman이 더 친숙하니까 postman을 사용할 것이다.

 

이제 NestJS를 설치하자.

npm i -g @nestjs/cli

 

nest new (프로젝트 이름)으로 프로젝트를 생성하고, 패키지 매니저를 선택하면 express generator처럼 디렉토리가 만들어진다.

 

우선 app.controller.spec.ts를 지우자.

그러면 controller, module, service, main만 남을 것이다.

 

npm run start:dev

굿!

 

 

 

NestJS의 기본 구조

 

main.ts를 한번 살펴보자.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

NestFactory.create(AppModule)을 호출하고, 3000번 포트를 듣고 있다.

 

Hello world라는 텍스트가 어디서 왔는지 알아보기 위해 import한 파일들로 하나씩 이동해보자.

AppModule에 커서를 두고 ctrl+클릭을 해서 app.module.ts로 가보자 슝

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

AppModule는 보이다싶이 클래스이다.

@Module 함수는 데코레이터라는 것으로, 클래스에 함수의 기능을 추가한다.

앞으로 NestJS를 하며 계속 데코레이터를 사용할 것이므로 데코레이터에 익숙해져야 한다.

 

데코레이터의 정의는, 새 함수를 반환하여 전달 된 함수 또는 메서드의 동작을 수정하는 함수이다.

 

이번엔 app.controller.ts로 가보자.

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

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

@Get이라는 새로운 데코레이터가 있고, appService.getHello()를 리턴한다.

 

그럼 app.service.ts로 가보자.

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

우리가 화면에서 본 Hello World의 결과가 여기 있다.

 

정리를 해보면, main > 모듈 > 컨트롤러 > 서비스 순서로 파일이 연결되어 있으며, 우리가 화면에서 보는 것은 서비스에서 변경된다.

 

 

 

Controller

 

NestJS 어플리케이션은 main.ts에서 시작한다.

그리고, AppModule이라는 하나의 모듈에서 어플리케이션을 생성한다.

App 모듈은 모든 것의 루트 모듈이라고 볼 수 있다.

( + 모듈이란, 어플리케이션의 일부분을 말한다. )

출처: https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgZEug%2FbtqK2YQvlBR%2FFouKzb7YB1fqj3yNCsZfK0%2Fimg.png

 

App 모듈에는 imports, controllers, providers가 있다. Controllers에 대해 먼저 알아보자.

컨트롤러가 하는 일은 기본적으로 url로부터 요청을 받고 함수를 실행하는 것이다.

express의 라우터 같은 존재로 생각할 수 있다.

 

@Get 데코레이터는 express의 get 라우터같은 것으로,  NestJS의 @Get이 express의 app.get과 비슷하다고 생각할 수 있다.

 

예시를 하나 들어보자. app.controller.ts에 '/hello' 라우터에 대한 데코레이터를 하나 만들어보자.

 

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

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

  @Get('/hello')
  sayHello(): string {
    return 'This is hello router';
  }
}

여기서 주의할 점 !!

데코레이터는 꾸며주는 함수나 클래스랑 붙어있어야 된다! 그러므로 데코레이터(@Get)랑 함수 사이에 간격을 두면 안된다.

 

hello 라우터로 들어갔을 때 우리가 리턴한 문자열이 출력된 것을 볼 수 있다. 굿~

 

만약 @Get을 @Post로 바꾸면 Post 데코레이터가 되는 것이다. ( + 타입스크립트가 필요한 것을 자동으로 import해준다. )

 

 

 

Services

 

NestJS는 컨트롤러와 비즈니스 로직을 구분짓고 싶어한다.

 

컨트롤러는 단순히 url을 가져오는 역할로, 함수를 실행하는 역할을 한다.

나머지 비즈니스 로직은 서비스에서 처리한다. 일반적으로 컨트롤러에서 실행되는 함수들의 내용이 서비스에 담겨있다.

 

또한, 데이터베이스와 연락하는 것도 서비스에서 담당하는 부분이다.

 

우리가 앞에서 작성한 sayHello 함수를 컨트롤러와 서비스로 분리하면 아래와 같다.

 

[ app.controller.ts ]

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

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

  @Get('/hello')
  sayHello(): string {
    return this.appService.sayHello();
  }
}

 

[ app.service.ts ]

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World~!';
  }
  
  sayHello(): string {
    return 'This is hello router';
  }
}

 

이제 우리는 REST API를 만들고, 컨트롤러와 서비스를 만들 것이다.

시작하기 전에 가능한 전부 지우고, 새로 시작해...보자.... ( ╯□╰ )

컨트롤러와 서비스 파일은 삭제하고..! 모듈 파일은 아래와 같이 수정한다.

import { Module } from '@nestjs/common';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {}

 

 


참고