[C#] Singleton 패턴 잘못 쓰면 발생하는 문제 – 메모리 누수 & DI 문제

2025. 3. 24. 08:25·프로그래밍/C#

[C#] Singleton 패턴 잘못 쓰면 발생하는 문제 – 메모리 누수 & DI 문제

C#에서 Singleton 패턴은 전역 인스턴스를 하나만 유지한다는 점에서 자주 사용됩니다. 하지만 잘못된 싱글톤 사용은 메모리 누수, 테스트 어려움, 의존성 주입(DI) 충돌 등의 문제를 발생시킬 수 있습니다.

이 글에서는 Singleton 패턴의 기본 구조와 함께 실무에서 문제가 되는 사용 예, 그리고 올바른 구현 방법을 소개하겠습니다.


✅ Singleton 패턴 기본 구조


// 기본 싱글톤 구현 (Lazy + Thread-safe)
public sealed class MyService
{
    private static readonly Lazy<MyService> instance =
        new Lazy<MyService>(() => new MyService());

    public static MyService Instance => instance.Value;

    private MyService()
    {
        // 생성자
    }

    public void DoSomething()
    {
        Console.WriteLine("작업 실행");
    }
}

이 구조는 실무에서 가장 많이 쓰이는 Lazy + Thread-safe 패턴입니다.
하지만 아래와 같은 문제들을 유발할 수 있습니다.


⚠️ 문제 1 – 테스트 코드 작성 어려움

싱글톤 인스턴스는 전역 상태를 가지기 때문에, 단위 테스트에서 격리(Isolation)된 테스트 작성이 어렵습니다.
Mocking이 어렵고, 테스트 간 상태 공유로 인해 예기치 않은 결과가 발생할 수 있습니다.


// 다음 테스트는 상태 공유 문제를 일으킬 수 있음
MyService.Instance.DoSomething(); // 이전 테스트의 상태가 남아있음

⚠️ 문제 2 – DI(Dependency Injection)와 충돌

최근에는 의존성 주입(Dependency Injection)을 활용하는 경우가 많은데, 이 때 Singleton 패턴은 DI 컨테이너가 객체 생명주기를 관리하는 방식과 충돌할 수 있습니다.


// DI Container에서 관리되는 객체 예시
services.AddSingleton<IMyService, MyService>();

DI 컨테이너를 사용한다면 굳이 수동으로 Singleton 패턴을 구현할 필요 없이 컨테이너에게 Singleton 생명주기를 맡기는 게 더 안전하고 유연합니다.


⚠️ 문제 3 – 메모리 누수

GC(가비지 컬렉터)는 더 이상 참조되지 않는 객체를 정리하지만, Singleton은 앱 종료 시까지 메모리에 유지되기 때문에 불필요한 리소스가 계속 메모리에 남아 메모리 누수처럼 보일 수 있습니다.


// 싱글톤 내부에서 IDisposable 리소스를 직접 관리하면 누수 위험
private SqlConnection conn = new SqlConnection(...);

→ 이럴 땐 IDisposable을 구현하지 말고, 외부에서 의존성 주입 받는 구조로 개선해야 합니다.


✅ 해결 방법 – DI와 함께 쓰는 Singleton

.NET Core 이상에서는 Microsoft.Extensions.DependencyInjection을 통해 싱글톤 생명주기를 컨트롤 할 수 있습니다.


// Startup.cs 또는 Program.cs에서 등록
services.AddSingleton<IMyService, MyService>();

// 생성자 주입으로 사용
public class MyController
{
    private readonly IMyService myService;

    public MyController(IMyService myService)
    {
        this.myService = myService;
    }
}

이처럼 DI Container를 활용한 Singleton 등록 방식이 테스트 코드 작성, 생명주기 관리, 메모리 안정성 측면에서 훨씬 유리합니다.


🧠 마무리 요약

  • 전통적인 Singleton 패턴은 간단하지만 테스트/확장/DI 측면에서 단점이 많음
  • 의존성 주입을 활용해 Singleton을 안전하게 구현하는 것이 권장됨
  • 싱글톤 내부에 리소스를 직접 소유하지 말고, 외부에서 주입받는 구조가 이상적

실무에서는 항상 유지보수성과 테스트 가능성을 고려한 구조 설계가 중요합니다.
이 글이 도움이 되셨다면 공감/댓글 부탁드려요 😊

반응형
저작자표시 비영리

'프로그래밍 > C#' 카테고리의 다른 글

[C#] DevExpress WinForms GridView 속도 개선 팁 – 렌더링 최적화 & 클릭 지연 해결  (0) 2025.03.24
[C#] Singleton, Scoped, Transient 차이점 – DI Container 생명주기 완전 정리  (0) 2025.03.24
[C#] 디자인 패턴 - 실무에서 가장 많이 쓰는 디자인 패턴 3가지 정리 (Singleton, Factory, Command)  (0) 2025.03.21
[C#] Winform/Devexpress GridView DoubleClick Event  (0) 2023.06.29
[C#] Winform/WPF 디자인모드(DesignMode) 구분하기  (0) 2023.06.28
'프로그래밍/C#' 카테고리의 다른 글
  • [C#] DevExpress WinForms GridView 속도 개선 팁 – 렌더링 최적화 & 클릭 지연 해결
  • [C#] Singleton, Scoped, Transient 차이점 – DI Container 생명주기 완전 정리
  • [C#] 디자인 패턴 - 실무에서 가장 많이 쓰는 디자인 패턴 3가지 정리 (Singleton, Factory, Command)
  • [C#] Winform/Devexpress GridView DoubleClick Event
큐레이트
큐레이트
저의 일상을 기록하는 블로그입니다.
  • 큐레이트
    큐레이트의 기록
    큐레이트
  • 전체
    오늘
    어제
    • 분류 전체보기 (186) N
      • 국내여행 (37)
        • 애견여행 (33)
        • 맛집여행 (2)
      • 프로그래밍 (81)
        • C# (24)
        • Python (23)
        • Flutter (5)
        • .NET (4)
        • ASP (7)
        • Html (5)
        • Tomcat (2)
        • typescript (3)
        • etc (8)
      • 일상생활 (68) N
        • 다이어트일지 (67) N
        • 기타 (1)
  • 블로그 메뉴

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

    • 복이랑스마트스토어
    • 복이랑블로그
  • 공지사항

    • 블로그 소개
  • 인기 글

  • 태그

    애견동반
    다이어트일지
    식단
    pt
    오블완
    일상생활
    국내여행
    파이썬
    티스토리챌린지
    애견동반여행
    FastAPI
    식단관리
    제주도
    운동일지
    HTML
    오운완
    다이어트 일지
    코인자동매매
    애견여행
    입력폼
    제주도 애견동반
    Flutter
    iis
    Python
    제주도애견동반여행
    C#
    체중기록
    DevExpress
    자동매매
    다이어트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
큐레이트
[C#] Singleton 패턴 잘못 쓰면 발생하는 문제 – 메모리 누수 & DI 문제
상단으로

티스토리툴바