IServiceScopeFactory 란?
IServiceScopeFactory 는 ASP.NET Core의 의존성 주입(DI) 컨테이너에서 새로운 서비스 범위(Scope) 를 만들기 위한 팩토리 인터페이스입니다.
기본적으로 DI 컨테이너는 Singleton / Scoped / Transient 세 가지 생명주기를 제공합니다.
일반적으로 Scoped 서비스는 HTTP 요청(Request)마다 생성되고, 요청이 끝나면 해제됩니다.
하지만 BackgroundService, Singleton 클래스 안에서는 Scoped 서비스를 직접 DI 받을 수 없습니다.
이를 해결하기 위하여 IServiceScopeFactory 를 이용해 임시 Scope를 만들어서 Scoped 서비스를 안전하게 사용합니다.
| 구분 | Singleton | Scoped | Transient |
|---|---|---|---|
| 인스턴스 생성 시점 | 애플리케이션 시작 시 한 번 | 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);
}
}
정리
IServiceScopeFactory는 Scoped 서비스의 생명주기를 직접 제어할 수 있게 해줍니다.- 주로 Singleton 객체나 BackgroundService 에서 Scoped 서비스를 안전하게 사용하기 위해 필요합니다.
CreateScope()로 범위를 열고, 작업이 끝나면 자동으로 Dispose 되어 메모리 누수 없이 관리됩니다.



Scoped 서비스와 `IServiceScopeFactory`의 쓸모는 정말 대단하네요! 개념만 이해하고 사용하면 뭐, 깔끔하게 관리할 수 있겠는데요. 그런데 왜 이게 Grow a garden mutation calculator 이라는 블로그에 올라와 있는 거지? 아마도 이게 특별한 농법이나 식물 변이 계산기인 줄 알고 찾아온 사람들이 많았을지도 모르겠네요. 뭐, Scoped 서비스는 확실히 쓸만하지만, 이게 농사와 무슨 연관이 있는지는 궁금하네요.quay random
Scoped 서비스와 `IServiceScopeFactory`의 쓸모는 정말 대단하네요! Singleton처럼 영원히 살아있는 것들한테 Scoped 서비스를 주는 건 꿀잠이라도 자는 거겠죠? BackgroundService에서 안심하고 쓸 수 있게 해주는 부분은 진짜 고양이 밥 같아요. 물론, 임시 Scope를 열 때마다 새로운 인스턴스를 만드는 거라 좀 번거로울 수도 있겠지만, 그래야 메모리가 터질까도 모르니까 안전장치라는 거겠죠! 이건 개발자들에게는 정말 최고의 선물이겠어요!grow a garden calculator