Singleton VS DI

2024. 2. 12. 18:04·프로그래밍 언어/C#

✅ 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,,,

싱글턴을 사용하는 것이 더 나은 경우

  • 환경 의존성(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
'프로그래밍 언어/C#' 카테고리의 다른 글
  • 컴파일 타임 상수와 런타임 상수: 어떤 것을 사용해야 할까?
  • C#에서 var를 사용하는 이유와 주의사항
  • 비동기 프로그래밍
  • 람다식 () =>
가든_
가든_
  • 가든_
    Code Garden
    가든_
  • 전체
    오늘
    어제
    • 글 목록 (60)
      • 프로그래밍 언어 (11)
        • JAVA (0)
        • C++ (2)
        • C# (9)
      • 개발툴 (24)
        • Visual Studio (0)
        • Visual Studio Code (1)
        • Eclipse (1)
        • Unity (19)
        • Unreal (0)
        • Spring (1)
        • SpringBoot (0)
        • Vue (2)
      • 디자인 패턴 (6)
      • 백엔드 (4)
        • MySQL (1)
        • Servlet (3)
      • 프론트엔드 (4)
        • HTML (3)
        • CSS (0)
        • Javascript (1)
      • 알고리즘 (10)
        • 공식 (3)
        • 백준 (6)
        • SW Expert Academy (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    구조적 UML 다이어그램
    Reflex
    ()=>
    Java
    Adaptee
    오브젝터 어댑터
    Proxy 패턴
    스택
    DI
    UniRX
    chatGPT
    컴파일 상수
    다이어그램 그리기
    런타임 상수
    c#
    FixedUpdate
    swea2112
    행동 UML 다이어그램
    Adapter 패턴
    상태공간트리
    Unity
    MVC
    클래스 어댑터
    Abstract Factory 패턴
    구조패턴
    HTML
    RDBM
    SetTile
    12738
    Factory 패턴
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
가든_
Singleton VS DI
상단으로

티스토리툴바