ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nest.js 공식문서 읽기] Module
    Server/Nest.js 2023. 1. 27. 14:58

    Module

    module은 만들어진 controller, sevice, repository 등을 하나로 합치는 역할을 한다.

    • 캡슐화
      • nest의 모듈은 기본적으로 provider를 캡슐화한다. 즉, 현재 모듈에서 export된 프로바이더나 주입된 모듈에서 export된 프로바이더가 아니라면 프로바이더를 주입(inject)하는 것은 불가능하다. 만약 하나의 모듈에서 직접 exports를 통해 내보낸 것들이 아니면 외부에서 접근 또는 삽입이 불가능하다.
      • 예를들어 a, b, c 모듈이 있다고 가정하면 a 모듈에서 b 모듈의 프로바이더를 사용하고 싶다면, b 모듈에서 해당 프로바이더를 직접 exports에 등록해주어야 한다.
      • export에 등록하는 방법은 @Module 데코레이터 내부에 등록하면 된다.

    위 예시처럼 컨트롤러가 정의되어 있어도 nest는 boards.controller가 존재하는지 모르고, 이 클래스의 인스턴스를 생성하지 않는다.

    컨트롤러는 항상 모듈에 속해있어야 한다.

    아래처럼 @Module() 데코레이터 내에 controller가 무엇인지 배열에 담아 메타데이터로 전달해줘야만, nest가 controller가 무엇인지 인지할 수 있다.

    // boards.module.ts
    import { Module } from '@nestjs/common';
    import { BoardsController } from './boards.controller';
    import { BoardsService } from './boards.service';
    import { BoardRepository } from './board.repository';
    
    @Module({
      controllers: [BoardsController],
      providers: [BoardsService, BoardRepository],
    })
    export class BoardsModule {}
    
    • @Module() 데코레이터는 모듈을 설명하는 프로퍼티들을 갖는 단일 객체를 가져온다.
      • providers : 프로바이더는 Nest injector에 의해 인스턴스화되고 이 모듈 전체에서 공유된다.
      • controllers: 컨트롤러는 인스턴스화 해야하는 모듈에 정의된 컨트롤러 집합이다.
      • imports : 프로바이더를 export한 모듈 중 이 모듈에 필요한 프로바이더를 가진 모듈을 imports하는 모듈 목록이다.
      • exports : 모듈에서 사용하는 provider를 다른 모듈에서 사용(import)할 수 있도록 등록할 수 있다.

     

    Feature modules

    위의 코드에서 BoardController와 BoardService, BoardRepository는 같은 어플리케이션 도메인에 속해있다. 아주 밀접하게 연관되어있기 때문에 feature module로 이동하는 것이 합리적이다. 피쳐모듈은 단순히 특정 피쳐와 관련된 코드를 구성하고 명확한 경계를 설정한다. 이를 이용해 어플리케이션의 사이즈 또는 팀의 규모가 커짐에 따라 복잡성을 관리하고 SOLID 원칙을 지키며 개발할 수 있게 된다.

    boards모듈을 정의하고 모듈과 관련된 모든 파일들을 boards 디렉토리로 옮겼다면 마지막으로 해야할 것은 이 모듈은 루트 모듈(AppModule, app.module.ts file)로 import해주는 것이다.

    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { BoardsModule } from './boards/boards.module';
    import { typeORMConfig } from './configs/typeorm.config';
    
    @Module({
      imports: [TypeOrmModule.forRoot(typeORMConfig), BoardsModule],
    })
    export class AppModule {}
    

     

    Shared modules

    nest에서 모듈은 기본적으로 싱글톤이므로 여러 모듈간에 provider의 동일한 인스턴스를 쉽게 공유할 수 있다.

    모든 모듈은 자동적으로 shared module이다. 일단 생성되면 어느 모듈에서든지 재사용이 가능하다.

    만약 boardsService의 인스턴스를 다른 모듈에 공유하고 싶다면 boardsmodule에서 exports 등록하면 된다.

    // boards.module.ts
    import { Module } from '@nestjs/common';
    import { BoardsController } from './boards.controller';
    import { BoardsService } from './boards.service';
    import { BoardRepository } from './board.repository';
    
    @Module({
      controllers: [BoardsController],
      providers: [BoardsService, BoardRepository],
    	exports: [BoardsService] // shared module 등록
    })
    export class BoardsModule {}
    

    이제 boardsModule을 가져 오는 모든 모듈은 BoardsService에 액세스할 수 있으며 이를 가져 오는 다른 모든 모듈과 동일한 인스턴스를 공유합니다.

     

    Module re-exporting

    모듈은 내부 프로바이더를 export할 수 있다. 또한 import한 모듈을 re-export하는 것도 가능하다.

    @Module({
      imports: [CommonModule],
      exports: [CommonModule],
    })
    export class CoreModule {}
    

     

    Global module

    모든 곳에서 동일한 모듈을 import 해야 하는 경우 모듈 클래스별로 필요한 모듈을 각각 import 해야하는 번거로움이 있다. 이럴 때 @Global() 데코레이터를 사용하면 개별 모듈 클래스에 import해줄 필요 없이 전역에서 사용 가능한 모듈이 된다. 단, 내보내고자 하는 기능을 다른 모듈에서 사용하게 하려면 exports는 꼭 작성해야한다. 또한 전역 모듈이라도 루트 모듈에는 반드시 import해야한다.

    // boards.module.ts
    import { Module } from '@nestjs/common';
    import { BoardsController } from './boards.controller';
    import { BoardsService } from './boards.service';
    import { BoardRepository } from './board.repository';
    
    @Global()
    @Module({
      controllers: [BoardsController],
      providers: [BoardsService, BoardRepository],
    	exports: [**BoardsService**] // shared module 등록
    })
    export class BoardsModule {}
    
    //app.module.ts
    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { BoardsModule } from './boards/boards.module';
    import { typeORMConfig } from './configs/typeorm.config';
    
    @Module({
      imports: [TypeOrmModule.forRoot(typeORMConfig), **BoardsModule]**,
    })
    export class AppModule {}
    

    댓글