[[분류:웹 프레임워크]] [include(틀:웹 프레임워크)] ||<-2>
'''{{{+1 Nest.js}}}''' || ||<-2> [[파일:nest_logo.svg|width=100%]] || || '''개발''' ||[[https://github.com/kamilmysliwiec|Kamil Mysliwiec]] || || '''종류''' ||[[백엔드]] [[웹 프레임워크]] || || '''언어''' ||[[TypeScript]]([[JavaScript]]) || || '''버전''' ||[[https://github.com/nestjs/nest/releases/tag/v10.2.2|v10.2.2]] || || '''라이선스''' ||[[MIT 라이선스]] || ||<-2> [[https://nestjs.com/|[[파일:홈페이지 아이콘.svg|width=20]]]] | [include(틀:GitHub 로고,링크=nestjs/nest,크기=20)] || [목차] [clearfix] == 개요 == [[Node.js]] 런타임 위에서 동작하는 [[TypeScript]]용 [[오픈 소스]] [[백엔드]] [[웹 프레임워크]]. == 상세 == 노드 생태계에서 거의 기본처럼 쓰였던 [[Express.js]]에 비해 제어 역전성을 가지는 [[프레임워크]]적 성향이 더욱 강하며, NestJS가 상당한 아이디어를 차용한 자바 생태계의 [[Spring(프레임워크)|Spring]]과도 자주 비교된다. 애초에 [[Angular]]로부터 영감을 받은 프로젝트라 구조적으로 유사성이 많이 보인다. 다만 NestJS 자체는 독립적인 프레임워크가 아니며, 내부적으로 기존의 웹 프레임워크들의 기능을 일관된 API로 노출해 주는 거대한 어댑터(Adapter)에 가깝다. 현재까지는 공식적으로 [[Express.js]] 및 Fastify를 지원한다. == 특징 == === 구조화된 아키텍처 === NestJS는 코드를 거시적인 관점에서 Provider, Controller, Module로 분리하며 이런 작은 컴포넌트들끼리의 조합(DI)을 통해 전체 애플리케이션을 완성한다. ==== Provider ==== {{{#!syntax typescript @Injectable() export class Service {} }}} nest의 가장 간단하고 작은 단위의 컴포넌트를 표현한다. 기본적으로 {{{@Injectable()}}} 데코레이터로 나타내며 이름에서도 알 수 있듯이 프로바이더는 다른 프로바이더나 컨트롤러에 주입(Inject)될 수 있다. Provider의 종류로는 가장 간단한 Service부터 시작해서 Middleware, Pipe, Guard, Interceptor 등이 존재한다. ==== Controller ==== provider들이 비즈니스 로직을 추상화한다면, Controller는 실제 외부와의 통신과 라우팅 등을 담당한다. 주로 쓰이는 것은 당연히 HTTP지만 추가적인 모듈을 통해 게이트웨이([[웹소켓]]), [[TCP]], 이벤트 컨슈머(Kafka), [[gRPC]] 등의 계층도 컨트롤러에서 사용할 수 있다.[* 몇몇 경우는 {{{Transporter}}}이기 때문에 앱 초기화 전 별도로 마이크로서비스로 선언해야 한다.] ==== Module ==== {{{#!syntax typescript @Module({ imports: [], controllers: [], providers: [], exports: [] }) class Module {} }}} 수평적으로 흩어진 Provider와 Controller들을 논리적인 기능이나 도메인에 따라 하나로 묶어주는 역할을 하며, 재사용성을 높여준다. 예를 들어 고객의 주문을 받는 {{{BucketController}}}, 주문을 외부 K-V 스토어에 캐싱하는 {{{CacheService}}}, 고객의 신용카드 정보를 확인하는 {{{CreditService}}}, {{{order}}}라는 토픽으로 이벤트를 발행하는 프로듀서 {{{ProduceOrder}}} 컨트롤러가 존재할 때, 이러한 여러 컴포넌트를 하나의 기능으로 묶어 {{{OrderModule}}}로 분리할 수 있다. 단순히 코드를 부분이나 폴더로 묶어주는 것 뿐만 아니라 계속해서 재사용될 기능을 정의할 수도 있다. 가령 레디스 서버에 요청을 주고받는 서비스를 앱의 다른 부분에서도 사용해야 한다면, {{{RedisModule}}} 등으로 이를 모듈화한 후 {{{exports}}}에 노출할 provider를 나열하면 다른 모듈에서 그 서비스를 종속성으로 주입할 수 있다. Nest개발시 흔히 자주 쓰이는 모듈로는 {{{ConfigModule}}}, {{{HttpModule}}} 등이 존재한다.[* 간혹 {{{ConfigModule}}}로 다른 모듈을 설정해야 하는 경우도 종종 존재하는데, 이럴때는 다른 모듈의 초기화를 별도의 콜백 안에서 수행하기 위해 {{{Dynamic module}}}기능을 사용해야 한다.] 만약 모듈이 너무 크거나 초기화에 오래 걸린다면, {{{LazyModuleLoader}}} 클래스를 주입해 해당 모듈을 lazy-loading하도록 설정할 수도 있다. 보통 ~~안그래도 가뜩이나 느린~~ 자바스크립트 코드의 초기 시작(cold start)속도가 크게 영향을 끼칠 수 있는 스케줄링 작업, 람다, 웹훅 등에서 사용될 때 유용하다. === 데코레이터 === 데코레이터는 여러 프로그래밍 언어에서 사용되는 개념이지만, 자바스크립트 생태계에서는 아직 조금 낯선 개념일 수 있다. NestJS 에서는 데코레이터 개념을 채용해서 사용하고 있다. HTTP route를 위한 데코레이터, 요청의 param에 대한 데코레이터 등 미리 만들어둔 데코레이터들이 있으며, 사용자가 정의해서 추가할 수 있다. === Express와의 차이점 === 기존의 노드 개발 환경에서 사실상 유일했었고 현재도 사실상 업계 표준으로 인정받는, 그야말로 자바스크립트 생태계에 막대한 영향력을 끼치는 프레임워크 중 하나다 보니 두 프레임워크가 비교되는 일이 굉장히 잦다. express는 간단한 {{{req-res}}} 미들웨어 콜백 스타일과 당시 주류였던 commonjs 특유의 제약 없는 모듈 시스템이 합쳐져 굉장히 프로젝트 구조가 자유로운 프레임워크가 되었고, 비즈니스 로직이 복잡하지 않을 때는 거의 한 파일에 코드를 다 집어넣어도 돌아가는[* 이런 장점(?) 덕분에 node런타임을 지원하는 대부분의 람다 서비스에서는 전용 SDK를 제공하더라도 express랑 비슷한 형태로 제공해준다. 그러면 정말이지 한 파일에 람다 코드를 다 작성하게 되는 일이 빈번하다.] 간결성과 유연성을 가지게 되었다. 다만 서버사이드 자바스크립트 생태계가 점점 발전하고 요구사항이 커지면서 명확한 구조도, [[코딩 스타일]]도 없는 express로는 협업 등에 문제가 생겼고 이걸 해결하기 위해 express MVC등 여러 패턴들이 등장했지만 그중 누구도 nest만큼 성공적이지 못했다. 재미있는 점은 nest가 모든 걸 처음부터 하나하나 개발하지 않고 기존 express 생태계의 기술들을 가져다 사용했다는 부분인데, {{{typeORM}}}, {{{ClassValidator}}}, {{{cookie-parser}}}, {{{axios}}}, {{{multer}}}, {{{ClassTransformer}}}, {{{passsport}}} 등 기존의 익스프레스 개발자라면 반갑게 느껴질 만한 패키지들을 그대로 사용하거나, nest에 어울리게 래퍼로 감싸서 제공하는 것을 볼 수 있다. 게다가 사실 내부적으로는 express를 사용하기 때문에 결국 {{{req}}}, {{{res}}}등의 객체들을 사용할 수도 있다. 이러한 express 친화적인 부분들이 기존의 개발자들에겐 다른 프레임워크에 비해 훨씬 커다란 장점으로 다가오고, 기존 프로젝트의 마이그레이션 역시 쉽게 진행될 수 있도록 뒷받침해준다는 사실 또한 큰 특징이라 볼 수 있다.[* 다만 Spring 등의 프레임워크에 비해 상대적으로 그렇다는 말이지 fastify나 koa등의 express식 스타일을 거의 비슷하게 따라가는 다른 프레임워크들에 비해선 러닝커브가 압도적으로 높은 것이 사실이다.] Express, Nest를 Python 백엔드 프레임워크에 비유하자면 Express는 Flask고, Nest.js는 Django에 비유할 수 있다. === TypeScript Native === 기존의 자바스크립트 프레임워크와는 다르게, '타입스크립트를 지원할 수 있다'가 아니라 처음부터 '타입스크립트로 쓸 것을 가정하고' 만들어졌다.[* 이는 [[Angular]]와도 상당히 비슷한 특징이다.] 물론 쓸려면 js로도 쓸 수는 있으며 자세한 것은 후술. 타입스크립트를 단순한 기초 이상으로 활용하며 이 프레임워크의 핵심 컨셉 자체에 각종 타입스크립트 특수적인 개념들이 들어가기 때문에 타입스크립트를 모른다면 러닝커브가 상당히 높을 수 있다. 반대로 [[앵귤러]] 개발자들이었다면 provider, 데코레이터, Compodoc, DI 패턴 등 친숙한 개념들이 많아 가장 배우기 쉽다. 가장 눈에 띄는 특징으로, 앵귤러만큼 데코레이터를 도처에 활용한다. 그 외에도 표준화된 인터페이스의 사용({{{OnModuleInit}}} 등), 생성자 DI 등을 찾아볼 수 있다. 타입스크립트의 타입을 활용한 DTO를 사용한다. 즉 다음과 같이 선언한 클래스는{{{#!syntax typescript class Dto { constructor( private readonly name: string, private readonly age: number, private readonly isMan: boolean, ) {} } }}}어떠한 별도의 데코레이터 등이 없이도 자동으로 클라이언트에 전달되는 시점에서{{{#!syntax typescript @Controller() class SomeController { @Get() returnDto(): Dto { return new Dto('namuwiki', 123, false) } } }}}아래와 같이 자동으로 직렬화된다.{{{#!syntax json { "name": "namuwiki", "age": 123, "isMan": false } }}} 또한 {{{classTransformer}}}나 {{{classValidator}}}등을 이용해서 추가적인 비즈니스 로직을 작성할 수도 있다. 주의할 점으로, DTO 클래스에 부분적인 변경을 가하기 위해서는 타입스크립트의 내장 {{{Partial}}}, {{{Omit}}}등을 사용하기보단 {{{@nestjs/mapped-types}}}를 사용하는 것이 좋은데, 이는 내장 타입은 단지 mapped-type이기 때문에 데코레이터가 붙은 클래스에 사용하면 런타임에서 읽어봐야 할 정보다 날아가기 때문이다. 사실상 100% 타입스크립트로 쓰일 것을 가정하고 만들어진 프레임워크지만, 자바스크립트로도 작성이 불가능한 것은 아니다. 다만 100% 네이티브로 돌아가는 것은 아니고 자바스크립트 스캐폴딩 기준으로는 바벨을 사용해 데코레이터를 컴파일한다. 다만 이 과정이 느리기 때문에 [[SWC]]를 사용할 수도 있다(이는 타입스크립트 코드베이스에서도 마찬가지). [[https://github.com/manuschillerdev/nestjs-swc|swc용 스타터 템플릿]]을 보면 성능 차이가 얼마나 나는지 실감할 수 있다. === 강력한 [[CLI]] === [[https://github.com/nestjs/nest-cli|#]] 상당히 압도적인 특징 중 하나인데, 기존 스프링 등과 같이 파일 구조가 복잡하고 동시에 여러 부분을 변경할 필요가 있는 프레임워크는 매번 빈번히 여러 파일을 수정하기도 불편하고 실수가 발생하기 쉬웠기에 [[IDE]] 레벨에서 여러 작업의 자동화를 지원해왔다. 다만 자바스크립트의 경우는 일관된 구조도 없거니와 통합적인 개발 환경이 통일되지 않고 무엇보다 매번 같은 작업을 반복해야 한다면 해당 프레임워크의 만족도가 떨어질 수 있는데, nest의 경우 강력한 cli를 만들어 이를 해결했다. 예를 들어{{{#!syntax typescript $ nest g res users}}}를 입력하면 CRUD 컨트롤러, 서비스, 유닛 테스트, DTO, 심지어 엔티티 정의까지 자동으로 만들어 준다. 따라서 cli를 잘 활용할수록 nest 개발중 기능 추가 등이 상당히 편해지는 것을 느낄 수 있다. 또한 다양한 cli플러그인을 사용해 기능을 확장할 수 있다. 대표적인 예시가 {{{@nestjs/swagger}}}.[* 타입스크립트의 메타데이터만으로는 자동으로 OAS문서를 생성하기에 충분한 정보를 찾을 수 없기 때문에 컴파일 전 별도의 파서를 실행해 필요한 타입 정보를 얻어내기 위해서 cli 플러그인이 필요하다.] == 사용해 보기 == === 프로젝트 생성 === {{{#!syntax sh $ npm i -g @nestjs/cli $ nest new project-name # 또는 $ npx -y @nestjs/cli new project-name }}} {{{project-name}}}라는 이름으로 가장 기본적인 보일러플레이트 프로젝트를 생성해 준다. 만약 자바스크립트로 프로젝트를 생성하고 싶다면 {{{-l javascript}}} 옵션을 줄 수 있다. == NestJS를 사용하는 기업 == * [[리디주식회사|리디]][* NestJS 프로젝트에 지속적인 기여와 재정적인 후원을 하고 있다.[[https://opencollective.com/ridi-corporation|#]]] * [[토스(금융)|토스]] * [[아디다스]] * [[AutoCAD]] * Neo4j * Roche * [[당근(플랫폼)|당근]] == 관련 문서 == * [[웹 프레임워크]] * [[Node.js]] * [[Express.js]] * [[TypeScript]]