NestJS (1)

2 분 소요

Intro

필자에게 개발자란 해결하려는 문제를 소프트웨어 개발로 풀어내는 사람이라고 생각한다. 특정 하나의 프로그래밍 언어의 스페셜리스트가 되기보단 여러 언어들의 패러다임과 장단점을 파악하고 다룰 줄 알아야 해결하려는 문제에 올바른 접근을 할 수 있다고 생각한다. 이런 생각으로 필자는 다양한 언어를 공부와 프레임워크를 경험하고 공부해왔다.(c, java, python, go, js/ts, spring, flask, echo, nodejs, react, vue, express, nestjs…)

아직도 이 배움에 끝은 없고 완벽하지도 않지만 지금까지의 공부해온 경험으로 개인적인 선호도를 따졌을 때 Typescript라는 언어와 NestJS라는 프레임워크 조합이 가장 좋았다. 지극히 개인적으로 생각한 장점은 아래와 같다.

  1. 공식문서가 정말 잘 정리되어있다. 개발공부를 할 때 필자는 주로 공식문서를 통해 기초를 다지는데 많은 공식문서들의 스타일이 다르다. NestJS의 공식문서는 독자친화적으로 사람이 쓴 글 같아서 좋았다. 중간마다 해당 프레임워크의 철학에 대한 문장도 있고 무엇보다 글이 간결하다. (+ 고양이 마크가 내 취향이다.)

  2. 프레임워크 구조가 엄격하다. NestJS는 기본적으로 DI와 IOC개념을 따르며 이를 모듈이라는 개념으로 구현하는데 이 때 module, controller, resolver, provider, service, subscriber 등의 서로 다른 성격의 파일 이름이 구조화되어있다. 디렉토리 구조도 이에 따라 규격화되어 세상에 다양한 성격의 개발자가 존재하지만 NestJS 앞에서의 프로젝트 구조는 나름(?) 통일화되어있다. (이는 팀원간 협업에도, 신규 팀원의 코드 적응에도 이점이 있다.)

  3. 쉽다. 프레임워크가 그냥 배우기 쉽다. 비하는 아니지만 개인적으로 spring security를 공부할 때 개인적으론 꽤나 어려웠다. 하지만 NestJS의 guard개념은 비교적 매우 쉽게 풀어낸다. (-> 개발생산성이 올라간다.)

  4. 심플하고 다양한 기능이 존재한다. (middleware, interceptor, exception filer, pipe, guard…)

Concept

  • DI

    • Provider는 Controller와 달리 Service, Repository, Factory, Helper 등의 Dependency를 Nest Core가 Register 할 수 있도록 등록되는 것이다. (provider token과 함께 등록된다.)
    • 이런 Dependency들을 등록하기 위해서는 클래스에 @Injectable() 이라는 Decorator로 선언하고 Module에서 등록한다. (Nest IoC Container에 등록)
    • Dependency를 설계할 때에는 객체지향의 SOLID방식을 따르는 것이 좋다.
    • @Injectable()로 선언된 Dependency는 Nest Runtime 시 Singleton 의 객체로 메모리 상에 존재한다.
    • 메모리 상에 객체로 존재하는 이 Provider는 사용되어지는 곳(e.g. Controller) 클래스 생성자를 통해 클래스 멤버 변수에 주입되어 사용된다. (Dependency Injection) → 그 때 그 때 사용하고자하는 Service객체를 생성하여 사용하는 것이 아니라 메모리에 상주하고 있는 객체를 주입만 하는 개념
    @Injectable()
    export class UserService{
      ...
    }
    
    @Controller('user')
    export class UserController {
      // 의존성(Dependency) 주입
      constructor(private readonly userService: UserService) {}
    
      ...
    }
    
    @Module({
        imports: [],
        providers: [UserService],
        controllers: [UserController],
    })
    export class UserModule {}
    
  • Scope
    • Provider의 생명주기는 default - Singleton일 때 애플리케이션의 생명주기와 같다. 앱이 실행되면 객체로 메모리상에 존재했다가 애플리케이션이 shut down되면 메모리에서 해제되는…
    • Scope option으로 이를 제어할 수 있다. (e.g. request-scope…)
  • IoC
    • Dependency (Nest에선 Provider)의 객체화를 개발자가 하는 것이 아니라 IoC Container (Nest에선 NestJS runtime system) 에게 위임한다.
    • 기존엔 객체를 생성하고 사용하는 것이 개발자 주도로 이루어졌다면 IoC방식에선 IoC Container가 미리 객체화시켜놓고 필요에 따라 주입시키므로 이는 객체를 제어하는 것이 역전된 셈이다. → Inversion of Control

CLI

# For using nest cli at first
npm i -g @nestjs/cli

# 새로운 nest 프로젝트를 만들 때
nest new {project-name}

# 새로운 controller를 만들 때 (without .spec.ts file  =>  --no-spec)
nest generate controller {domain-name}
nest g co {domain-name}

# 새로운 service를 만들 때 (without .spec.ts file  =>  --no-spec)
nest generate service {domain-name}
nest g s {domain-name}

# 새로운 module를 만들 때
nest generate module {domain-name}
nest g mo {domain-name}

# 새로운 도메인의 crud로직 만들 때 (dto, entity, controller, service, module)
nest g resource {domain-name} # --no-spec

카테고리:

업데이트:

댓글남기기