본문 바로가기

Typescript

[Typescript] tsyringe: JavaScript/TypeScript 의존성 주입 라이브러리

728x90

개요

tsyringe는 TypeScript와 JavaScript에서 의존성 주입(Dependency Injection)을 가능하게 하는 경량 라이브러리입니다. 의존성 주입은 객체 간의 결합도를 낮추고, 테스트 가능성을 높이며, 코드의 유지 보수를 쉽게 하는 데 유용합니다. 

 

 

1. 의존성 주입의 개념

의존성 주입은 객체가 직접 의존성을 생성하지 않고, 외부에서 제공받는 디자인 패턴입니다. 이를 통해 객체 간의 결합도를 낮추고, 모듈화와 테스트 가능성을 높일 수 있습니다.

 

2. tsyringe 설치

tsyringe를 설치하려면 npm 또는 yarn을 사용할 수 있습니다.

npm install tsyringe reflect-metadata

또는

yarn add tsyringe reflect-metadata

 

reflect-metadata는 데코레이터를 사용하기 위해 필요합니다.

 

3. 기본 사용법

1. 설정

TypeScript 설정 파일(tsconfig.json)에서 experimentalDecoratorsemitDecoratorMetadata 옵션을 활성화해야 합니다.

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

2. 간단한 예제

먼저, 의존성을 정의하고, 이를 tsyringe를 통해 주입해 보겠습니다.

import 'reflect-metadata';
import { container, injectable, inject } from 'tsyringe';

@injectable()
class Logger {
  log(message: string) {
    console.log('Logger:', message);
  }
}

@injectable()
class UserService {
  constructor(@inject(Logger) private logger: Logger) {}

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

// 의존성 주입을 통해 객체 생성
const userService = container.resolve(UserService);
userService.createUser('John Doe');

 

위 예제에서 LoggerUserService 클래스는 @injectable() 데코레이터로 표시되어 tsyringe 컨테이너에 등록됩니다. UserService의 생성자에서 Logger를 주입받아 사용합니다. container.resolve(UserService)를 통해 UserService 인스턴스를 생성할 때, tsyringe가 자동으로 Logger 인스턴스를 주입합니다.

 

4. 고급 사용법

1. 싱글톤 패턴

tsyringe는 싱글톤 패턴을 쉽게 구현할 수 있습니다.

@singleton()
class DatabaseConnection {
  connect() {
    console.log('Database connected');
  }
}

// 싱글톤 인스턴스 주입
const db1 = container.resolve(DatabaseConnection);
const db2 = container.resolve(DatabaseConnection);

console.log(db1 === db2); // true

 

2. 등록 방식

 

tsyringe는 클래스를 자동으로 주입하는 것 외에도 수동으로 주입할 수 있는 다양한 방법을 제공합니다.

interface IDatabase {
  connect(): void;
}

@injectable()
class MySQLDatabase implements IDatabase {
  connect() {
    console.log('MySQL Database connected');
  }
}

// 인터페이스와 구현체를 수동으로 등록
container.register<IDatabase>('IDatabase', {
  useClass: MySQLDatabase
});

@injectable()
class App {
  constructor(@inject('IDatabase') private database: IDatabase) {}

  start() {
    this.database.connect();
  }
}

const app = container.resolve(App);
app.start();

 

3. Factory와 Value Providers

 

tsyringe는 팩토리와 값 제공자도 지원합니다.

// 값 제공자
container.register('API_URL', { useValue: 'https://api.example.com' });

@injectable()
class ApiService {
  constructor(@inject('API_URL') private apiUrl: string) {}

  fetchData() {
    console.log(`Fetching data from ${this.apiUrl}`);
  }
}

const apiService = container.resolve(ApiService);
apiService.fetchData();

 

5. 다른 의존성 주입 라이브러리와의 비교

 

InversifyJS

  • 장점: InversifyJS는 더 많은 기능과 유연성을 제공하며, 대규모 애플리케이션에 적합합니다.
  • 단점: 설정이 다소 복잡하고, 사용법이 tsyringe보다 어렵습니다.

tsyringe

  • 장점: 경량 라이브러리로 설정이 간단하고 사용법이 직관적입니다. 소규모에서 중규모 애플리케이션에 적합합니다.
  • 단점: 기능이 InversifyJS보다 제한적입니다.

 

6. 요약

tsyringe는 TypeScript와 JavaScript에서 의존성 주입을 쉽게 구현할 수 있는 경량 라이브러리입니다. 이를 통해 코드의 결합도를 낮추고, 테스트 가능성과 유지보수성을 높일 수 있습니다. tsyringe는 설정이 간단하고 사용법이 직관적이어서, 소규모에서 중규모 애플리케이션에 특히 유용합니다.

 

주요 포인트:

  • @injectable 데코레이터로 클래스 등록
  • @inject 데코레이터로 의존성 주입
  • container.resolve로 인스턴스 생성
  • 싱글톤, 수동 등록, 값 제공자 등 다양한 기능 지원

reference :

https://github.com/microsoft/tsyringe