본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Node.js/Nestjs (Nest.js)

Nestjs 프레임워크 서버(컨트롤러와 모듈) -3

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2022. 6. 30.

 

#컨트롤러(Controller)

Nest.js에서 컨트롤러는 사용자의 요청에 대한 행위를 처리하는 기능으로 구성되어 있습니다.

브라우저에서의 요청에 따른 데이터처리, 결과반환 및 정보저장 등 이러한 모든 행위를 담당 합니다.

 

그런데 데이터베이스에 접속하여 무언가 행동을 하는 기능이 필요한다고 가정하여 봅니다.

그러면 컨트롤러가 1개인 경우 직접 추가하면 좋겠지만..

여러개의 컨트롤러에서 이러한 기능을 붙여야 한 다면 코드가 중복되고 집중되지 않는 문제가 발생 합니다.

왼쪽보다 오른쪽이 나아보이지 않나요..?

 

위 사진에서 만약 데이터베이스에 접속하는 기능에서 테이블의 컬럼이 추가되거나, 쿼리가 바뀌거나 또는 접속정보가 바뀐 경우라고 가정 한 다면 왼쪽개발 방식은 파일 4개를 고쳐야 합니다.

그리고 해당 파일에서의 오탈자, 오류 및 버그가 없는지 일일이 확인해야 합니다.

그러나 오른쪽 경우처럼 서로 공통적으로 필요한 기능을 분리한 경우 라면 1개의 파일만 수정 및 디버깅을 하면 됩니다.

 

이처럼 비지니스로직을 분리하는, 공통의 관심을 따로 빼 두어 추상화하는 기능과 역할을 Nest.js에서는 서비스라 부르며 Injectable데코레이터를 통해 만들 수 있습니다.

inject!!

 

이렇게 서비스를 만들게 되면 이제 해당 클래스의 생성 및 소멸은 Nest.js에서 관리를 하게 됩니다.

해당 클래스를 사용하기 위해서 new 연산자를 쓸 필요없이 간단한 설정만을 통해서 싱글톤 형식으로 클래스를 사용 할 수 있습니다!

 

nestjs에서 컨트롤러와 서비스 같은 실제 동작에 필요한 기능들에게 정보를 제공하고, 제어하고 관리하는 곳은 모듈(Module)입니다.

모듈!

 

모듈데코레이터에서 providers 속성은 Injectable 데코레이터가 있는 파일들의 생명을 불어넣고 해당 클래스를 사용하고자 하는 클래스에게 전달 해 주는 역할을 합니다.

간단하게 풀어 쓰면

"서비스를 사용하기 위해서는 Inject 데코레이터를 붙여주고, 모듈에서 providers에 넣어주면 된다" 라고 말 할수 있습니다.

* 추가로, 다른모듈을 사용하기 위해서는 imports 부분에 원하는 모듈을 추가 해 주면 됩니다.

 

이렇게 providers로부터 제공되는 클래스는 사용하고자 하는 클래스에서 생성자를 통해 받을 수 있습니다.

* 대상 : app.controller.ts

import { Controller } from '@nestjs/common';
import { AppService } from './app.service';


@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {  //<-- 요렇게 사용 합니다.
  
  }
}

 

위 코드처럼 생성자에 사용하고자 하는 클래스를 입력하면 됩니다.

생성자 내부에서 간단하게 받는 모습만 구현 하더라도 클래스 내부의 전역변수처럼 쓸 수 있습니다.

위 코드는 아래처럼 표기할 수도 있습니다.

* 대상 : app.controller.ts

import { Controller } from '@nestjs/common';
import { AppService } from './app.service';


@Controller()
export class AppController {
  private readonly appService;
  //constructor(private readonly appService: AppService) { 
  constructor(service: AppService) {  
    this.appService = service;
  }
}

 

이러한 서비스는 A라는 클래스에서 사용할때의 데이터와 B라는 클래스에서 사용할 때의 데이터가 서로 일치하기 때문에 특정 변수를 사용하여 작업을 하게 되는경우 데이터에 대한 무결성을 항상 고려해야 합니다.

테스트를 위해 새로운 컨트롤러를 만들어 줍니다.  * 파일을 새로 만들어주세요!

* 대상 : app.다른컨트롤러.ts

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class 다른컨트롤러 {
  constructor(private readonly appService: AppService) {}

  @Get('other') //myData가 변하는지 확인하는 주소 입니다.
  getHello(): string {
    return this.appService.myData;
  }
}

 

이렇게 만들어진 컨트롤러를 모듈에 추가합니다.

모듈에 추가하지 않으면 해당 컨트롤러는 아무행동도 하지 않습니다!

* 대상 : app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { 다른컨트롤러 } from './app.다른컨트롤러';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController, 다른컨트롤러],
  providers: [AppService],
})
export class AppModule {}

 

이제 서비스를 손볼 차레 입니다.

기존 서비스에 간단한 set get 메서드를 추가하여 줍니다.

* 대상 : app.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  private data: any;

  getHello(): string {
    return 'Hello World!';
  }

  set myData(arg) {
    this.data = arg;
  }

  get myData() {
    return this.data;
  }
  
}

 

기존 컨트롤러에서는 간단하게 해당 데이터를 수정하는 메서드를 추가합니다.

* 대상 : app.controller.ts

@Controller()
export class AppController {

  //생략....

  @All('changeData') //서비스의 데이터 바꿔보기
  서비스Data바꿔보기(): any {
    this.appService.myData = '컨트롤러에서바꾼데이터';
    return { result: true };
  }


}

 

테스트는 아래처럼 진행 합니다.

1. 서비스의 데이터를 변하게 하려는 컨트롤러에 먼저 접속 합니다 : http:x.x.x.x:3000/changeData

2. result 값을 확인 하였 다면 "다른컨트롤러"에서 제공하는 주소로 접속 합니다 : http:x.x.x.x:3000/other

3. 결과를 확인 합니다.

서비스의 데이터가 바뀝니다.

 

당연한 결과이지만 이러한 부분에 익숙하지 않는 경우 발생할 수 있는 실수 입니다.

이러한 방법을 활용 하여 컨트롤러끼리 서로의 필요한 자원을 공유할 수 있습니다.

아니면 nestjs에서 제공하는 rxjs 프레임워크를 활용하여 구독 / 발행 개념으로도 활용 가능 합니다.

기존 "AppController"에서 데이터를 발행하면, 새로 만든 "다른컨트롤러" 에서 구독하여 콜백으로 정의한 행위를 할 수 있습니다!

 

위 내용처럼 하면 기존 컨트롤러인 AppController에서의 addItem 주소로 요청이 들어오게 되면 서비스에 등록한 BehaviorSubject객체에서 발행(publish)됨에 따라서 , 새로 만들어 준 "다른컨트롤러"의 생성자에 정의한 구독(subscribe) 행위가 동작하게 됩니다.

* rxjs와 관련된 내용은 조금 복잡하므로 제 깃허브 저장소에 올린 샘플코드를 실행하면 확인 할 수 있습니다.

 

https://github.com/TaeSeungRyu/NestProject/tree/main/step2

 

GitHub - TaeSeungRyu/NestProject: Nestjs 프로젝트

Nestjs 프로젝트. Contribute to TaeSeungRyu/NestProject development by creating an account on GitHub.

github.com

 

공부하면 할 수록 재미있고 즐거운 nestjs!!!

다음 포스팅에서는 컨트롤러와 모듈, 모듈의 간단한 역할에 대해서 살펴보겠습니다!

궁금한점 또는 틀린부분은 언제든 연락 주세요!

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글