Node.JS의 새로운 파트너 NestJS는 왜 탄생했을까?

이 글은 [Node.js 백엔드 개발자 되기]에서 발췌했습니다.
골든래빗 출판사

왜 NestJS가 출현했을까?

기존에는 Node.js와 익스프레스를 사용해 웹 서버를 구축하고 서비스를 만들었습니다. 익스프레스를 사용해서 서버를 구축할 때, 먼저 고민했던 부분이 무엇이었나요? 바로 디렉터리 구조입니다. 별거 아닌 것 같지만 구조에 따라서 아키텍처가 변경되므로 간단한 문제는 아닙니다. 익스프레스에서는 router > controller > service 디렉터리 구조로 만들어서 유저로부터의 요청이 전달되도록 했습니다. 문제는 익스프레스를 사용하는 모든 사람이 이런 아키텍처 문제를 고민해야 한다는 겁니다. 코드 작성자 이외의 사람이 코드를 읽을 때 불편함이 있습니다. NestJS는 이러한 문제를 해결한 웹 서버 프레임워크입니다. NestJS는 서버 개발 시의 아키텍처를 누구든 비슷하게 설계하도록 아키텍처 문제를 해결하는 데 중점을 두고 있습니다.

현업에는 다양한 요구사항이 있습니다. 또한 레거시와 신규 기술이 공존합니다. 그래서 익스프레스와 네스트 모두를 알고 있어야 적절하게 활용할 수 있습니다. 이제부터 네스트가 왜 출현했는데 어떤 특징이 있는지 알아보겠습니다.

 

1. NestJS 소개

NestJS네스트제이에스는 자바스크립트 최신 기능을 사용하는 웹 프레임워크입니다.2 좋은 구조로 애 플리케이션을 작성해 프로젝트의 복잡성을 잘 관리하는 것을 목표로 합니다. NestJS로 코드를 작 성해보기 전에 우선 NestJS가 무엇인지 왜 만들었는지, 왜 익혀두면 좋은지 알아보겠습니다. 우리가 함께 배워볼 NestJS는 다음과 같은 특징이 있습니다.

1 Node.js에서 실행하는 서버 사이드 프레임워크입니다.

2 타입스크립트를 완벽하게 지원합니다.

3 자바스크립트의 최신 스펙을 사용합니다. 그러므로 바닐라 자바스크립트를 사용한다면 babel 사용이 필수입니다.

4 HTTP 요청 부분은 추상화된 코드를 제공해 익스프레스와 패스티파이(Fastify)를 사용할 수 있습니다.

쉬어 가는 코너 : 패스티파이 소개

패스티파이(https://www.fastify.io/)는 익스프레스와 하피Hapi에 영감을 받은 웹 프레임워 크입니다. 특징은 다음과 같습니다.

• 고성능 : 초당 최대 3만 개의 요청을 처리할 수 있습니다.

• 확장성 : hooks, plugins, decorator를 사용해 확장할 수 있습니다.

• 스키마 기반 : JSON 스키마를 사용해 데이터의 유효성 검증을 할 수 있습니다.

• 로깅 : 로깅은 매우 중요하지만, 비용이 큽니다. 이에 오버헤드가 매우 적은 pino4를 로깅 라 이브러리로 사용합니다.

• 개발자 친화적 : 성능과 보안에 대한 타협을 하지 않으면서도 사용이 간편합니다.

2. 익스프레스와 NestJS 비교하기

익스프레스는 최소한의 기능을 제공하는 반면 NestJS는 상대적으로 조금 더 많은 기능을 제공합니다. NestJS의 목표 중의 하나가 자바스크립트로 만드는 웹 서버 프레임워크의 아키텍처 문제를 효과적으로 해결하는 겁니다. NestJS가 지금 주목받는 이유로 아키텍처 문제를 잘 해결하고 있기 때문으로 생각합니다.

서버 개발에 아키텍처는 왜 필요할까요? 바로 쉽게 테스트하고, 쉽게 확장이 가능하고, 각 모듈 간의 의존성은 줄이도록 해야 유지보수가 쉬운데 좋은 아키텍처는 이런 목표를 달성할 수 있게 해줍니다. 익스프레스 사용 경험이 있으시다면 서버를 만들 때 폴더 구조들을 어떻게 잡을지 고민을 했을 겁니다. NestJS에서는 컨트롤러를 어디에 둘지, 서비스를 어디에 둘지, 미들웨어를 어떤 식으로 작성할지 등 개발자의 고민거리를 미리 정리해두었습니다. 이를 데코레이터 기반으로 제공하고 있어서, 배우기가 쉽습니다.

3. NestJS 둘러보기

NestJS의 핵심 기능으로 의존성 주입을 들 수 있습니다. 의존성 주입은 모듈 간의 결합도를 낮춰서 코드의 재사용을 용이하게 합니다(8.5절 ‘의존성 주입하기’). 즉, 모듈 내에서의 코드의 응집도는 높여서 모듈의 재사용을 꾀하고 모듈 간에는 결합도를 낮춰서 다양한 아키텍처에서 활용할 수 있게 해줍니다. 이를 위한 장치들로 모듈, 가드, 파이프, 미들웨어, 인터셉터 같은 모듈과 코드의 의존 관계를 구성하는 프로그래밍적 장치들이 있습니다.

기존의 Node.js 생태계에서 자주 사용하는 기능을 통합하고 있으며 기본적으로 RDB와 NoSQL의 연동, 세션 처리, 문서화, 테스트 지원, 로깅, 태스크 스케줄링 등 상업용 서버에서 필요한 대부분의 기능을 제공합니다. 새로 필요한 기능이 있다면 모듈이나 커스텀 데코레이터를 만들어서 다른 코드들에 손쉽게 적용하도록 지원을 합니다. NestJS의 기능들은 다음의 그림에 정리해두었습니다. 둥근 사각형 모양으로 되어 있는 주제들은 이 책에서 다루는 내용입니다.

NestJS에서도 데코레이터를 많이 사용합니다. 데코레이터를 만드는 것은 까다롭지만 사용이 매우 직관적이고 간편하기 때문에 NestJS에서는 데코레이터를 적극적으로 사용하고 있습니다. 일반적으로 @ 함수명을 클래스나 함수의 윗 줄에 명시하고 적절한 매개변수를 추가하면 됩니다.

《Node.js 백엔드 개발자 되기》에서는 HTTP에 관련된 데코레이터를 굉장히 많이 사용합니다. 다음 그림에 HTTP 요청과 관련된 데코레이터를 추가해두었으니 참고해주세요.

HTTP 부분은 익스프레스를 사용하고 있으므로 익스프레스와 대응되는 데코레이터들이 모두 있습니다. 다음 표를 참고해주세요.

NestJS는 익스프레스를 품고 있기 때문에 익스프레스 기반의 미들웨어를 거의 대부분 사용할 수 있습니다. 정확하게는 HTTP 요청과 응답에 익스프레스의 Request와 Response 객체를 기본으로 사용합니다. 성능이 중요하다면 패스티파이로 바꿔 쓸 수도 있습니다. 이는 아키텍처 구조를 유연하게 잘 만들었기 때문입니다.

빠른 성능이 필요한 부분에서는 패스티파이를 사용하고 그렇지 않은 부분에서는 막강한 서드파티 의 지원을 받는 익스프레스를 쓸 수 있으니 NestJS는 성능과 확장성, 유연함을 모두 가져갈 수 있습니다. npm에서 NestJS의 내려받기 수를 살펴봅시다. 최근 1년간이지만 사용하는 사람이 거의 2배로 늘었습니다. 꾸준하게 성장한다는 겁니다. 사용처도 계속 늘어나고 있으며 현재는 오토데스크, 깃랩, 레드햇, IBM, 젯브레인스 등의 기업에서 사용합니다. 국내에서는 당근마켓에서 사용합니다.

 

 

4. NestJS 설치하고 실행하기

이왕 네스트를 알아봤으니 설치 방법까지 다뤄보겠습니다. NestJS는 3가지 방법으로 설치할 수 있습니다. 첫 번째는 NestJS 구동에 필요한 라이브러리들을 모두 손으로 한땀한땀 설치하고 설정하는 방법입니다. 사실 node.js의 익스프레스에는 설치해야 하는 패키지가 별로 없기 때문에 이 방식을 많이 사용합니다. 하지만 NestJS는 설치해야 하는 패키지들이 더 많아서 설정을 더 해야 합니다.

그래서 NestJS에서는 간편하게 프로젝트를 생성하도록 nest-cli 패키지를 제공합니다. 설치를 하고 나면 nest 명령어를 사용해 쉽게 프로젝트를 생성할 수 있습니다. 이것이 두 번째 방법입니다.

마지막은 nest 명령어로 설치하는 저장소를 직접 git clone 명령어로 개발자의 디렉터리에 내려받은 후 자신에게 맞도록 설정을 변경하는 방법입니다. 《Node.js 백엔드 개발자 되기》에서는 nest-cli를 사용하는 두 번째 방법을 대부분 사용할 예정이지만, 처음에는 첫 번째 방법을 사용해서 hello-nestjs를 웹브라우저로 살펴보겠습니다. 다른 방법으로 설치를 하면 더 간단하지만 지금은 배우는 단계이므로 많은 설정 파일을 알아두는 것이 더 이득이기 때문입니다.

4.1 의존성 패키지 설치하기

[01 단계] 프로젝트 디렉터리를 생성하고 의존성 패키지를 설치합시다. 디렉터리명은 hello-nestjs로 이름 짓겠습니다.

$ mkdir chapter8
$ cd chapter8
$ mkdir hello-nestjs
$ cd hello-nestjs

[02 단계] 디렉터리를 만들었다면 필요한 패키지들을 설치해봅시다. 행내림 없이 한 줄로 명령을 작성해 실행하세요.

$ npm i @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata typescript

[03 단계] 설치가 완료되었다면 package.json을 열어봅니다(버전은 설치 시점에 따라 조금씩 다를 수 있습 니다).

▼ 패키지 설정

chapter8/hello-nestjs/package.json
{
   "dependencies": {
      "@nestjs/common": "^9.0.3", // ❶  NestJS의 공통 코드들
      "@nestjs/core": "^9.0.3", //  NestJS의 핵심 코드(가드, 미들웨어, 파이프 등)
      "@nestjs/platform-express": "^9.0.3", // ❸ HTTP 요청에 익스프레스 사용
      "reflect-metadata": "^0.1.13", // 데코레이터 사용 시 필수
      "typescript": "^4.7.4" // 타입스크립트 사용 시 필수
   }
}

설치한 패키지들을 하나씩 살펴보면서 간략하게 설명드리겠습니다. ❶ @nestjs/common은 실제 프로젝트에서 사용할 대부분 코드가 들어 있습니다. 데코레이터 (decorator)로 사용하는 함수들의 클래스들이 대표적입니다. @nestjs/core는 @nestjs/common에서 사용하는 코드가 들어 있습니다. 가드(guard), 미들웨어(middleware), 파이프(pipe) 등을 만 드는 핵심 코드가 있습니다. ❸ @nestjs/platform-express는 이전에 말씀드린 대로 HTTP 요 청/응답 부분을 감싸서 익스프레스의 req, res 객체를 사용하는 라이브러리입니다.

4.2 타입스크립트 설정하기

NestJS는 타입스크립트를 완벽히 지원하기 때문에 타입스크립트를 사용하면 더 편리하게 개발할 수 있습니다. 그러므로 지금부터는 타입스크립트로 코드를 작성하겠습니다. 타입스크립트는 자바스크립트에 타입을 추가한 언어라고 생각하면 되며, 자바스크립트로 트랜스파일됩니다. 그러므로 어떤 식으로 컴파일할지 설정을 추가해야 합니다. 부록 A에서는 타입스크립트 문법을 알려줍니다. 익숙하지 않은 분이라면 먼저 학습하기 바랍니다. 특별히 어려운 문법을 사용하지는 않으므로, 책에 있는 코드를 이해하는 데 불편함이 없도록 필요할 때마다 문법을 알려드리겠습니다.

[01 단계] 타입스크립트를 설정하겠습니다. 타입스크립트 설정 파일은 tsconfig.json 파일이며 프로젝트의 루트 디렉터리에 위치시키면 됩니다. tsconfig.json 파일을 만들고 다음과 같이 작성합시다.

 

▼ chapter8/hello-nestjs/tsconfig.json

{
   "compilerOptions": { // ❶ 컴파일러 옵션
      "module": "CommonJS", // ❷ 모듈 시스템
      "target": "ESNEXT", // ❸ 사용할 ES 버전
      "experimentalDecorators": true, // ➍ 데코레이터를 사용할지 여부
      "emitDecoratorMetadata": true // ➎ 데코레이터의 메타 데이터를 같이 내보낼지 여부
   }
}

❶ 타입스크립트의 컴파일러 옵션은 compilerOptions에 설정합니다. ❷ 컴파일 시 모듈 시스템을 선택할 수 있으며 NodeJS의 모듈 시스템은 CommonJS이므로 CommonJS로 넣어줍니다. ❸ target에는 컴파일 시 사용할 ECMA 버전을 적어줍니다. ESNEXT를 설정하면 최신 버전으로 컴파일을 해줍니다.

➍ experimentalDecorators와 ➎ emitDecoratorMetadata는 데코레이터 관련 부분입니다. NestJS에서는 데코레이터를 매우 매우 많이 사용하므로 꼭 필요한 옵션이라고 할 수 있습니다. ➍ experimentalDecorators는 데코레이터를 사용할지 여부입니다. 타입스크립트 5.0 버전부터 정식으로 지원합니다. ➎ emitDecoratorMetadata는 타입스크립트를 자바스크립트로 컴파일 시 데코레이터가 설정된 클래스, 함수, 변수, 객체의 메타 데이터를 함께 넣어줄지 여부를 선택합니다. 메타 데이터에는 테코레이터를 달아준 곳이 함수인지, 클래스인지 변수인지 에 대한 여부와 매개변수가 있다면 해당 타입, 그리고 결괏값을 포함합니다. 메타 데이터를 넣을 때 의존성 패키지로 설치한 reflect-metadata가 사용됩니다. 즉 reflect-metadata와 emitDecoratorMetadata는 함께 설정이 되어야 합니다. 타입스크립트 설정값 자체는 몇 개 없습니다만, 모르고 사용하는 것보다는 알고 사용하는 것이 당연히 좋습니다.

박승규


아직도 개발이 재미 있는 15년차 천상 개발자입니다. 웹 개발, 게임 백엔드 개발, 플랫폼 및 인프라 개발 등 다양한 영역을 경험했습니다. 현재는 카카오엔터테인먼트에서 백엔드 개발자로 일합니다.


현) 카카오엔터테인먼트 페이지 서비스 개발팀
전) 트리노드 (포코팡, 포코포코) 서버 개발자
전) NHN Japan 플랫폼 개발팀

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내