0Pricing
C# Academy · 강의

Worker Service 프로젝트

독립 실행형 Worker Service를 만들고 DI와 로깅을 구성하며 Windows 서비스 또는 Linux 데몬으로 배포합니다.

Worker Service 프로젝트은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Worker Service란 무엇입니까?

Worker Service는 장시간 실행되는 백그라운드 애플리케이션을 만들기 위한 .NET 프로젝트 템플릿입니다. 웹 서버나 HTTP 엔드포인트가 없습니다. 큐 처리기, 예약된 작업, 데몬 형태의 서비스에 적합한 가벼운 호스트입니다.

Worker Service 만들기

CLI 템플릿을 사용하여 Worker Service 프로젝트의 기본 구조를 생성합니다. 최소한의 Program.cs와 BackgroundService를 상속하는 Worker.cs 클래스가 생성됩니다.

# Create a new Worker Service project
dotnet new worker -n OrderProcessor

# Generated structure:
# OrderProcessor/
#   Program.cs       — host configuration
#   Worker.cs        — your BackgroundService subclass
#   appsettings.json

Worker Service Program.cs

생성된 Program.cs는 제네릭 호스트를 사용합니다. DI, 로그 기록, 구성 및 작업자를 등록하도록 설정하며, 웹 서버가 없다는 점을 제외하면 ASP.NET Core와 동일합니다.

using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Register services
builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddScoped<IOrderRepository, OrderRepository>();
builder.Services.AddHostedService<OrderProcessorWorker>();

var host = builder.Build();
host.Run();

Worker 클래스

BackgroundService를 상속하고 ExecuteAsync를 구현합니다. 호스트는 시작 시 이 메서드를 호출하고, 종료 시 발생하는 취소 토큰을 전달합니다.

public class OrderProcessorWorker : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<OrderProcessorWorker> _logger;

    public OrderProcessorWorker(
        IServiceScopeFactory factory,
        ILogger<OrderProcessorWorker> logger)
    {
        _factory = factory;
        _logger  = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            using var scope = _factory.CreateScope();
            var repo = scope.ServiceProvider.GetRequiredService<IOrderRepository>();
            var pending = await repo.GetPendingAsync(ct);
            foreach (var order in pending)
                await ProcessOrderAsync(order, ct);
            await Task.Delay(TimeSpan.FromSeconds(10), ct);
        }
    }

    private Task ProcessOrderAsync(Order o, CancellationToken ct) =>
        Task.Delay(100, ct); // placeholder
}

Worker의 구성 및 DI

Worker Service는 앱 설정, 환경 변수, 사용자 암호를 포함한 전체 .NET 구성 시스템을 지원합니다. IConfiguration 또는 강력한 형식의 옵션을 주입하세요.

builder.Services.Configure<WorkerSettings>(
    builder.Configuration.GetSection("Worker"));

public class OrderProcessorWorker : BackgroundService
{
    private readonly WorkerSettings _settings;

    public OrderProcessorWorker(IOptions<WorkerSettings> opts, ...)
        => _settings = opts.Value;

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            // ...
            await Task.Delay(_settings.PollIntervalSeconds * 1000, ct);
        }
    }
}

Worker Service의 로그 기록

제네릭 호스트가 로그 기록을 자동으로 구성합니다. 구조화된 로그 기록에는 ILogger<T>를 사용하세요. 운영 환경에서는 Serilog, Application Insights 또는 다른 공급자를 구성하세요.

// Add Serilog to a Worker Service
builder.Host.UseSerilog((ctx, logConfig) =>
    logConfig
        .ReadFrom.Configuration(ctx.Configuration)
        .WriteTo.Console()
        .WriteTo.Seq(ctx.Configuration["Seq:ServerUrl"]!));

// Structured logging in the worker:
_logger.LogInformation("Processing {Count} orders at {Time}",
    orders.Count, DateTimeOffset.UtcNow);
_logger.LogError(ex, "Failed to process order {OrderId}", order.Id);

Windows 서비스로 실행

UseWindowsService()를 사용하면 Worker를 Windows 서비스로 실행할 수 있습니다. 서비스가 OS와 함께 시작 및 중지되고 사용자가 로그아웃한 후에도 계속 실행됩니다.

// dotnet add package Microsoft.Extensions.Hosting.WindowsServices

builder.Services.AddWindowsService(options =>
    options.ServiceName = "OrderProcessor");

// Build and publish:
// dotnet publish -c Release -o ./publish

// Install as Windows Service:
// sc create OrderProcessor binpath="C:\services\publish\OrderProcessor.exe"
// sc start OrderProcessor

Linux systemd 데몬으로 실행

UseSystemd()를 사용하여 Linux의 systemd와 통합하세요. 서비스가 적절한 중지 신호를 받고 journald 로그 기록과 통합됩니다.

// dotnet add package Microsoft.Extensions.Hosting.Systemd

builder.Services.AddSystemd();

// Systemd unit file: /etc/systemd/system/orderprocessor.service
// [Unit]
// Description=Order Processor Worker
// [Service]
// Type=notify
// ExecStart=/usr/bin/dotnet /app/OrderProcessor.dll
// Restart=always
// [Install]
// WantedBy=multi-user.target

// Commands:
// sudo systemctl enable orderprocessor
// sudo systemctl start orderprocessor
// sudo journalctl -u orderprocessor -f

Docker에서 실행

Worker Service는 Docker 컨테이너에 적합합니다. 포트 매핑이 필요하지 않으며, 컨테이너가 중지될 때까지 프로세스를 반복 실행하면 됩니다.

# Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app

FROM mcr.microsoft.com/dotnet/runtime:9.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "OrderProcessor.dll"]

# docker-compose.yml:
# services:
#   worker:
#     build: .
#     environment:
#       - ConnectionStrings__Default=Server=db;...
#     depends_on: [db]

실전: 이메일 요약 작업자

데이터베이스에서 정보를 읽고 이메일 서비스를 통해 발송하여 매일 이메일 요약을 보내는 완전한 작업자입니다.

public class EmailDigestWorker : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<EmailDigestWorker> _log;

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        // Run daily at midnight UTC
        while (!ct.IsCancellationRequested)
        {
            var now = DateTime.UtcNow;
            var next = now.Date.AddDays(1); // next midnight
            await Task.Delay(next - now, ct);

            using var scope = _factory.CreateScope();
            var mailer = scope.ServiceProvider.GetRequiredService<IDigestMailer>();

            try   { await mailer.SendDailyDigestsAsync(ct); }
            catch (Exception ex) { _log.LogError(ex, "Digest failed"); }
        }
    }
}

빠른 확인

Worker Service 프로젝트와 ASP.NET Core Web API 프로젝트의 가장 큰 차이는 무엇입니까?

복습: Worker Service 프로젝트

핵심 요점:

  • Worker Service = 제네릭 호스트 + BackgroundService, 웹 서버 없음
  • 전체 DI, 로그 기록 및 구성 지원 — 단 HTTP는 지원하지 않음
  • Windows 서비스 배포에는 UseWindowsService() 사용
  • journald 통합을 지원하는 Linux 데몬에는 UseSystemd() 사용
  • 클라우드 네이티브 백그라운드 처리를 위해 Docker 컨테이너에 배포
  • 작업자에서 범위 지정 종속성을 사용할 때는 항상 IServiceScopeFactory 사용

자주 묻는 질문

“Worker Service 프로젝트” 강의는 무료인가요?

네 — “Worker Service 프로젝트” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“Worker Service 프로젝트”에서 뭘 배우나요?

독립 실행형 Worker Service를 만들고 DI와 로깅을 구성하며 Windows 서비스 또는 Linux 데몬으로 배포합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“Worker Service 프로젝트” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. IHostedService와 BackgroundService
  2. Worker Service 프로젝트
  3. 주기적 작업과 타이머
  4. Quartz.NET 예약 작업
← C# Academy(으)로 돌아가기