✅ Singleton VS DI
Singleton
- GoF 책에서 나온 가장 기본적인 디자인 패턴
- 싱글톤은 응용 프로그램 전체 수명 동안 어떤 클래스의 인스턴스를 하나만 가지는 것을 의미하는 디자인 패턴이다
- 싱글톤을 사용하는 것은 본질적으로 나쁜 것은 아님.
일반적인 구현 방법
public class BankGateway
{
public readonly static BankGateway Instance = new BankGateway();
private BankGateway()
{
}
public void TransferMoney()
{
/* Transferring money */
}
}
- private를 생성자로 가지며, Instance 참조를 통해 인스턴스를 유일하게 가져올 수 있다.
- static이기 때문에 응용 프로그램 프로세스가 실행 중인 한 계속 유지 된다. (응용 프로그램의 수명에 바인딩 됨)
- 그렇기 때문에 지연 로딩을 지원하지 않는다.
- 객체는 필요 여부에 관계 없이 로드 시에 인스턴스 된다. (실제로는 조금 더 복잡하다)
단점
- 종속성 주입 원칙과 모순되어 테스트 가능성 방해
- 전역 상수로 작동하기 때문에 필요할 때 대체하기 어렵다.
- 싱글턴을 부를때마다 실제(Origin) 데이터로 불러오기 때문에 테스트가 어려움
- 이것은 유닛 테스트시 피해야 하는 것 중 하나이다.
- 애플리케이션이 항상 모든 것을 메모리에 유지하게 된다.
Dependency Injection
- 객체에 의존성을 전달하는 디자인 패턴
일반적인 구현 방법
public interface IBankGateway
{
void TransferMoney();
}
public class BankGateway : IBankGateway
{
public void TransferMoney()
{
/* Transferring money */
}
}
public class Processor
{
private readonly IBankGateway_gateway;
public Processor(IBankGateway gateway)
{
_gateway = gateway;
}
public void Process()
{
_gateway.TransferMoney();
}
}
- 이 코드는 테스트 가능하다.
- 가짜 BankGateway를 만들고 프로세서에 전달해서 돈을 이체하는지 확인할 수 있다.
- 실제 은행 게이트웨이에는 호출이 이루어지지 않는다.
기본 클래스 외부에 객체를 만들어야 하는 이유?
- 코드를 완전히 테스트 가능하다.
- 언제나 필요한 스크립트의 동작이 포함된 다른 구현으로 대체할 수 있다.
- 생성 작업과 사용 작업의 분리가 가능하다.
- 클래스에 제공되는 종속성 유형을 제어할 수 있다.
- DI 컨테이너를 사용하면 저장된 종속성 유형을 정의하고, 이를 약한 링크, 직접 링크, 또는 싱글톤 유형의 링크로 전송할 수 있다.
Singleton vs Dependency Injection
- 대부분의 경우 Dependency Injection이 선호된다.
- non-stable한 dependency가 있다면 해당하는 의존성을 주입해서 종속 클래스가 필요한 것을 명시적으로 지정하는 것이 좋다.
- non-stable dependency : 전역 상태를 참조하는 것
- ex) external service, file system, database,,,
- non-stable dependency : 전역 상태를 참조하는 것
싱글턴을 사용하는 것이 더 나은 경우
- 환경 의존성(Ambient dependencies)
- 여러 클래스 및 레이어에 걸친 의존성
- 이런 종류의 의존성에 대해서는 의존성 주입 패턴을 적용하는 것에 별로 의미가 없다. 왜냐하면 어디에나 존재할 것이기 때문이다.

- 세가지 서비스 각각 의존성 #1이 존재한다. → 싱글턴 추출 가능

- 의존성 제거를 통해 전체 그래프를 단순하게 만들었다.
❓ 싱글턴을 도입해야 하는 경우 의존성이 대부분의 클래스 및 응용 프로그램의 여러 레이어를 횡단하는 경우 싱글턴을 사용해서 해당 의존성을 추출할 수 있다.
결론
- Singleton과 DI를 사용할 땐 주입된 의존성 사이의 균형을 유지하는 것이 중요하다.
- singleton 사용 : 의존성이 많은 클래스와 레이어에서 사용되는 경우
- di 사용 : 이 외에 사용
📜참고자료
Singleton vs Dependency Injection
Dependency injection and Singleton. Everything you need to know and a little more
'프로그래밍 언어 > C#' 카테고리의 다른 글
| 컴파일 타임 상수와 런타임 상수: 어떤 것을 사용해야 할까? (0) | 2024.02.29 |
|---|---|
| C#에서 var를 사용하는 이유와 주의사항 (0) | 2024.02.26 |
| 비동기 프로그래밍 (0) | 2023.12.25 |
| 람다식 () => (0) | 2023.11.01 |
| C#과 .NET Framework (0) | 2023.10.08 |