IServiceScopeFactory 인터페이스

IServiceScopeFactory 란?

https://learn.microsoft.com/ko-kr/dotnet/api/microsoft.extensions.dependencyinjection.iservicescopefactory?view=net-8.0

IServiceScopeFactory 는 ASP.NET Core의 의존성 주입(DI) 컨테이너에서 새로운 서비스 범위(Scope) 를 만들기 위한 팩토리 인터페이스입니다.

기본적으로 DI 컨테이너는 Singleton / Scoped / Transient 세 가지 생명주기를 제공합니다.

일반적으로 Scoped 서비스는 HTTP 요청(Request)마다 생성되고, 요청이 끝나면 해제됩니다.

하지만 BackgroundService, Singleton 클래스 안에서는 Scoped 서비스를 직접 DI 받을 수 없습니다.

이를 해결하기 위하여 IServiceScopeFactory 를 이용해 임시 Scope를 만들어서 Scoped 서비스를 안전하게 사용합니다.

구분SingletonScopedTransient
인스턴스 생성 시점애플리케이션 시작 시 한 번HTTP 요청 시작 시 한 번의존성 주입 요청 시마다
인스턴스 수명애플리케이션 전체 수명HTTP 요청 수명가장 짧은 수명
공유 범위전체 애플리케이션에서 단일 인스턴스 공유동일 HTTP 요청 내에서 동일 인스턴스 공유매번 새로운 인스턴스 생성
사용 사례– 캐시 서비스
– 설정 관리자
– 로깅 서비스
– DB Context
– 사용자 세션
– 트랜잭션 관리
– 경량 서비스
– 상태 없는 헬퍼
– 일회성 작업
주의사항상태 저장 시 thread-safe 고려 필요요청 간 상태 공유 불가빈번한 생성으로 성능 영향 가능성

사용법

1. 기본적인 사용법

using (var scope = scopeFactory.CreateScope())
{
    var myService = scope.ServiceProvider.GetRequiredService<MyScopedService>();
    myService.DoSomething();
}
// scope.Dispose()가 호출되면서 MyScopedService도 정리됨

2. BackgroundService에서 DbContext 사용하기

public class MyWorker : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public MyWorker(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _scopeFactory.CreateScope();
            var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();

            var users = await db.Users.ToListAsync(stoppingToken);
            Console.WriteLine($"현재 사용자 수: {users.Count}");

            await Task.Delay(5000, stoppingToken);
        }
    }
}

// MyDbContext 가 Scoped 로 등록되어 있어도 Worker에서 안전하게 사용 가능.

3. Scoped 서비스 임시 실행

public class ReportGenerator
{
    private readonly IServiceScopeFactory _scopeFactory;

    public ReportGenerator(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public void Generate()
    {
        using var scope = _scopeFactory.CreateScope();
        var service = scope.ServiceProvider.GetRequiredService<ReportService>();

        service.CreateDailyReport();
    }
}

// ReportService 가 Scoped 로 등록되어 있어도 IServiceScopeFactory 를 사용해 특정 시점에만 실행 가능.

4. 여러 Scoped 서비스 조합

public class CleanupJob
{
    private readonly IServiceScopeFactory _scopeFactory;

    public CleanupJob(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public async Task RunAsync()
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
        var emailService = scope.ServiceProvider.GetRequiredService<EmailService>();

        var expiredUsers = db.Users.Where(u => u.IsExpired).ToList();
        db.Users.RemoveRange(expiredUsers);
        await db.SaveChangesAsync();

        await emailService.SendCleanupReport(expiredUsers.Count);
    }
}

정리

  • IServiceScopeFactoryScoped 서비스의 생명주기를 직접 제어할 수 있게 해줍니다.
  • 주로 Singleton 객체나 BackgroundService 에서 Scoped 서비스를 안전하게 사용하기 위해 필요합니다.
  • CreateScope() 로 범위를 열고, 작업이 끝나면 자동으로 Dispose 되어 메모리 누수 없이 관리됩니다.

“IServiceScopeFactory 인터페이스”에 대한 5개의 생각

  1. 좋은 지혜를 얻었습니다! `IServiceScopeFactory`는 개발자의 삶을 구원하는 중요한 도구이지만, 농법 블로그에 나와 있는 건 정말 신기하네요. 개발자들이 이런 기능을 찾을 때 농법 블로그에 먼지 쌓이는 건 아쉽지만, 만약 농가들이 이 기술을 농사에 적용한다면 Scope 농법이라는 새로운 트렌드가 생길지도 모릅니다. 예를 들어, 비료를 주는 시점을 스코프에 맞춰 정확히 관리하면 농사 생산성이 폭발적으로 증가할지도 모릅니다. 그래도 개발자들이 이 기능을 찾을 때 농법 블로그에 먼지 쌓이는 건 정말 아쉽네요!vòng quay may

  2. Scoped 서비스와 `IServiceScopeFactory`는 확실히 대단한 기능이지만, 왜 농법 블로그에 나와 있는지는 정말 궁금하네요. 아마도 Scope라는 단어 때문에 농가들이 식물의 생애주기를 관리하려고 찾아온 것 같기도 하고요. 그래도 이게 개발자들의 세계에서는 정말 유용하니, 농가들이 이걸로 농사를 짓는다면 아마 매우 혁신적인 Scope 농법이 될지도 모르겠습니다. 그래도 개발자들이 이런 기능을 찾을 때 농법 블로그에 먼지 쌓이는 건 아쉽네요.random wheel

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤