NestJS 독학 - 소개

김정원·2020년 10월 17일
1

NestJS 독학

목록 보기
1/4

소개

NestJS는 Express를 기반으로 돌아가는 (혹은 Fastify) NodeJS의 서버 프레임워크이다. typescript를 네이티브로 지원하기 때문에 typescript에서 사용하기 편하고 데코레이터 클래스를 통해서 다양한 기능을 정형화/구조화 하여 설계할 수 있다. 때문에 코드 스타일이 통일되어 협업 프로젝트 진행 시 각자 다른 스타일로 커뮤니케이션을 좀 더 자연스럽게 할 수 있다. 또한 CLI를 통해 보일러플레이트 코드를 생성하여 간단하게 프로젝트를 시작할 수 있다. 하지만 대부분의 코드가 클래스구문을 통해 설계되기 때문에 자바스크립트 클래스에 대한 확실한 이해가 필요하다.


설치

NestJS는 React와 마찬가지로 보일러플레이트를 사용해 프로젝트를 생성할 수 있다. @nestjs/cli 를 설치하여 CLI도구를 설치해 준다.

yarn global add @nestjs/cli

CLI를 설치한 뒤 다음 명령을 통해서 NestJS 프로젝트를 만들 수 있다. 시간이 조금 걸린다.

nest new *project_name*

명령을 실행한 폴더 내에 project_name에 해당하는 폴더를 생성한 뒤 그 안에서 초기화를 해준다.

폴더 구조를 살펴보면,

src
 | main.ts                    # 앱의 시작점
 | app.module.ts              # 앱의 루트모듈
 | app.controller.ts          # 앱의 컨트롤러
 | app.service.ts             # 앱의 서비스

이런 구조로 되어있다. 하나씩 코드를 살펴보자


구조

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();

bootstrap 이라는 함수를 만든 뒤 바로 실행한다. 구조를 보고 생각 해 봤을때는 서버를 동작하게 해주는 말단지점으로 파악된다. 함수명은 임의로 지어도 잘 작동한다. NestFactory 클래스를 이용해 AppModule 클래스를 받아와서 app객체를 만든다. 그리고 그 listen메소드를 사용해서 포트를 열어준다. 기존의 express를 사용할 때와 비슷한 느낌이 있다.

app.module.ts

그렇다면 NestFactory에서 받아오는 AppModule의 구조를 살펴보자

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

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

데코레이터가 사용되었다. 모양을 봤을때는 class AppModule을 꾸며주는 역할로 보인다. 한 눈에 봤을 때는 imports, controllersproviders를 배열로 받아서 AppModule 클래스를 만들어주는 역할을 하는 것 같다. 여기저기 흩어져있는 코드를 AppModule로 묶어서 export한 뒤 NestFactory에서 받아서 서버를 만들어주는 걸로 예상된다.

app.controller.ts

먼저 controllers에서 배열로 받은 AppController를 확인해 보자

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();
  }
}

이번에도 역시 데코레이터가 사용되고 있다. 아무래도 Nestjs는 데코레이터를 적극적으로 사용해서 class 구조를 조작하는 듯 하다.

하나씩 살펴보면 @Controller 데코레이터를 달고있는 AppController클래스에서 AppService클래스를 인자의 타입으로 받은 뒤 @Get 데코레이터를 통해 AppService 타입 내의 getHello 메소드를 호출해 사용하는 듯 하다. 타입 지정만 받았을 뿐인데, 어떻게 그 안에 있는 메소드를 사용할 수 있는지는 모르겠다. 아마 app.module.ts내에서 providers로 전달됐기 때문에 호출되는 게 아닐까 추측

@Controller 데코레이터를 통해 Controller 클래스를 정의해 줄 수 있는 듯하다. ControllerExpress에서 Route 기능을 대신 해 주는 듯 하고 각 Controller안에 @Get, @Post, @Put, @Delete 등의 HTTP request를 정의하는 모양이다.

app.service.ts

마지막으로 providers의 배열로 받고 AppController에서도 Controller에서 전달받은 AppService 클래스를 살펴보자

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

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

이번에도 역시 @Injectable 데코레이터를 사용해 클래스를 정의한다. 위의 app.controller.ts에서 사용한 getHello메소드가 정의되어 있다. 'Hello World!' 라는 문자열을 출력하는데 실제로 서버를 작동시키고 localhost:3000으로 접속하면 화면에 Hello World! 라는 문자열이 출력된다. 이를 통해 providers에 전달된 클래스의 메소드를 Controller를 통해서 사용할 수 있다고 확인할 수 있다.

지금까지의 구조를 대략적인 구조를 이미지로 설명하자면 아래와 같다.

전체적으로 NestJS는 분리할 수 있는 단위의 기능들을 모듈로 정의해서 가능한 독립적으로 사용한다. 물론, 다른 모듈과 상호작용을 하게 설계할 수도 있는 듯 하다. 가장 근본이 되는 App Module을 통해 또 다른 모듈을 imports를 통해 배열로 전달받을 수 있다. 하나의 모듈 내에는 복수의 ControllerService도 존재할 수 있다. 하지만 하나의 단위 기능은 모듈로 묶어야 NestJS를 효율적으로 사용할 수 있다.

앞으로 Controller, Service, Module을 하나씩 살펴보자.

profile
영원히 공부중

0개의 댓글