Dependency 실전 가이드

Dependency의 핵심 개념과 실무 활용

TypeScript중급
6시간
3개 항목
학습 진행률0 / 3 (0%)

학습 항목

1. TypeScript
고급
Dependency|Injection|기초부터|심화까지
퀴즈튜토리얼
2. TypeScript
고급
Dependency|Injection|베스트|프랙티스
퀴즈튜토리얼
3. TypeScript
초급
Dependency|Injection|핵심|개념|완벽|정리
퀴즈튜토리얼
1 / 3

이미지 로딩 중...

Dependency Injection 기초부터 심화까지 - 슬라이드 1/13

Dependency Injection 기초부터 심화까지

의존성 주입(DI)의 핵심 개념부터 고급 패턴까지 실전 예제로 학습합니다. 생성자 주입, 인터페이스 분리, IoC 컨테이너 활용법을 다룹니다.


카테고리:TypeScript
언어:TypeScript
난이도:advanced
메인 태그:#TypeScript
서브 태그:
#DependencyInjection#DesignPatterns#SOLID#IoC

들어가며

이 글에서는 Dependency Injection 기초부터 심화까지에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. 기본_의존성_주입_개념
  2. 인터페이스_기반_주입
  3. 싱글톤_패턴과_DI
  4. 팩토리_패턴_DI
  5. 프로퍼티_주입_패턴
  6. DI_컨테이너_기본
  7. 자동_의존성_해결
  8. 스코프_관리_패턴
  9. 생성자_주입_vs_메서드_주입
  10. 순환_의존성_해결
  11. 모듈_기반_DI_시스템
  12. 고급_인터셉터_패턴

1. 기본_의존성_주입_개념

개요

클래스가 필요한 의존성을 외부에서 주입받는 기본 패턴입니다. 결합도를 낮추고 테스트를 용이하게 만듭니다.

코드 예제

class Logger {
  log(message: string) { console.log(message); }
}

class UserService {
  constructor(private logger: Logger) {}

  createUser(name: string) {
    this.logger.log(`User ${name} created`);
  }
}

const service = new UserService(new Logger());

설명

UserService가 Logger를 생성자를 통해 주입받아 사용합니다. 의존성이 외부에서 관리되어 코드 재사용성이 높아집니다.


2. 인터페이스_기반_주입

개요

인터페이스를 통해 구체적인 구현체를 추상화하여 더 유연한 설계를 만듭니다.

코드 예제

interface ILogger {
  log(message: string): void;
}

class ConsoleLogger implements ILogger {
  log(msg: string) { console.log(msg); }
}

class FileLogger implements ILogger {
  log(msg: string) { /* 파일에 저장 */ }
}

class UserService {
  constructor(private logger: ILogger) {}
}

설명

ILogger 인터페이스를 사용해 ConsoleLogger나 FileLogger를 자유롭게 교체할 수 있습니다. 개방-폐쇄 원칙을 준수합니다.


3. 싱글톤_패턴과_DI

개요

싱글톤 인스턴스를 의존성으로 주입하여 전역 상태를 안전하게 관리합니다.

코드 예제

class Database {
  private static instance: Database;

  private constructor() {}

  static getInstance(): Database {
    if (!this.instance) {
      this.instance = new Database();
    }
    return this.instance;
  }
}

const db = Database.getInstance();

설명

Database 클래스는 단 하나의 인스턴스만 생성되며, getInstance()를 통해 동일한 인스턴스를 공유합니다.


4. 팩토리_패턴_DI

개요

팩토리 함수를 주입하여 객체 생성 로직을 캡슐화하고 런타임에 다양한 타입을 생성합니다.

코드 예제

interface INotification { send(msg: string): void; }

type NotificationFactory = (type: string) => INotification;

class NotificationService {
  constructor(private factory: NotificationFactory) {}

  notify(type: string, msg: string) {
    const notification = this.factory(type);
    notification.send(msg);
  }
}

설명

팩토리 함수를 주입받아 필요한 타입의 알림 객체를 동적으로 생성합니다. 객체 생성 로직이 분리됩니다.


5. 프로퍼티_주입_패턴

개요

생성자가 아닌 프로퍼티를 통해 의존성을 주입하는 방식입니다. 선택적 의존성에 유용합니다.

코드 예제

class UserService {
  logger?: ILogger;

  setLogger(logger: ILogger) {
    this.logger = logger;
  }

  createUser(name: string) {
    this.logger?.log(`Creating ${name}`);
  }
}

const service = new UserService();
service.setLogger(new ConsoleLogger());

설명

setLogger()를 통해 나중에 의존성을 주입할 수 있습니다. 순환 참조 문제를 해결할 때도 활용됩니다.


6. DI_컨테이너_기본

개요

DI 컨테이너는 의존성 등록과 해결을 자동화하는 핵심 도구입니다.

코드 예제

class DIContainer {
  private services = new Map<string, any>();

  register(name: string, instance: any) {
    this.services.set(name, instance);
  }

  resolve<T>(name: string): T {
    return this.services.get(name);
  }
}

const container = new DIContainer();
container.register('logger', new ConsoleLogger());

설명

컨테이너에 서비스를 등록하고 필요할 때 resolve()로 가져옵니다. 의존성 관리가 중앙화됩니다.


7. 자동_의존성_해결

개요

메타데이터를 활용해 의존성을 자동으로 주입하는 고급 패턴입니다.

코드 예제

const Injectable = () => (target: any) => {
  target.injectable = true;
};

@Injectable()
class ApiService {
  constructor(private http: HttpClient) {}
}

function autoResolve<T>(Class: new (...args: any[]) => T): T {
  // 생성자 파라미터 자동 해결
  return new Class(/* auto resolved deps */);
}

설명

데코레이터를 사용해 클래스를 주입 가능하게 표시하고, 컨테이너가 자동으로 의존성을 해결합니다.


8. 스코프_관리_패턴

개요

의존성의 생명주기를 Singleton, Transient, Scoped로 관리합니다.

코드 예제

enum Scope { Singleton, Transient, Scoped }

class Container {
  register(name: string, factory: () => any, scope: Scope) {
    if (scope === Scope.Singleton) {
      const instance = factory();
      return () => instance;
    }
    return factory; // Transient
  }
}

container.register('db', () => new Database(), Scope.Singleton);

설명

Singleton은 하나의 인스턴스를 공유하고, Transient는 매번 새로 생성합니다. 리소스 관리가 최적화됩니다.


9. 생성자_주입_vs_메서드_주입

개요

필수 의존성은 생성자로, 선택적 의존성은 메서드로 주입하는 하이브리드 패턴입니다.

코드 예제

class OrderService {
  constructor(private db: Database) {} // 필수

  private emailService?: EmailService;

  setEmailService(service: EmailService) { // 선택
    this.emailService = service;
  }

  createOrder() {
    this.db.save(/* ... */);
    this.emailService?.sendConfirmation();
  }
}

설명

필수 의존성은 생성자로 강제하고, 선택적 기능은 메서드로 주입하여 유연성을 확보합니다.


10. 순환_의존성_해결

개요

Provider 패턴을 활용해 순환 참조 문제를 우아하게 해결합니다.

코드 예제

class ServiceA {
  private serviceB?: ServiceB;

  setServiceB(b: ServiceB) {
    this.serviceB = b;
  }
}

class ServiceB {
  constructor(private serviceA: ServiceA) {}
}

const a = new ServiceA();
const b = new ServiceB(a);
a.setServiceB(b);

설명

한쪽은 생성자 주입, 다른 쪽은 세터 주입을 사용해 순환 참조를 끊습니다. 의존성 그래프가 명확해집니다.


11. 모듈_기반_DI_시스템

개요

관련된 의존성을 모듈로 그룹화하여 대규모 애플리케이션을 구조화합니다.

코드 예제

class AppModule {
  static providers = [
    { provide: 'Logger', useClass: ConsoleLogger },
    { provide: 'Database', useClass: PostgresDB },
  ];

  static create() {
    const container = new DIContainer();
    this.providers.forEach(p =>
      container.register(p.provide, new p.useClass())
    );
    return container;
  }
}

설명

모듈이 관련 서비스를 묶어 등록하고, 애플리케이션 전체 의존성을 체계적으로 관리합니다.


12. 고급_인터셉터_패턴

개요

의존성 호출을 가로채서 로깅, 캐싱, 에러 핸들링 등을 추가하는 AOP 스타일 패턴입니다.

코드 예제

function createProxy<T extends object>(target: T): T {
  return new Proxy(target, {
    get(obj, prop) {
      const original = obj[prop as keyof T];
      if (typeof original === 'function') {
        return (...args: any[]) => {
          console.log(`Calling ${String(prop)}`);
          return original.apply(obj, args);
        };
      }
      return original;
    }
  });
}

설명

Proxy를 사용해 메서드 호출을 가로채고 추가 로직을 투명하게 실행합니다. 횡단 관심사를 분리합니다.


마치며

이번 글에서는 Dependency Injection 기초부터 심화까지에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#TypeScript #DependencyInjection #DesignPatterns #SOLID #IoC

#TypeScript#DependencyInjection#DesignPatterns#SOLID#IoC