1 분 소요

지난 시간에는 Nest의 로직 중 controller를 보았다. 이번에는 Provider에 대해 알아보겠다.

Provider

컨트롤러에서는 클라이언트의 요청을 받아 응답을 해주는 역할을 하고, 라우팅을 해주는 역할을 담당을 했다. 프로바이더는 비즈니스 로직을 수행하는 역할을 한다.

Nest에서 제공하는 프로바이더의 핵심은 의존성을 주입할 수 있다는 점이라고 한다.

의존성 주입(Dependency Injection, DI)은 OOP에서 많이 활용되고 있는 기법이다. 의존성 주입을 이용하면 객체를 생성하고 사용할 때 관심사를 분리할 수 있다. 이는 코드 가독성과 재사용성이 높은 SW를 만들게 도와준다.

UserController 코드를 살펴보자.

@Controller("users")
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(":id")
  findOne(@Param("id") id: string) {
    return this.usersService.findOne(+id);
  }

  @Patch(":id")
  update(@Param("id") id: string, @Body() updateUserDto: UpdateUserDto) {
    return this.usersService.update(+id, updateUserDto);
  }

  @Delete(":id")
  remove(@Param("id") id: string) {
    return this.usersService.remove(+id);
  }
}

컨트롤러는 직접 비즈니스 로직을 수행하지 않는다. 컨트롤러와 연결된 UserService에서 수행한다. UserService는 UserController에서 생성자를 주입받아, userService라는 객체 멤버 변수에 할당되어 사용되고 있다.

UserService를 살펴 보면 이렇게 되어 있다.

@Injectable()
export class UsersService {
  create(createUserDto: CreateUserDto) {
    return "This action adds a new user";
  }

  findAll() {
    return `This action returns all users`;
  }

  findOne(id: number) {
    return `This action returns a #${id} user`;
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    return `This action updates a #${id} user`;
  }

  remove(id: number) {
    return `This action removes a #${id} user`;
  }
}

@Injectable 데코레이터가 선언되어 있는 것을 볼 수 있다. 이를 통해 다른 어떤 Nest 컴포넌트에서도 주입할 수 있는 프로바이더가 된다. 별도의 스코프를 지정해주지 않으면 일반적으로 싱글톤 인스턴스가 생성된다.

프로바이더 등록과 사용

프로바이더 인스턴스 역시 모듈에서 사용할 수 있도록 등록을 해주어야 한다.

속성 기반 주입

지금까지 컨트롤러에서 생성자를 통해 프로바이더를 주입 받았다. 하지만 프로바이더를 직접 주입받아 사용하지 않고 상속관계에 있는 자식 클래스를 주입받아 사용하고 싶은 경우가 있다.

레거시 클래스를 확장한 새로운 클래스를 만드는 경우 새로 만든 클래스를 프로바이더로 제공하고 싶은 경우이다. 이럴 때, 자식 클래스에서 부모 클래스가 제공하는 함수를 호출하기 위해서는 부모 클래스에서 필요한 프로바이더를 super()를 통해 전달 해주어야 한다.

레거시 클래스 : 테스트가 불가능 하거나 어려운 클래스를 뜻한다.

댓글남기기