NestJS에서의 DI (Dependency Injection)는 애플리케이션 개발에서 중요한 개념이며, 코드의 재사용성, 테스트 용이성, 모듈화 등을 촉진하는 핵심적인 매커니즘이다.
NestJS는 @Injectable()
로 주석이 달린 클래스를 의존성 주입 컨테이너에 등록한다.
이 클래스의 인스턴스는 필요한 곳에서 DI를 통해 주입될 수 있다.
@Injectable()
을 사용하여 클래스를 정의하면 해당 클래스는 NestJS 모듈의 범위 내에서 재사용 할수 있다.
다른 모듈에서 같은 서비스를 다시 정의하지 않고도 주입할 수 있다.
@Injectable()
은 이 아키텍처의 핵심 원칙 중 하나인 서비스 분리를 가능하게 한다.@Injectable()
을 사용하면 코드가 의존성 주입 메커니즘을 명확히 보여주므로 코드의 의도를 이해하기 쉽다.import { Injectable } from '@nestjs/common';
@Injectable()
export class MyService {
// 서비스 로직 구현
}
위의 예시에서 MyService 클래스는 @Injectable() 데코레이터로 주석이 달려있다. 이는 NestJS에게 이 클래스가 서비스로 사용될 수 있음을 알리는 것이다.
@Injectable()
을 사용하는 클래스는 NestJS에서 관리되어야 하며, 그 외의 클래스에서는 일반 클래스로 간주된다.
NestJS 모듈의 providers 배열이나 imports 배열 내에서 @Injectable()
클래스를 등록해야 DI가 올바르게 작동한다.
// user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
private users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
];
findAll(): any[] {
return this.users;
}
findById(id: number): any {
return this.users.find(user => user.id === id);
}
createUser(name: string): void {
const newUser = { id: this.users.length + 1, name };
this.users.push(newUser);
}
}
위의 코드에서 UserService는 @Injectable() 데코레이터로 주석이 달린 서비스 클래스로 이 클래스는 사용자 데이터를 관리하는 간단한 메서드들을 포함하고 있다. (findAll, findById, createUser).
// user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
@Module({
providers: [UserService], // UserService를 providers 배열에 등록
exports: [UserService], // UserService를 다른 모듈에서 사용할 수 있도록 export
})
export class UserModule {}
위의 코드는 UserModule에서 UserService를 NestJS 모듈의 providers 배열에 등록하고, 다른 모듈에서도 이 서비스를 사용할 수 있도록 exports 배열에 추가한다.
// user.controller.ts
import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
findAll() {
return this.userService.findAll();
}
@Get(':id')
findById(@Param('id') id: string) {
return this.userService.findById(parseInt(id, 10));
}
@Post()
createUser(@Body('name') name: string) {
this.userService.createUser(name);
return 'User created successfully';
}
}
위의 코드에서 UserController는 UserService를 생성자 주입을 통해 사용한다. 각각의 메서드는 HTTP 요청에 따라 UserService의 메서드를 호출하여 작업을 수행한다.
모듈화와 재사용성
: 서비스 클래스를 별도로 관리하고 재사용할 수 있다.
테스트 용이성
: 의존성을 주입하여 모의 객체(mock)를 사용하여 테스트하기 쉽다.
의존성 분리
: 클래스 간의 결합도를 낮추어 유연성을 높이고 유지보수를 쉽게 한다.