백엔드/nest.js

[nest.js] 계층 구조 / DI / Provider

개발자딥게 2022. 11. 25. 00:53
반응형

 


계층 구조

 

3계층 구조(3-tier Architecture)

  • Presentation Tier: 사용자 인터페이스 혹은 외부와의 통신을 담당 (nest에선 Controller)
  • Application Tier: Logic Tier라고 하기도 하고 Middle Tier라고 하기도 함. 주로 비즈니스 로직을 여기서 구현을 하며, Presentation Tier와 Data Tier사이를 연결 (nest에선 Service)
  • Data Tier: 데이터베이스에 데이터를 읽고 쓰는 역할을 담당

 

 

계층형 구조(Layered Architecture)

3계층 구조처럼 계층형 구조를 사용하는 이유는 무엇일까.

소프트웨어 개발시, 각 계층은 응집도가 높으면서다른 계층과는 낮은 결합도를 가져야 한다는 설계법칙이 있다.

복잡해 보이는 작업도 그 작업을 분리하고 작은 단위로 쪼개면 간단하게 해결할 수 있다. 계층화의 핵심은 이것이다.

단, 상위 계층은 하위 계층을 사용할 수 있지만 하위 계층은 본인의 상위 계층으로 누가 있는지 인식 못하도록 해야한다.

(Presentation 계층은 Application  계층을 알 수 있지만, Application 계층은 Presentation 계층을 인식하지 못해야만 한다)

 

 

 


의존성 주입 (DI)

 

추상화

추상화는 곧 인터페이스를 의미한다.

인터페이스를 이용하면 프로그래머는 호출하는 클래스가 무엇인지 알 필요없이,

특정 기능에만 초점을 맞춰 구현하면 된다. 따라서 클래스가 변경되거나 확장되더라도 문제가 발생하지 않게 된다.

구체적인 특정 객체에 의존하지 말고 인터페이스(추상화)에 의존하라는 것이다.

 

인터페이스 예시

export interface Cat {
  name: string;
  age: number;
  breed: string;
}

 

제어 역전(IoC, Inversion of Control)

일반적으로 객체의 생명주기(생성, 호출, 소멸,, 등)를 제어하는 권한을 프로그래머가 갖는다.

하지만 이를 프로그래머가 직접 관리하지 않고 외부(프레임워크)에 위임하는 설계 원칙을 제어의 역전이라고 한다.

객체는 스스로가 사용할 객체를 선택할 수 없고, 외부로부터 결정된다. 따라서 코드 내에 new를 이용한 객체 생성이 없다.

 

 

의존성 Dependency

의존성이 높은 코드는 new를 통해 객체를 만드는 로직을 말한다. 

의존성을 낮추기 위해서는 외부로부터 객체를 받아 사용하도록 해야한다. (의존성 주입)

즉 객체를 직접 생성하지 않고 객체를 전달받는 형태로 구성이 되면 의존성이 낮아졌다고 한다.

 

 

의존성 주입 (DI, Dependency Injection)

객체간의 결합을 느슨하게 만들어 의존성을 낮추고, 유연하고 확장성 있는 코드를 작성하기 위한 패턴이다.

외부(프레임워크)에서 객체의 생명주기를 관리하는 개념이라고 보면 된다.

nestJS는 DI를 통해 IoC를 구현한 프레임워크이다.

 

 

 


Provider

Provider

Nest 클래스(서비스, 리포지토리, 팩토리, 헬퍼 등)는 Provider로 취급되어 다른 컨트롤러(소비자)에 종속적으로 주입되어 컨트롤러(소비자)에게 제공될 서비스이다. 즉, 개체는 서로 다양한 관계를 만들 수 있으며 개체 인스턴스를 "연결"하는 기능은 대부분 Nest 런타임 시스템에 위임한다. 

 

 

코드로 확인하기

 

1. Service 정의하기

아래 CatsService는 데이터 저장 및 검색을 담당하도록 설계되었다.

CatsService는 CatsController의 Provider로 정의하기에 좋다.

//	src/app.service.ts

import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()		// 해당 어노테이션이 붙은 것만 provider로 쓰여질 수 있음
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}

 

2. Provider 등록하기

위에서 만든 서비스를 공급자로 등록하면, 컨트롤러에서 의존성 주입으로 서비스를 전달해줄 수 있다.

//	src/app.module.ts 

import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],			// 여기에 Provider를 정의해야 한다.
})
export class AppModule {}

 

3. Controller에서 사용하기

app.module에서 provider로 정의된 서비스는 컨트롤러에 주입되어 사용가능해진다.

주로 생성자에서 주입되며 선언을 따로 하지 않고 곧바로 사용이 가능하다.

//	src/app.controller.ts 

import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
  constructor(private catsService: CatsService) {}	// 생성자에서 주입된 CatsService instance

  @Post()
  async create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);		// 공급받은 CatsService instance를 사용할 수 있음
  }

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();			// 공급받은 CatsService instance를 사용할 수 있음
  }
}

 

 

 

 

 

 

 

 

 

 

 

참고 링크

https://docs.nestjs.com/providers

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

https://www.wisewiredbooks.com/nestjs/overview/04-provider.html

 

프로바이더 - 쉽게 풀어 쓴 Nest.js

프로바이더는 Nest의 기본 개념입니다. 많은 기본 Nest 클래스는 서비스(Service), 레파지토리, 팩토리, 헬퍼 등등의 프로바이더로 취급될 수 있습니다. 프로바이더의 주요 아이디어는 의존성을 주입

www.wisewiredbooks.com

 

 

반응형