C# 응용 프로그램에서의 Quartz.NET 을 통한 정기 작업 자동화 방안

배경 및 개요

현대 소프트웨어 시스템에서는 특정 시간마다 반복되어야 하는 유지보수 업무나 알림 전송 같은 로직이 빈번히 요구됩니다. 예를 들어, 일정한 주기로 데이터를 집계하여 보고서로 배포하거나, 주기적인 파일 다운로드 및 상태 통지를 수행해야 할 경우 수동 개입 없이 자동으로 처리할 메커니즘이 필수적입니다. 이러한 니즈를 충족시키기 위해 C# 생태계에서 널리 쓰이는 오픈소스 프레임워크인 Quartz.NET 을 활용해 스케줄링 시스템을 구축하는 방법을 살펴보겠습니다.

개발 환경 준비

가장 먼저 Visual Studio 또는 IDE 내의 NuGet Package Manager 를 열어 Quartz 패키지를 검색하고 해당 프로젝트에 의존성으로 추가해야 합니다. 이 과정을 통해 관련 네임스페이스와 클래스들을 사용할 수 있는 기반이 마련됩니다.

작업 로직 정의 (Job 구현)

Quartz 는 실행할 단위 작업을 IJob 인터페이스를 구현한 클래스로 정의합니다. 실제 비즈니스 로직은 Execute 메서드 내부에 작성하며, 여기서는 간단한 로그 출력 예시를 구현해 보겠습니다. 변수명과 클래스 명을 변경하여 구체적인 사용 시나리오 (예: 데이터 정리) 를 반영했습니다.

public class DataCleanUpJob : IJob
{
    public async Task Execute(IJobExecutionContext executionContext)
    {
        try
        {
            string logMessage = $"[실행시간:{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 데이터 정류 작업 시작";
            Console.WriteLine(logMessage);
            
            // 실제 비동기 비즈니스 로직 수행 영역
            await Task.Delay(1000); 
        }
        catch (Exception ex)
        {
            Console.WriteLine($"오류 발생: {ex.Message}");
        }
    }
}

스케줄러 초기화 및 구성

정의된 잡(Job) 을 언제, 어떻게 실행할지 결정하려면 트리거 (Trigger) 와 스케줄러 (Scheduler) 가 필요합니다. 먼저 표준 팩토리를 이용해 스케줄러 인스턴스를 생성한 후 활성화 시킵니다. 이후 개별 잡 세부 정보와 실행 조건인 트리거를 결합하여 등록합니다.

1. 단순 반복 트리거 설정

고정된 시간 간격으로 동작해야 하는 경우에는 SimpleScheduleBuilder 를 사용합니다. 아래 코드에서는 작업을 1 초 마다 무한히 반복하도록 설정하는 예를 보여줍니다.

var jobConfig = JobBuilder.Create<DataCleanUpJob>()
    .WithIdentity("DailyCleanup", "MaintenanceGroup")
    .Build();

var intervalTrigger = TriggerBuilder.Create()
    .WithIdentity("IntervalTrigger", "MaintenanceGroup")
    .WithSimpleSchedule(x =>
    {
        x.WithIntervalInSeconds(1).RepeatForever();
    })
    .Build();

// 스케줄러 생성 및 태스크 등록
var factory = new StdSchedulerFactory();
IScheduler taskManager = await factory.GetScheduler();
await taskManager.Start();
await taskManager.ScheduleJob(jobConfig, intervalTrigger);

고급 시간 지정: 크론 (Cron) 표현식

간단한 반복 외에도 요일, 달, 시각 등 복잡한 규칙을 적용해야 한다면 크론 (Cron) 표현식을 사용하는 것이 효율적입니다. Quartz.NET 의 크론 식은 공백으로 구분된 6 개 또는 7 개의 필드로 이루어집니다. 각 필드는 특정한 범위와 허용되는 특수 문자를 가집니다.

순서 필드명 허용값 범위 특수문자
1 초 (Seconds) 0 ~ 59 , - * /
2 분 (Minutes) 0 ~ 59 , - * /
3 시간 (Hours) 0 ~ 23 , - * /
4 날짜 (Day of Month) 1 ~ 31 , - * ? / L W
5 월 (Month) 1 ~ 12 , - * /
6 요일 (Day of Week) SUN-SAT 또는 1-7 , - * ? / L #
7 연도 (Year) (선택항목) , - * /

예를 들어, 매일 오전 10 시 15 분 정각에 작업을 실행하려는 경우 0 15 10 * * ?라는 식을 입력하면 됩니다. 연도가 필요한 상황이나 요일을 지정할 때는 마지막 필드를 활용하거나 생략 처리를 적절히 조합합니다.

크론 표현식 적용 예제

아래 코드는 매일 매달 15 일에 10 시 15 분에만 실행되도록 구성된 스케줄을 보여주는 실전 예시입니다. 기존 단순 반복과는 달리 WithCronSchedule 메서드를 통해 문자열 형태의 식을 주입합니다.

var monthlyJob = JobBuilder.Create<DataCleanUpJob>()
    .WithIdentity("MonthlyTask", "ReportingGroup")
    .Build();

var cronTrigger = TriggerBuilder.Create()
    .WithIdentity("MonthlyTrigger", "ReportingGroup")
    .WithCronSchedule("0 15 10 15 * ?") // 매월 15 일 오전 10:15
    .Build();

using (var schedulerService = await factory.GetScheduler())
{
    await schedulerService.Start();
    await schedulerService.ScheduleJob(monthlyJob, cronTrigger);
    Console.WriteLine("스케줄러 서비스가 대기 모드 진입.");
}

태그: Quartz.NET C# Scheduled Task Cron Expression

5월 25일 10:51에 게시됨