@Injectable() 데코레이터
NestJS에서 제공하는 데코레이터로, 클래스가 의존성 주입(DI, Dependency Injection) 컨테이너에 의해 관리되는 '프로바이더(Provider)'임을 명시한다. 이 데코레이터를 사용하면 해당 클래스의 인스턴스를 다른 클래스에서 주입받아 사용할 수 있다.
주요 역할
1. 의존성 주입 컨테이너에 등록
@Injectable()이 붙은 클래스는 NestJS의 IoC 컨테이너(의존성 주입 컨테이너)에 등록된다. IoC 컨테이너는 이 클래스의 인스턴스를 생성하고, 필요할 때 다른 클래스에 주입한다.
2. 다른 클래스에서 사용 가능
@Injectable()이 적용된 클래스는 다른 클래스(예: 컨트롤러, 서비스)에서 의존성으로 주입(constructor)될 수 있다.
3. 싱글톤 관리
기본적으로 NestJS는 @Injectable() 클래스를 싱글톤으로 관리한다. 즉, 애플리케이션 전체에서 동일한 인스턴스를 공유한다.
코드 예시
@Injectable() 클래스 정의
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
이 코드는 AppService 클래스를 NestJS의 IoC 컨테이너에 등록한다.
서비스 클래스 주입
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {} // AppService 주입
@Get()
getHello(): string {
return this.appService.getHello(); // AppService의 메서드 호출
}
}
AppController의 생성자에서 AppService를 주입받는다. AppService는 @Injectable()로 등록되어 있으므로 컨테이너가 자동으로 생성하고 주입한다.
주요 동작 흐름
1. 클래스 등록
@Injectable()을 통해 AppService가 IoC 컨테이너에 등록된다.
2. 자동 주입
AppController에서 AppService를 생성자에 선언하면 NestJS 컨테이너가 자동으로 AppService 인스턴스를 생성하여 주입한다.
3. 싱글톤 관리
NestJS는 기본적으로 AppService의 하나의 인스턴스를 공유하여 애플리케이션 전반에서 사용할 수 있게 한다.
왜 사용하는가?
1. 의존성 분리
@Injectable()을 사용하면 클래스 간의 의존성을 쉽게 관리할 수 있다.
2. IoC(제어의 역전)
객체 생성과 라이프사이클 관리를 IoC 컨테이너에 위임하여 코드의 유지보수성을 높인다.
3. 재사용성
한 번 정의된 프로바이더를 여러 클래스에서 재사용할 수 있다.
요약
@Injectable()은 NestJS에서 클래스를 프로바이더로 등록하기 위한 데코레이터이다.
프로바이더는 IoC 컨테이너에서 관리되며, 다른 클래스에 의존성 주입을 통해 전달된다.
주로 서비스 클래스를 정의할 때 사용한다.
※ '주입'이란?
필요한 객체를 다른 객체에 전달해주는 과정을 말한다.
예시 - 직접 객체를 만드는 경우 (주입X)
일반적으로 필요한 객체를 직접 만들어야 한다.
class Engine {
start() {
console.log('Engine started');
}
}
class Car {
private engine: Engine;
constructor() {
this.engine = new Engine(); // 직접 객체 생성
}
startCar() {
this.engine.start();
}
}
const car = new Car();
car.startCar(); // Engine started
여기서 Car 클래스가 Engine을 직접 생성해야 한다.
만약, Engine의 구현이 바뀌면 Car도 수정해야한다.
이는 코드가 유연하지 않게 된다.
예시 - NestJS의 의존성 주입을 사용하는 경우
NestJS가 대신 객체를 만들어 자동으로 주입해 준다.
import { Injectable } from '@nestjs/common';
@Injectable()
class Engine {
start() {
console.log('Engine started');
}
}
@Injectable()
class Car {
constructor(private engine: Engine) {} // 엔진을 주입받음
startCar() {
this.engine.start();
}
}
// NestJS가 Engine과 Car를 생성하고 연결(주입)해줌
const car = new Car(new Engine());
car.startCar(); // Engine started
여기서 Car는 Engine을 주입받는다.
Car는 엔진을 '어떻게 만드는지'를 신경 쓰지 않고 그냥 받기만 하면 된다.
NestJS에서의 실제 예제
import { Injectable } from '@nestjs/common';
@Injectable()
class AppService {
getHello(): string {
return 'Hello World!';
}
}
import { Controller, Get } from '@nestjs/common';
@Controller()
class AppController {
constructor(private readonly appService: AppService) {} // AppService를 주입받음
@Get()
getHello(): string {
return this.appService.getHello();
}
}
1. AppService 클래스
getHello라는 메서드를 제공한다.
2. AppController 클래스
생성자에서 AppService를 주입받아 사용한다.
3. NestJS의 역할
AppService를 생성하고, 자동으로 AppController에 전달(주입)한다.
요약
'주입'은 필요한 객체를 대신 만들어서 전달해주는 것이라고 생각하면 된다. NestJS가 이 과정을 자동으로 처리해주므로, 개발자는 필요한 것을 선언만 하면 된다.
constructor(private readonly service: ServiceClass) {}
위 코드에서 service는 NestJS가 알아서 생성하고 전달해주는 '도구'이다. Car가 Engine을 필요로 하듯, 클래스는 필요한 '부품'을 받는다고 생각하면 된다.
'Nest.js' 카테고리의 다른 글
[NestJS] readonly란? | const와 비교, C++ 관점에서 비교 (0) | 2025.01.20 |
---|---|
[NestJS] export 키워드에 대해서 (1) | 2025.01.20 |
[NestJS] 데코레이터에 대해서 (2) | 2025.01.20 |
[NestJS] 파일 끝의 export {};의 의미 | Top-Level await (0) | 2025.01.14 |