본문 바로가기

Backend/NestJS

NestJS - 대충 서비스 만들어보기 (1)

- NestJS

 

Nest is a framework for building efficient, scalable Node.JS server-side applications.

NestJS 공식 페이지에 있는 첫 소개 문구입니다. NestJS is a framework 는 문구 그대로 우리가 짜는 코드는 이 프레임워크 안에서

사용되며 앱의 제어 흐름은 프레임워크가 쥐게 됩니다. NestJS 를 좀 더 자세히 봐야겠다는 생각이 근래 들어 좀 들게 되었는데요.

 

현재 팀에선 NestJS 도 사용하고 있긴하지만, 대체로 관리중인 대부분의 서버들이 Express 또는 Koa 로 구성되어있습니다.

예전엔 Express 나 Koa 를 사용함으로써 자유도 높은 개발 환경이 이것저것 해볼 수 있어서 좋다고 생각하긴했지만,

근래 들어서는 이런 생각이 좀 바뀌었습니다.

 

생각이 바뀌게 된 이유를 단적으로 Express 와 비교해 몇가지 적어보자면, 우선 별도로 기능을 구현하거나 추가해야하는 라이브러리가

시스템이 커질수록 너무 많아졌고, 이를 서버 담당자들의 개인 취향에 맡기다보니 구성이 너무 제각각인게 나중에는 오히려 유지보수에

큰 비용으로 다가왔습니다.

 

둘째로는 DI 였습니다. 많은 개발자들이 얘기하는 느슨한 결합을 쉽게 가져가기 위해선 DI 는 어찌보면 필수같은데,

물론 Express 로 못하는건 아니지만, DI Container 를 직접 구현하거나 별도 라이브러리를 사용해야하죠. 이런 라이브러리로는

TypeDIAwilix 등을 선택할 수 있지만, 여기부터 이미 바로 위에 적은 첫번째 이유와 어느정도 충돌하는게 있죠.

 

세번째로는 데코레이터 및 AOP 입니다.

물론 이것도 reflect-metadata 와 같은 라이브러리를 사용해 커스텀 데코레이터를 만드는건 가능합니다.

전에 이걸 사용해서 일부 validation 용 데코레이터를 만들어 적용해봤는데, 은근히 시간을 잡아먹기도하고 어떤 경우엔 NestJS 에서 이미 지원하는 데코레이터를 굳이 다시 만들어야 하는게 시간 낭비라는 생각이 들었습니다.

이미 있는 데코레이터 또는 커스텀 데코레이터를 사용해 AOP 관점으로 횡단 관심사를 분리함으로써 자꾸 생기는 부가 기능으로 인해

코드가 더러워지는걸 깔끔하게 만들 수 있다는게 큰 장점으로 느껴졌습니다.

 

그 외에 NestJS 에서 제공하는 Batch 등도 상황에 따라 충분히 사용할 수 있어 보여 팀에서 관리하는 서버 중 Express 로 구성되어있는 것들을 최대한 NestJS 로 옮기려는 플랜을 갖고 있습니다. 그런김에 대충 간략한 서비스를 하나 만들어보면서 저도 미처 모르고있던 NestJS 의 더 다양한 기능들에 대해 알아보고 이를 포스팅으로 남겨볼까 합니다.

 

- NestJS 프로젝트 생성

 

저는 nvm 을 통해 node 16 버전으로 세팅을 해보도록 하겠습니다. 사실 cli 가 다 해주기때문에 세팅이랄것도 없지만..

 

> nvm use v16.18.0
> npm install -g @nestjs/cli

 

먼저 @nestjs/cli 를 글로벌로 설치합니다. 그리고 nest cli 를 사용해 프로젝트를 만들어보겠습니다.

 

> nest new nest-ad

 

저는 nest-ad 라는 이름의 프로젝트를 생성했습니다.

 

 

그럼 어떤 package manager 를 사용할지 묻는 문구가 나옵니다. pnpm 은 써본적이 없고, 일정 버전 이후부턴 yarn 과 npm 의 차이를

크게 못느끼고 있어서 npm 으로 갑니다.

 

 

package manager 를 선택하면 위와 같이 자동으로 필요한 구성 파일들과 함께 app module, controller, service 가 구성됩니다.

모듈도 이때 같이 설치 되므로 다시 npm install 을 할 필요는 없습니다.

 

 

설치가 완료된 후 생성된 보일러 플레이트 코드의 디렉토리 구조를 보면 위와 같습니다. TS 는 NestJS 에서 기본으로 선택된 스펙이라 당연히 구성해주는건 알고 있었지만 Prettier 와 Eslint 그리고 Jest 까지 세팅해주는건 편하네요. Express cli 는 안해줬던 것 같은데..

필요한 설정은 나중에 좀 바꿔주면 될 것 같습니다.

 

"scripts": {
  "build": "nest build",
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
  "start": "nest start",
  "start:dev": "nest start --watch",
  "start:debug": "nest start --debug --watch",
  "start:prod": "node dist/main",
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
  "test": "jest",
  "test:watch": "jest --watch",
  "test:cov": "jest --coverage",
  "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
  "test:e2e": "jest --config ./test/jest-e2e.json"
},

 

간단하게 package.json 의 scripts 쪽만 좀 살펴보겠습니다.

빌드할때는 TS compiler 그리고 dev 환경에서 코드 변경 감지는 nodemon 등이 사용될 것 같긴 하지만, 이런 명령어들이 전부 

nest 에 녹아있네요. 빌드는 nest build, dev 환경에서 띄우는건 nest start --watch 등으로 세팅되어 있는게 눈에 띕니다.

 

캡쳐나 코드를 따로 올리진 않았지만 eslint 와 prettier 는 서로 충돌이 나지 않게 플러그인이 잘 들어가있는 것 같습니다.

둘 다 상당히 최소한으로 룰이 세팅되어있어 필요한건 개발자가 개인 또는 팀의 컨벤션에 맞게 세팅하면 될 듯 하구요.

Jest 같은 경우엔 config 파일이 따로 분리되어있진 않지만 e2e 도 가능하게끔 세팅은 해주니, 초기 프로젝트 세팅할 때 은근히 공수를

잡아먹는 것들 대부분을 해결해주는 느낌입니다.

 

> npm run start:dev

 

 

대충 볼 파일들은 봤으니 dev 모드로 실행해보겠습니다.

사실상 루트인 app module 에 의존성들이 등록되고, 라우터가 등록된 후 Nest application 이 시작되는 로그를 볼 수 있습니다.

main.ts 의 bootstrap 코드를 보면 3000 포트로 실행하게끔 되어있으니 브라우저에서 localhost 에 3000 포트로 접근해봅니다.

 

 

app.controller.ts 와 app.service.ts 만 대충 봐도 알 수 있듯이 위처럼 국민 문구인 Hello World 가 나오는걸 볼 수 있습니다.

 

- NestJS 가 지원하는 다양한 기능들

 

  • @nestjs/config 를 사용한 동적 config 구성
    • @nestjs/config 모듈을 사용해 config 를 구성할 수 있습니다. 앞에 동적이라고 붙은건 대부분의 prodution 을 운영하는 회사들은 다 그렇게 하긴 하겠지만, 예를들어 특정 DB 의 host 등 접속 정보가 production 환경일 때, staging 환경일 때, 로컬일 때 다 다를 수 있습니다. 이런 경우 환경에 따라 config 를 동적으로 구성할 수 있고, 이런 것들을 환경변수에 세팅하고 dotenv 를 사용하는 것까지 이번 기회에 볼까 합니다.
  • 다양한 데코레이터
    • NestJS 는 좀 전에 cli 로 생성한 보일러 플레이트 코드에서도 볼 수 있듯이 @Controller, @Service, @Get, @Post 등 여러가지 데코레이터를 제공하고 커스텀 데코레이터도 생성할 수 있습니다.
    • 기본 제공 데코레이터들도 활용하면서 커스텀 데코레이터를 생성해 AOP 관점에서 여러 횡단 관심사를 분리해보겠습니다.
  • 헬스 체크
    • 위에 기본 제공하는 데코레이터 쓰면 되는거긴 한데.. 이것도 간단하게 볼 예정입니다.
  • CQRS
    • Command 와 Query 의 책임을 분리하는건 NestJS 에서 @nestjs/cqrs 모듈을 사용할 수 있습니다.
    • 이 모듈은 저도 아직 써본적은 없고 다른 프레임워크를 쓴다고 cqrs 를 할 수 없는건 아니지만, 얼마나 모듈화가 잘 되어있는지 확인해 볼 예정입니다.
  • ORM
    • NestJS 는 typeorm, sequelize 와 같은 ORM 과의 통합 또한 마찬가지로 모듈로 제공합니다.
    • 개인적으로 현 회사에선 ORM 을 거의 안쓰고있는데.. 좋은 기회가 될 것 같습니다.
  • 그 외에 인터셉터, 미들웨어, 테스트 등

 

제가 위에서 NestJS 프로젝트를 만들 때 nest-ad 라고 이름을 만들었는데요.

저는 다음 포스팅부터 간단한 광고 서비스 서버를 만들면서 위에 소개한 여러 기능들을 필요한 부분에 하나씩 붙여가며 살펴보려고 합니다.

유저는 너무 식상해서 제맘대로 사내 도메인 중 하나 가져와봤는데 광고 서비스라고 해봐야 거창한건 아니고, 그냥 흔히 생각하는 유저 서비스의 유저가 광고로만 바뀌었다고 보시면 됩니다. 광고 컨텐츠 불러오고 등록하고 뭐 이런 것들..