의존성 주입(Dependency Injection, DI)란?

TaeWoo·2025년 2월 13일

기술면접

목록 보기
1/3
post-thumbnail

의존성 주입(DI)은 객체 간의 의존성을 외부에서 주입해주는 디자인 패턴이다.
이를 통해 객체 간 결합도를 낮추고 유연성을 높일 수 있다. DI는 주로 제어의 역전 개념과 함께 사용되며, 객체의 생성 및 관리를 담당한다.

  1. 의존성 주입의 개념

DI는 객체가 직접 의존성을 생성하지 않고, 외부에서 주입받도록 설계하는 방식이다.
즉, 클래스 내부에서 다른 객체를 직접 생성하지 않고, 외부에서 필요한 객체를 제공해준다.

예제: 직접 의존성 생성(DI 미사용)

class Engine {
    start() {
      console.log('Engine started');
    }
  }
  
  class Car {
    private engine: Engine;
  
    constructor() {
      this.engine = new Engine(); // 직접 객체 생성
    }
  
    drive() {
      this.engine.start();
      console.log('Car is moving');
    }
  }

위 코드에서는 Car 가 Engine 을 직접 생성하고 있기 때문에 두 객체는 강하게 결합되어있다.
이 경우 Engine을 다른 엔진으로 교체하려면 Car의 코드도 수정해야 하므로 확장성이 떨어진다.

  1. 의존성 주입을 활용한 개선 방법

DI를 적용하면 Car 클래스가 Engine을 직접 생성하는 것이 아니라, 외부에서 주입받도록 변경할 수 있다.

예제: 생성자를 통한 의존성 주입

class Engine{
    start(){
        console.log('Engine started');
    }
}

class Car{
    private engine: Engine;

    constructor(engine: Engine){
        this.engine = engine; //외부에서 주입
    }

    drive(){
        this.engine.start();
        console.log('Car is moving');
    }
}


const engine = new Engine();
const car = new Car(engine);
car.drive();

Engine 을 다른 종류의 엔진으로 쉽게 교체 가능하다.

  1. Nestjs의 의존성 주입

Nestjs는 DI 컨테이너를 통해 의존성을 자동으로 관리한다.
Nestjs에서는 클래스 기반의 프로바이더를 사용하여 DI를 구현한다.

Nestjs에서 DI 사용 예제

1) Service 클래스 생성

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

@Injectable()
export class EngineService{
    start(){
        console.log('Engine started');
    }
}

@Injectable() 데코레이터를 사용하여 이 클래스가 의존성 주입 가능한 프로바이더 임을 선언한다.

2) Service를 주입받는 클래스

import {Injectable} from '@nestjs/common';
import {EngineService} from './engine.service';

@Injectable()
export class CarService{
    constructor(private readonly engineService: EngineService){}

    drive(){
        this.engineService.start();
        console.log('Car is moving');
    }
}

CarService는 EngineService에 의존하고 있으며, 생성자를 통해 주입받는다.

3) Module에서 등록

import {Module} from '@nestjs/common';
import {EngineService} from './engine.service';
import {CarService} from './car.service';

@Module({
    providers: [EngineService, CarService],
    export:[CarService],
})

export class CarModule{}

Nestjs에서는 @Module을 사용하여 서비스들을 등록하고, 이를 자동으로 주입해준다.

4) 사용 예시

import {Injectable} from '@nestjs/common';
import {CarService} from './car.service';

@Injectable()
export class AppService{
    constructor(private readonly carService:CarService){}

    run(){
        this.carService.drive();
    }
}

Nestjs가 CarService와 EngineService를 자동으로 주입하여 사용할 수 있도록 해준다.

  1. DI의 장점과 활용

✅ 장점
객체 간 결합도 감소 -> 유지보수 용이
코드의 재사용성 증가 -> 동일한 의존성을 여러 곳에서 사용 가능
테스트 용이 -> Mock을 활용한 유닛 테스트 가능
확장성과 유연성 증가 -> 새로운 기능 추가가 쉬움

✅ 활용 예시
REST API 서비스 간의 분리
데이터베이스 연결을 관리하는 Repository 패턴
메시지 브로커(MQTT, Kafka)와의 인터페이스 모듈
OAuth 또는 JWT 기반 인증 모듈

profile
코드와 아이디어의 소통, 기록하는 개발자. 🚀✨

0개의 댓글