C#고급 주제

dependency injection과 options pattern

서비스 간 결합을 낮추는 DI와 설정을 강한 타입으로 읽는 options pattern이 .NET 애플리케이션에서 어떻게 함께 쓰이는지 정리합니다.

마지막 수정 2026년 3월 22일

기본 패턴

csharp
builder.Services.Configure<AppOptions>(
    builder.Configuration.GetSection("App"));

builder.Services.AddSingleton<GreetingService>();

설명

  • dependency injection은 객체가 필요한 의존성을 직접 만들지 않고, 외부 컨테이너가 주입하게 하는 구조입니다. 핵심 목적은 테스트 용이성보다도 먼저 결합도를 낮추고 구성 책임을 한곳에 모으는 데 있습니다.
  • .NET 생태계에서는 DI와 설정 바인딩이 자연스럽게 연결됩니다. 설정을 IConfiguration에서 바로 문자열로 꺼내 쓰기보다, options pattern으로 강한 타입 객체에 바인딩한 뒤 필요한 서비스에 주입하는 흐름이 일반적입니다.
  • IOptions<T>, IOptionsSnapshot<T>, IOptionsMonitor<T>는 "언제 읽고 얼마나 자주 갱신할 것인가"에 따라 선택지가 달라집니다. 그래서 설정도 단순 데이터가 아니라 수명(lifetime) 개념과 연결됩니다.
  • DI를 이해할 때 중요한 것은 등록과 해석보다 lifetime입니다. singleton, scoped, transient가 잘못 섞이면 상태 공유와 dispose 시점 문제가 생길 수 있습니다.
  • 이 주제는 C# 문법을 넘어 .NET 애플리케이션 구조의 핵심입니다. 서비스 객체와 설정 객체를 어떤 경계에서 주입할지 감이 생기면, 웹 앱과 백그라운드 작업 모두 구조가 훨씬 읽기 쉬워집니다.

빠른 정리

요소역할
DI container의존성 생성과 연결 관리
AddSingleton / AddScoped / AddTransient수명 등록
Configure<TOptions>설정을 강한 타입으로 바인딩
IOptions<T>설정 읽기
핵심 질문이 서비스와 설정은 얼마나 오래 살아야 하는가

주의할 점

DI는 "new를 줄이는 기술"이 아니라 수명과 결합도를 관리하는 구조입니다. 특히 scoped 서비스를 singleton에 넣는 식의 lifetime 충돌은 겉보기보다 위험하므로 등록 단계에서 먼저 점검하는 편이 중요합니다.

참고 링크

2 sources