TypeScript에서 Dependency Injection 간소화: `singleton-factory-ts` 살펴보기

발행: (2026년 2월 18일 오후 07:30 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

위에 제공된 Source 링크만 포함되어 있어 번역할 본문이 없습니다. 번역을 원하는 텍스트(본문, 코드 블록 제외)를 제공해 주시면 한국어로 번역해 드리겠습니다.

핵심 개념: SingletonSingletonFactory

**singleton-factory-ts**의 핵심에는 두 가지 주요 구성 요소가 있습니다:

  • 서비스가 확장할 추상 Singleton 기본 클래스.
  • SingletonFactory(자체도 싱글톤)로, 의존성을 해결하고 캐시를 관리하며 순환 의존성 같은 아키텍처 결함을 감지합니다.

컨테이너에 서비스를 수동으로 등록하는 대신, 클래스는 static getter를 사용해 자체 의존성을 선언합니다.

Source:

깔끔하고 선언적인 사용법

라이브러리의 개발자 경험은 직관적입니다. 아래는 싱글톤과 그 관계를 정의하는 일반적인 예시입니다:

import { Singleton, SingletonClassType } from 'singleton-factory-ts';

// A base singleton with no dependencies
class S1 extends Singleton {
  doSomething() {
    console.log("S1 is working!");
  }
}

// A singleton that depends on S1
class S2 extends Singleton {
  // 1. Declare dependencies declaratively
  static get Dependencies(): [SingletonClassType] {
    return [S1];
  }

  // 2. The factory will automatically inject S1 here
  constructor(protected _s1: S1) {
    super();
  }

  execute() {
    this._s1.doSomething();
  }
}

// 3. Access the instance effortlessly
const s2 = S2.instance;
s2.execute();

S2.instance에 접근하면, 기본 Singleton 클래스가 호출을 가로채 SingletonFactory에 위임합니다. 팩토리는 Dependencies 배열을 읽어 필요한 인스턴스를 재귀적으로 생성(또는 가져오고) S2의 생성자에 주입합니다.

Source:

내부 구조: 무엇이 견고함을 보장할까?

스마트 토큰 캐싱

Singleton을 상속하는 모든 클래스는 Symbol.for(this.className)으로 생성된 InjectorToken을 자동으로 받습니다. SingletonFactory는 이러한 토큰을 저장하는 Map(_singletonCache)을 유지합니다. 이미 인스턴스가 존재하면 캐시된 버전을 반환하여 애플리케이션 전반에 걸쳐 진정한 싱글톤 동작을 보장합니다.

순환 의존성 감지

순환 의존성(예: Service A가 Service B에, Service B가 다시 Service A에 의존) 은 무한 루프를 초래할 수 있습니다. 인스턴스를 생성하는 동안 팩토리는 클래스의 InjectorToken_initializingClasses 집합에 추가합니다. 의존성 트리를 해결하는 과정에서 이미 이 집합에 존재하는 토큰을 만나면 Circular dependency detected for token… 라는 설명적인 오류를 발생시킵니다.

create 메서드를 통한 맞춤 인스턴스화

표준 new Constructor(...) 패턴만으로는 충분하지 않을 때가 있습니다—예를 들어 비동기 작업이나 커스텀 팩토리 로직이 필요할 경우. 라이브러리는 ObjectObject.prototype에 Objective‑C에서 영감을 받은 respondsToSelector 폴리필을 포함합니다. SingletonFactory가 의존성을 해결할 때 클래스가 respondsToSelector("create")를 만족하는지 확인하고, 만족한다면 생성자 대신 Class.create!(...deps)를 호출하여 높은 유연성을 제공합니다.

Real-World Adoption: @greeneyesai/api-utils

이 패턴은 실험적인 수준에 머무르지 않고 실제 운영 환경에서도 사용됩니다. **@greeneyesai/api-utils**는 이 싱글톤‑팩토리 아키텍처의 변형을 채택하여 내부 라이프사이클 및 서비스 의존성을 관리합니다. 이 패턴을 활용함으로써 라이브러리는 핵심 클라이언트, 설정 관리자, 로깅 서비스가 지연 초기화(lazy)되고, 상태를 안정적으로 공유하며, 무거운 DI 프레임워크를 도입하지 않고도 의존성 계약을 강제할 수 있습니다.

결론

엄격한 타입 안전성과 모듈성을 유지하면서 TypeScript 클래스를 디커플링하려는 개발자에게 **singleton-factory-ts**는 간결한 청사진을 제공합니다. 선언적인 정적 Dependencies 배열과 스마트한 중앙 팩터리를 결합함으로써, 가볍고 가독성 높은 패키지 안에서 엔터프라이즈 수준의 DI 기능을 구현합니다.

라이브러리를 직접 임포트하든 @greeneyesai/api-utils와 같은 도구용 아키텍처 변형에 적용하든, 싱글톤 팩터리 패턴은 모든 TypeScript 개발자 도구 상자에 강력한 추가 요소가 됩니다.

https://github.com/arpad1337/singleton-factory-ts

0 조회
Back to Blog

관련 글

더 보기 »