ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2023 - 08 - 06 Nest.js 프로젝트 @module, 데코레이터, 루트모듈, imports, controllers, providers, exports, 의존성 주입 DI, IoC, DI, 제어 역전, 의존성(DI)
    Today I Learned/TIL 08 2023. 8. 6. 01:11

    https://github.com/sangwoorhie/Nest.js.git

     

    GitHub - sangwoorhie/Nest.js

    Contribute to sangwoorhie/Nest.js development by creating an account on GitHub.

    github.com

     

    Nest.js 설치 명령어

    npm i -g @nestjs/cli

    Nest.js 실행 명령어 (메뉴얼을 제공함)

    nest

     

    Nest.js 프로젝트 생성 명령어

    $ nest new sparta-nest

    npm 선택

    ? Which package manager would you ❤️  to use? (Use arrow keys)
    ❯ npm
      yarn
      pnpm

     

    Nest.js 프로젝트에서 만약 실패했다면, 아래 명령어 순서대로 입력하기.

    git clone https://github.com/nestjs/typescript-starter.git sparta-nest
    cd sparta-nest
    npm i

    main.ts

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule); =>  AppModule이라는 모듈을 루트 모듈로 사용하는
      await app.listen(3000);                              Nest.js 어플리케이션 인스턴스를 생성함
    }
    bootstrap();

    NewsFactory 클래스의 create라는 정적 함수를 통해 Nest.js 어플리케이션 인스턴스를 새롭게 생성한다.

     


    app.module.ts  → 위에서 루트모듈로 지정이 된 AppModule

    (Nest.js에서 모듈은 레이어드 아키텍쳐 패턴을 구성하는 컴포넌트들을 매니징한다.

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    
    @Module({      => 이렇게 골뱅이(@)가 붙는 키워들을 데코레이터라고 한다.
      imports: [],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}

    @Module 에서 이렇게 골뱅이(@)가 붙는 키워드를 데코레이터라고 한다.

    데코레이터란 해당 클래스나 함수가 어떤 역할을 수행하는지에 대해 Nest.js에 알려주는 역할을 한다.

    즉 AppModule이라는 클래스는 Nest.js 웹 어플리케이션에서 모듈이라는 역할을 한다.

     

    @Module의 속성

    imports : 해당 모듈에서 필요한 모듈의 집합을 정의, 여기 들어가는 모듈은 서비스를 노출하는 모듈
    		  가장 흔하게 임포트를 하는 모듈 중 하나는 HttpModule(API 호출 모듈)이 있다.
              
    controllers : 해당 모듈에서 사용하는 컨트롤러를 정의함
    
    providers : 해당 모듈에서 사용하는 서비스를 정의함
    
    exports : 해당 모듈에서 노출시킬 서비스를 정의함

    app.controller.ts

    import { Controller, Get } from '@nestjs/common';
    import { AppService } from './app.service';
    
    @Controller()
    export class AppController {
      constructor(private readonly appService: AppService) {}
    
      @Get()
      getHello(): string {
        return this.appService.getHello();
      }
    }

    @Controller 데코레이터로 AppController클래스가 컨트롤러 역할을 하고 있음을 알 수 있다.

     

    위에 constructor 생성자의 인자로 AppService 객체를 넘기면 this.appService라는 멤버 변수에 Appservice 객체가 주입된다. 이를 DI (의존성 주입) 이라고 하며 이렇게 생성자를 통한 DI를 Nest.js에서 자체 지원한다.

     

    이 이유는, 컨트롤러는 서비스를 반드시 의존해야 하며 이는 생성자를 통한 DI로 해결해야 하기 때문이다.

     

    @Get 데코레이터는 @Post, @Put, @Delete 등 여러가지가 있다.


    app.service.ts

     

    import { Injectable } from '@nestjs/common';
    
    @Injectable()
    export class AppService {
      getHello(): string {
        return 'Hello World!';
      }
    }

     

    @Injectable 데코레이터 : AppService같은 서비스 객체는 실제로 레포지토리를 의존하며 비즈니스 로직 실행을 담당한다.

    AppService와 같은 서비스 객체는 실제로 리포지토리를 의존하며 비즈니스 로직 실행을 담당한다.


    app.controller.spec.ts

     

    import { Test, TestingModule } from '@nestjs/testing';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    
    describe('AppController', () => {
      let app: TestingModule;
    
      beforeAll(async () => {
        app = await Test.createTestingModule({
          controllers: [AppController],
          providers: [AppService],
        }).compile();
      });
    
      describe('getHello', () => {
        it('should return "Hello World!"', () => {
          const appController = app.get(AppController);
          expect(appController.getHello()).toBe('Hello World!');
        });
      });
    });

    해당 코드는 AppController를 Jest라는 테스트 프레임워크를 통해서 테스트하는 코드.

    이 컨트롤러 및 서비스들은 유닛테스트 및 E2E 테스트를 통과해야 한다.


    IoC : 제어 역전 (Inversion of Control)

    기존에는, 어떤 서비스를 이용하고 싶으면 아래와 같이 코드를 작성해야 했다.

    import { Controller, Get } from '@nestjs/common';
    import { AppService } from './app.service';
    
    @Controller()
    export class AppController {
      // 1. 사용하고 싶은 서비스 타입 객체를 미리 선언합니다.
      private appService: AppService
      
      constructor() {
        // 2. 생성자에서 실제로 사용할 서비스 객체를 직접 생성합니다.
        this.appService = new AppService();
      }
      ...
    }

    개발자가 사용하고 싶은 객체가 있다면 , 그 객체를 생성부터 소멸까지 개발자가 직접 관리해야 했다. 하지만, IoC는 개발자가 사용하고 싶은 객체를 직접 생성하는 것이 아니라 객체의 생명주기 관리 자체를 외부(Nest.js IoC 컨테이너)에 위임을 해야 한다.

    즉, 객체의 관리를 컨테이너에 맡겨서 제어권이 넘어갔기 때문에 IoC(제어역전)이라고 하는 것.

     

    IoC는 모듈 간 결합도를 낮추기 때문에 하나의 모듈이 변경되어도 다른 모듈들에는 영향을 최소화되어 웹 어플리케이션을 지속 가능하고 확장성 있게 해준다.

     

    DI 는 이런 IoC를 수행하는 방법의 하나이며, Nest.js에서는 생성자를 통한 DI를 가장 기본적인 IoC 테크닉으로 생각하고 있다.

     

    constructor(private readonly appService: AppService) {}

     

    댓글

Designed by Tistory.