๐ Quartz.NET์ผ๋ก ์์ ์ค์ผ์ค๋ง ๋ง์คํฐํ๊ธฐ ๐ฐ๏ธ

์๋ ํ์ธ์, ์ฝ๋ฉ ์น๊ตฌ๋ค! ์ค๋์ C# ๊ฐ๋ฐ์๋ค์ ํ์ ๋๊ตฌ์ธ Quartz.NET์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ์์ ์ค์ผ์ค๋ง์ด๋ผ๊ณ ํ๋ฉด ๋ญ๊ฐ ๋ณต์กํ๊ณ ์ด๋ ค์ธ ๊ฒ ๊ฐ์ง๋ง, ๊ฑฑ์ ๋ง์ธ์! ์ฐ๋ฆฌ๊ฐ ํจ๊ป ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์๋๊ฐ๋ฉด ๊ธ๋ฐฉ ๋ง์คํฐํ ์ ์์ ๊ฑฐ์์. ๐
์ฌ๋ฌ๋ถ, ํน์ ์ฌ๋ฅ๋ท์ด๋ผ๋ ์ฌ์ดํธ๋ฅผ ์์๋์? ์ด๊ณณ์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ๋ ํ๋ซํผ์ธ๋ฐ์, ์ด๋ฐ ์ฌ์ดํธ๋ฅผ ์ด์ํ๋ค ๋ณด๋ฉด ์ ๊ธฐ์ ์ผ๋ก ์คํํด์ผ ํ๋ ์์ ๋ค์ด ๋ง์ด ์์ด์. ์๋ฅผ ๋ค๋ฉด, ๋งค์ผ ๋ฐค 12์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐฑ์ ์ ํ๊ฑฐ๋, ๋งค์ฃผ ์์์ผ ์์นจ์ ์ฃผ๊ฐ ๋ฆฌํฌํธ๋ฅผ ์์ฑํ๋ ๋ฑ์ ์์ ์ด์ฃ . ์ด๋ฐ ์์ ๋ค์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ๋ฐ๋ก ์ฌ๊ธฐ์ Quartz.NET์ด ๋ฑ์ฅํฉ๋๋ค! ๐ฆธโโ๏ธ
Quartz.NET์ด๋? Quartz.NET์ .NET ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋ ๊ฐ๋ ฅํ ์์ ์ค์ผ์ค๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์. ๋ณต์กํ ์ค์ผ์ค์ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๊ณ , ๋ค์ํ ํธ๋ฆฌ๊ฑฐ ์ต์ ์ ์ ๊ณตํ์ฌ ์ ์ฐํ ์์ ์คํ์ด ๊ฐ๋ฅํด์.
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Quartz.NET์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ๊น์? ์ค๋น๋์ จ๋์? ๊ทธ๋ผ ์ถ๋ฐ~! ๐
๐ ๏ธ Quartz.NET ์ค์นํ๊ธฐ
Quartz.NET์ ์ฌ์ฉํ๊ธฐ ์ํ ์ฒซ ๋จ๊ณ๋ ๋ฐ๋ก ์ค์น์์. ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ Quartz.NET์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ๋งค์ฐ ๊ฐ๋จํด์. NuGet ํจํค์ง ๊ด๋ฆฌ์๋ฅผ ํตํด ์ฝ๊ฒ ์ค์นํ ์ ์๋ต๋๋ค.
Visual Studio๋ฅผ ์ฌ์ฉํ๊ณ ๊ณ์ ๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ฅผ ๋ฐ๋ผํด๋ณด์ธ์:
- ์๋ฃจ์ ํ์๊ธฐ์์ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ๋ฅผ ์ฐํด๋ฆญํฉ๋๋ค.
- 'NuGet ํจํค์ง ๊ด๋ฆฌ'๋ฅผ ์ ํํฉ๋๋ค.
- ๊ฒ์์ฐฝ์ 'Quartz'๋ฅผ ์ ๋ ฅํฉ๋๋ค.
- 'Quartz' ํจํค์ง๋ฅผ ์ฐพ์ ์ค์น ๋ฒํผ์ ํด๋ฆญํฉ๋๋ค.
๋๋ ํจํค์ง ๊ด๋ฆฌ์ ์ฝ์์ ์ฌ์ฉํ์๋ ๋ถ๋ค์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ์๋ฉด ๋ผ์:
Install-Package Quartz
์ ๋ง ์ฝ์ฃ ? ์ด๋ ๊ฒ ๊ฐ๋จํ ๊ณผ์ ๋ง์ผ๋ก Quartz.NET์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ค๋น๊ฐ ๋๋ฌ์ด์! ๐
Tip: Quartz.NET์ ๋ฒ์ ์ ๋ฐ๋ผ ์ฝ๊ฐ์ ์ฐจ์ด๊ฐ ์์ ์ ์์ด์. ์ด ๊ธ์์๋ ๊ฐ์ฅ ์ต์ ๋ฒ์ ์ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํ ๊ฑฐ์์. ํ์ง๋ง ๊ฑฑ์ ๋ง์ธ์! ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ๋๋ถ๋ถ ๋์ผํ๋ต๋๋ค.
์, ์ด์ Quartz.NET์ ์ค์นํ์ผ๋ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฌ์ฉ๋ฒ์ ์์๋ณผ๊น์? ๋ค์ ์น์ ์์๋ Quartz.NET์ ํต์ฌ ๊ฐ๋ ๋ค์ ํ๋์ฉ ์ดํด๋ณผ ๊ฑฐ์์. ์ฌ๋ฏธ์๊ณ ์ ์ตํ ์ฌ์ ์ด ๋ ๊ฑฐ์์, ํจ๊ป ๊ฐ๋ณด์ค๊น์? ๐
๐ง Quartz.NET์ ํต์ฌ ๊ฐ๋ ์ดํดํ๊ธฐ
Quartz.NET์ ์ ๋๋ก ํ์ฉํ๊ธฐ ์ํด์๋ ๋ช ๊ฐ์ง ํต์ฌ ๊ฐ๋ ์ ์ดํดํด์ผ ํด์. ๋ง์น ํผ์ฆ ์กฐ๊ฐ์ ๋ง์ถ๋ ๊ฒ์ฒ๋ผ, ์ด ๊ฐ๋ ๋ค์ ํ๋์ฉ ์ดํดํ๋ค ๋ณด๋ฉด ์ ์ฒด ๊ทธ๋ฆผ์ด ๋ณด์ด๊ฒ ๋ ๊ฑฐ์์. ์, ๊ทธ๋ผ ํ๋์ฉ ์ดํด๋ณผ๊น์?
1. Job (์์ ) ๐
Job์ ์ฐ๋ฆฌ๊ฐ ์คํํ๊ณ ์ ํ๋ ์์ ๊ทธ ์์ฒด๋ฅผ ๋งํด์. ์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐฑ์ ์ ํ๋ ์์ , ์ด๋ฉ์ผ์ ๋ณด๋ด๋ ์์ , ๋ก๊ทธ๋ฅผ ์ ๋ฆฌํ๋ ์์ ๋ฑ์ด ๋ชจ๋ Job์ด ๋ ์ ์์ด์. Job์ IJob ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ํด๋์ค๋ก ๋ง๋ค์ด์ง๋๋ค.
์์: ์ฌ๋ฅ๋ท์์ ๋งค์ผ ๋ฐค ์ฌ์ฉ์ ํต๊ณ๋ฅผ ์ง๊ณํ๋ ์์ ์ Job์ผ๋ก ๋ง๋ค ์ ์์ด์. ์ด Job์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ ๋ถ์ํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ๋ก์ง์ ํฌํจํ๊ฒ ๋ ๊ฑฐ์์.
2. Trigger (ํธ๋ฆฌ๊ฑฐ) โฐ
Trigger๋ Job์ ์ธ์ ์คํํ ์ง ๊ฒฐ์ ํ๋ ์์์์. ํน์ ์๊ฐ์ ํ ๋ฒ ์คํํ ์๋ ์๊ณ , ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ๋ณตํด์ ์คํํ ์๋ ์์ด์. Quartz.NET์ ๋ค์ํ ์ข ๋ฅ์ Trigger๋ฅผ ์ ๊ณตํ๋๋ฐ, ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฒ์ SimpleTrigger์ CronTrigger์์.
- SimpleTrigger: ํน์ ์๊ฐ์ ํ ๋ฒ ์คํํ๊ฑฐ๋, ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ๋ณต ์คํํ ๋ ์ฌ์ฉํด์.
- CronTrigger: ๋ ๋ณต์กํ ์ค์ผ์ค๋ง์ด ํ์ํ ๋ ์ฌ์ฉํด์. ์๋ฅผ ๋ค์ด, "๋งค์ฃผ ์์์ผ๋ถํฐ ๊ธ์์ผ๊น์ง ์ค์ 9์์ ์คํ"๊ณผ ๊ฐ์ ์ค์ผ์ค์ ์ค์ ํ ์ ์์ด์.
3. Scheduler (์ค์ผ์ค๋ฌ) ๐๏ธ
Scheduler๋ Job๊ณผ Trigger๋ฅผ ๊ด๋ฆฌํ๊ณ ์คํํ๋ ์ค์ฌ ์์ง์ด์์. Job๊ณผ Trigger๋ฅผ ์ฐ๊ฒฐํ๊ณ , ์ ํด์ง ์๊ฐ์ Job์ ์คํํ๋ ์ญํ ์ ํด์. Quartz.NET์์๋ IScheduler ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ค์ผ์ค๋ฌ๋ฅผ ์ ์ดํ ์ ์์ด์.
์ค์ ํฌ์ธํธ: Scheduler๋ Job๊ณผ Trigger์ ์ค์ฌ์ ์ญํ ์ ํด์. Job์ "๋ฌด์์ ํ ์ง"๋ฅผ ์ ์ํ๊ณ , Trigger๋ "์ธ์ ํ ์ง"๋ฅผ ์ ์ํ๋ฉฐ, Scheduler๋ ์ด ๋์ ์ฐ๊ฒฐํด์ ์ค์ ๋ก ์์ ์ด ์คํ๋๋๋ก ๊ด๋ฆฌํด์.
4. JobDetail ๐
JobDetail์ Job์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ๋ ์ฌ์ฉ๋๋ ์ค์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ด์. Job์ ์ด๋ฆ, ๊ทธ๋ฃน, ๋ฐ์ดํฐ ๋งต ๋ฑ์ ํฌํจํ ์ ์์ฃ . JobDetail์ ํตํด ๊ฐ์ Job ํด๋์ค๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ์๋ก ๋ค๋ฅธ ์ค์ ์ผ๋ก ์ฌ๋ฌ ๊ฐ์ Job ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์์ด์.
5. JobStore ๐๏ธ
JobStore๋ ์ค์ผ์ค๋ง ์ ๋ณด(Job๊ณผ Trigger)๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ ์ ์ํด์. ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ RAMJobStore์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๋ ADOJobStore๊ฐ ์ฃผ๋ก ์ฌ์ฉ๋ผ์.
- RAMJobStore: ๋น ๋ฅด์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋๋ฉด ๋ชจ๋ ์ ๋ณด๊ฐ ์ฌ๋ผ์ ธ์.
- ADOJobStore: ์๊ตฌ์ ์ผ๋ก ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์์ง๋ง, ์๋์ ์ผ๋ก ์๋๊ฐ ๋๋ ค์.
์ด๋ ๊ฒ Quartz.NET์ ํต์ฌ ๊ฐ๋ ๋ค์ ์ดํด๋ดค์ด์. ์ด ๊ฐ๋ ๋ค์ด ์ด๋ป๊ฒ ์ํธ์์ฉํ๋์ง ์ดํดํ๋ ๊ฒ์ด ์ค์ํด์. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ๋ค์ด ์๋ก ์ด์ฐ๋ฌ์ ธ ๋ฉ์ง ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ด๋ ๊ฒ์ฒ๋ผ, ์ด ๊ฐ๋ ๋ค๋ ์๋ก ์กฐํ๋กญ๊ฒ ์๋ํ๋ฉฐ ๊ฐ๋ ฅํ ์ค์ผ์ค๋ง ์์คํ ์ ๋ง๋ค์ด๋ด๋ ๊ฑฐ์ฃ . ๐
๋ค์ ์น์ ์์๋ ์ด ๊ฐ๋ ๋ค์ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฝ๋๋ก ๊ตฌํํ๋์ง ์์ธํ ์์๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๊ทธ๋ผ ๊ณ์ํด์ Quartz.NET์ ์ธ๊ณ๋ก ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ๊น์? ๐
๐ป Quartz.NET ์ค์ : ์ฝ๋๋ก ๊ตฌํํ๊ธฐ
์, ์ด์ Quartz.NET์ ํต์ฌ ๊ฐ๋ ๋ค์ ์ค์ ์ฝ๋๋ก ๊ตฌํํด๋ณผ ์๊ฐ์ด์์! ๋ง์น ๋ ๊ณ ๋ธ๋ก์ ์กฐ๋ฆฝํ๋ฏ์ด, ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๊ฐ๋ ๋ค์ ํ๋์ฉ ์กฐํฉํด์ ๋ฉ์ง ์ค์ผ์ค๋ง ์์คํ ์ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? ๊ทธ๋ผ ์์ํด๋ณผ๊น์? ๐๏ธ
1. Job ๋ง๋ค๊ธฐ
๋จผ์ , ์คํํ ์์ ์ ์ ์ํ๋ Job ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์. IJob ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ํด๋์ค๋ฅผ ๋ง๋ค๋ฉด ๋ผ์.
using Quartz;
using System;
using System.Threading.Tasks;
public class MyJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Console.Out.WriteLineAsync("์๋
ํ์ธ์! MyJob์ด ์คํ๋์์ด์!");
}
}
์ด Job์ ์คํ๋ ๋๋ง๋ค ์ฝ์์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํด์. ์ค์ ํ๋ก์ ํธ์์๋ ์ด ๋ถ๋ถ์ ์ฌ๋ฌ๋ถ์ด ์ํ๋ ์์ ์ ๋ฃ์ผ๋ฉด ๋ผ์. ์๋ฅผ ๋ค์ด, ์ฌ๋ฅ๋ท์ ์ผ์ผ ์ฌ์ฉ์ ํต๊ณ๋ฅผ ๊ณ์ฐํ๋ ๋ก์ง์ ์ฌ๊ธฐ์ ๋ฃ์ ์ ์๊ฒ ์ฃ ?
2. Scheduler ์์ฑํ๊ธฐ
๋ค์์ผ๋ก, ์ค์ผ์ค๋ฌ๋ฅผ ์์ฑํด๋ณผ๊ฒ์. ์ค์ผ์ค๋ฌ๋ Job๊ณผ Trigger๋ฅผ ๊ด๋ฆฌํ๊ณ ์คํํ๋ ์ค์ฌ ์์ง์ด์์.
using Quartz;
using Quartz.Impl;
// ์ค์ผ์ค๋ฌ ํฉํ ๋ฆฌ ์์ฑ
StdSchedulerFactory factory = new StdSchedulerFactory();
// ์ค์ผ์ค๋ฌ ์ธ์คํด์ค ๊ฐ์ ธ์ค๊ธฐ
IScheduler scheduler = await factory.GetScheduler();
// ์ค์ผ์ค๋ฌ ์์
await scheduler.Start();
์ด๋ ๊ฒ ํ๋ฉด ์ค์ผ์ค๋ฌ๊ฐ ์ค๋น ์๋ฃ๋์ด Job์ ์คํํ ์ค๋น๊ฐ ๋ ๊ฑฐ์์! ๐
3. JobDetail ๋ง๋ค๊ธฐ
์ด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ Job์ ์คํํ๊ธฐ ์ํ JobDetail์ ๋ง๋ค์ด๋ณผ๊ฒ์.
IJobDetail job = JobBuilder.Create<MyJob>()
.WithIdentity("myJob", "group1")
.Build();
์ฌ๊ธฐ์ "myJob"์ Job์ ์ด๋ฆ์ด๊ณ , "group1"์ Job์ด ์ํ ๊ทธ๋ฃน์ด์์. ์ด๋ ๊ฒ ์ด๋ฆ๊ณผ ๊ทธ๋ฃน์ ์ง์ ํ๋ฉด ๋์ค์ ํน์ Job์ ์ฝ๊ฒ ์ฐพ์ ์ ์์ด์.
4. Trigger ๋ง๋ค๊ธฐ
Job์ ์ธ์ ์คํํ ์ง ๊ฒฐ์ ํ๋ Trigger๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? ์ฌ๊ธฐ์๋ SimpleTrigger๋ฅผ ์ฌ์ฉํด์ 10์ด๋ง๋ค Job์ ์คํํ๋๋ก ์ค์ ํด๋ณผ๊ฒ์.
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.RepeatForever())
.Build();
์ด Trigger๋ ์ง๊ธ ๋ฐ๋ก ์์ํด์(StartNow) 10์ด ๊ฐ๊ฒฉ์ผ๋ก(WithIntervalInSeconds(10)) ๋ฌดํ ๋ฐ๋ณต(RepeatForever)ํ๋๋ก ์ค์ ๋์์ด์.
5. Job๊ณผ Trigger ์ค์ผ์ค๋งํ๊ธฐ
๋ง์ง๋ง์ผ๋ก, ๋ง๋ Job๊ณผ Trigger๋ฅผ ์ค์ผ์ค๋ฌ์ ๋ฑ๋กํด๋ณผ๊ฒ์.
await scheduler.ScheduleJob(job, trigger);
์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ์ค๋น๊ฐ ๋๋ฌ์ด์! ์ด์ ์ค์ผ์ค๋ฌ๊ฐ 10์ด๋ง๋ค MyJob์ ์คํํ ๊ฑฐ์์. ๐
์ ์ฒด ์ฝ๋: ์ง๊ธ๊น์ง ์์ฑํ ์ฝ๋๋ฅผ ๋ชจ๋ ํฉ์น๋ฉด ๋ค์๊ณผ ๊ฐ์์.
using Quartz;
using Quartz.Impl;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
StdSchedulerFactory factory = new StdSchedulerFactory();
IScheduler scheduler = await factory.GetScheduler();
await scheduler.Start();
IJobDetail job = JobBuilder.Create<MyJob>()
.WithIdentity("myJob", "group1")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("myTrigger", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(10)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
// ํ๋ก๊ทธ๋จ์ด ๋ฐ๋ก ์ข
๋ฃ๋์ง ์๋๋ก ๋๊ธฐ
await Task.Delay(-1);
}
}
public class MyJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Console.Out.WriteLineAsync("์๋
ํ์ธ์! MyJob์ด ์คํ๋์์ด์!");
}
}
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด, 10์ด๋ง๋ค ์ฝ์์ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ ๊ฑธ ๋ณผ ์ ์์ ๊ฑฐ์์. ์ ๋ง ์ ๊ธฐํ์ง ์๋์? ๐
์ด๋ ๊ฒ Quartz.NET์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ์์๋ดค์ด์. ๋ฌผ๋ก ์ด๊ฑด ์์ฃผ ๊ฐ๋จํ ์์ ์ผ ๋ฟ์ด์์. Quartz.NET์ ์ด๋ณด๋ค ํจ์ฌ ๋ ๋ณต์กํ๊ณ ๋ค์ํ ์ค์ผ์ค๋ง ์๋๋ฆฌ์ค๋ฅผ ์ง์ํด์. ์๋ฅผ ๋ค์ด, ์ฌ๋ฅ๋ท๊ฐ์ ์ฌ์ดํธ์์๋ ๋งค์ผ ๋ฐค 12์์ ๋ฐ์ดํฐ ๋ฐฑ์ ์ ํ๊ณ , ๋งค์ฃผ ์์์ผ ์์นจ์ ์ฃผ๊ฐ ๋ฆฌํฌํธ๋ฅผ ์์ฑํ๊ณ , ๋งค๋ฌ 1์ผ์ ์๊ฐ ํต๊ณ๋ฅผ ๊ณ์ฐํ๋ ๋ฑ ๋ค์ํ ์ฃผ๊ธฐ์ ์์ ๋ค์ ์ฝ๊ฒ ์ค์ผ์ค๋งํ ์ ์๋ต๋๋ค.
๋ค์ ์น์ ์์๋ ์ข ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ณด๋ฉด์, Quartz.NET์ ๋์ฑ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๊ณ์ํด์ Quartz.NET์ ๋งค๋ ฅ์ ์ธ ์ธ๊ณ๋ฅผ ํํํด๋ณผ๊น์? ๐
๐ฅ Quartz.NET ๊ณ ๊ธ ๊ธฐ๋ฅ ํํํ๊ธฐ
์, ์ด์ Quartz.NET์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ จ์ผ๋ ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ ์๊ฐ์ด์์! ์ฌ๋ฌ๋ถ์ ์ค์ผ์ค๋ง ๋ฅ๋ ฅ์ ํ ๋จ๊ณ ๋ ์ ๊ทธ๋ ์ด๋ํ ์ค๋น๊ฐ ๋์ จ๋์? ๊ทธ๋ผ ํจ๊ป Quartz.NET์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ณผ๊น์? ๐ต๏ธโโ๏ธ
1. CronTrigger ์ฌ์ฉํ๊ธฐ
์์ ์ฐ๋ฆฌ๋ SimpleTrigger๋ฅผ ์ฌ์ฉํด๋ดค์ด์. ํ์ง๋ง ์ค์ ํ๋ก์ ํธ์์๋ ๋ ๋ณต์กํ ์ค์ผ์ค๋ง์ด ํ์ํ ๋๊ฐ ๋ง์ฃ . ์ด๋ด ๋ CronTrigger๊ฐ ํฐ ๋์์ด ๋ฉ๋๋ค.
ITrigger cronTrigger = TriggerBuilder.Create()
.WithIdentity("cronTrigger", "group1")
.WithCronSchedule("0 0/5 * * * ?") // 5๋ถ๋ง๋ค ์คํ
.Build();
์ด CronTrigger๋ 5๋ถ๋ง๋ค Job์ ์คํํด์. Cron ํํ์ "0 0/5 * * * ?"๋ ๋ค์๊ณผ ๊ฐ์ด ํด์๋ฉ๋๋ค:
- 0: ๋ถ์ 0์ด์
- 0/5: 0๋ถ๋ถํฐ ์์ํด์ 5๋ถ ๊ฐ๊ฒฉ์ผ๋ก
- *: ๋ชจ๋ ์๊ฐ
- *: ๋ชจ๋ ์ผ
- *: ๋ชจ๋ ์
- ?: ์์ผ์ ์๊ด์์
Tip: Cron ํํ์์ ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ์ต์ํด์ง๋ฉด ์์ฃผ ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, "0 0 12 ? * MON-FRI"๋ "ํ์ผ ์ ์ค์ ์คํ"์ ์๋ฏธํด์. ์ฌ๋ฅ๋ท์์ ์ฃผ์ค ์ ์ฌ์๊ฐ์ ํน๋ณ ์ด๋ฒคํธ ์๋ฆผ์ ๋ณด๋ด๊ณ ์ถ๋ค๋ฉด ์ด๋ฐ ์์ผ๋ก ์ค์ ํ ์ ์๊ฒ ์ฃ ?
2. Job์ ๋ฐ์ดํฐ ์ ๋ฌํ๊ธฐ
๋๋ก๋ Job์ ์คํํ ๋ ํน์ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ์ ๋ฌํด์ผ ํ ๊ฒฝ์ฐ๊ฐ ์์ด์. Quartz.NET์์๋ JobDataMap์ ์ฌ์ฉํด ์ด๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
JobDataMap jobData = new JobDataMap();
jobData.Put("username", "Alice");
jobData.Put("runCount", 0);
IJobDetail job = JobBuilder.Create<MyJob>()
.WithIdentity("myJob", "group1")
.UsingJobData(jobData)
.Build();
๊ทธ๋ฆฌ๊ณ Job ํด๋์ค์์ ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์์ด์:
public class MyJob : IJob
{
public string Username { get; set; }
public int RunCount { get; set; }
public async Task Execute(IJobExecutionContext context)
{
RunCount++;
await Console.Out.WriteLineAsync($"์๋
ํ์ธ์, {Username}! ์ด Job์ {RunCount}๋ฒ์งธ ์คํ ์ค์
๋๋ค.");
}
}
์ด๋ ๊ฒ ํ๋ฉด Job์ด ์คํ๋ ๋๋ง๋ค ์ฌ์ฉ์ ์ด๋ฆ๊ณผ ์คํ ํ์๋ฅผ ์ถ๋ ฅํ ์ ์์ด์. ์ ๋ง ํธ๋ฆฌํ์ฃ ? ๐
3. ๋ฆฌ์ค๋ ์ฌ์ฉํ๊ธฐ
Quartz.NET์ ๋ค์ํ ๋ฆฌ์ค๋๋ฅผ ์ ๊ณตํด์. ์ด๋ฅผ ํตํด Job์ด๋ Trigger์ ์๋ช ์ฃผ๊ธฐ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๊ณ ๋์ํ ์ ์์ฃ . ์๋ฅผ ๋ค์ด, IJobListener๋ฅผ ๊ตฌํํด์ Job ์คํ ์ ํ์ ํน์ ์์ ์ ์ํํ ์ ์์ด์.
public class MyJobListener : IJobListener
{
public string Name => "MyJobListener";
public async Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default)
{
await Console.Out.WriteLineAsync($"Job {context.JobDetail.Key} ์คํ ์์!");
}
public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default)
{
await Console.Out.WriteLineAsync($"Job {context.JobDetail.Key} ์คํ ์๋ฃ!");
}
public async Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default)
{
await Console.Out.WriteLineAsync($"Job {context.JobDetail.Key} ์คํ์ด ๊ฑฐ๋ถ๋์์ต๋๋ค.");
}
}
์ด ๋ฆฌ์ค๋๋ฅผ ์ค์ผ์ค๋ฌ์ ๋ฑ๋กํ๋ฉด, ๋ชจ๋ Job์ ์คํ ์ ํ์ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋ ๊ฑฐ์์:
scheduler.ListenerManager.AddJobListener(new MyJobListener());
4. ์ค๋ฅ ์ฒ๋ฆฌ์ ์ฌ์๋
์ค์ ํ๊ฒฝ์์๋ Job ์คํ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ด์. Quartz.NET์ ์ด๋ฐ ์ํฉ์ ๋๋นํ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค.
public class MyJob : IJob
{
public async Task Execute(IJobExecutionContext context)
{
try
{
// ์์
์ํ
await PerformTask();
}
catch (Exception ex)
{
JobExecutionException e = new JobExecutionException(ex);
e.RefireImmediately = true; // ์ฆ์ ์ฌ์๋
throw e;
}
}
private async Task PerformTask()
{
// ์ค์ ์์
์ํ
}
}
์ด ์์ ์์๋ ์์ ์ํ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด JobExecutionException์ ๋์ง๊ณ ์ฆ์ ์ฌ์๋ํ๋๋ก ์ค์ ํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด ์ผ์์ ์ธ ์ค๋ฅ๋ก ์ธํด ์ค์ํ ์์ ์ด ๋๋ฝ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ฃ .
5. ํด๋ฌ์คํฐ๋ง
๋๊ท๋ชจ ์์คํ ์์๋ ์ฌ๋ฌ ์๋ฒ์ ๊ฑธ์ณ Quartz.NET์ ์คํํด์ผ ํ ์๋ ์์ด์. Quartz.NET์ ํด๋ฌ์คํฐ๋ง์ ์ง์ํด์ ์ด๋ฐ ์ํฉ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ค ๋๋ค.
var props = new NameValueCollection
{
{ "quartz.scheduler.instanceName", "MyClusteredScheduler" },
{ "quartz.jobStore.type", "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" },
{ "quartz.jobStore.dataSource", "default" },
{ "quartz.jobStore.tablePrefix", "QRTZ_" },
{ "quartz.jobStore.clustered", "true" },
{ "quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz" },
{ "quartz.dataSource.default.connectionString", "your_connection_string_here" },
{ "quartz.dataSource.default.provider", "SqlServer" }
};
ISchedulerFactory sf = new StdSchedulerFactory(props);
IScheduler scheduler = await sf.GetScheduler();
์ด๋ ๊ฒ ์ค์ ํ๋ฉด ์ฌ๋ฌ ์๋ฒ์์ Quartz.NET์ ์คํํด๋ ์์ ์ด ์ค๋ณต ์คํ๋์ง ์๊ณ , ํ ์๋ฒ๊ฐ ๋ค์ด๋์ด๋ ๋ค๋ฅธ ์๋ฒ๊ฐ ์์ ์ ์ด์ด๋ฐ์ ์คํํ ์ ์์ด์. ๋๊ท๋ชจ ์์คํ ์ ์์ ์ฑ์ ๋์ด๋ ๋ฐ ํฐ ๋์์ด ๋์ฃ .
์ค์ ์ฌ์ฉ ์: ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ๋๊ท๋ชจ ํ๋ซํผ์์๋ ์ด๋ฐ ํด๋ฌ์คํฐ๋ง ๊ธฐ๋ฅ์ด ๋งค์ฐ ์ ์ฉํ ์ ์์ด์. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ํต๊ณ ์ง๊ณ, ์ผ๊ด ๊ฒฐ์ ์ฒ๋ฆฌ, ๋๋ ์ด๋ฉ์ผ ๋ฐ์ก ๋ฑ์ ์์ ์ ์ฌ๋ฌ ์๋ฒ์ ๋ถ์ฐํด์ ์ฒ๋ฆฌํ ์ ์๊ฒ ์ฃ . ์ด๋ ๊ฒ ํ๋ฉด ์์คํ ์ ๋ถํ๋ฅผ ๋ถ์ฐ์ํค๊ณ ์์ ์ฑ์ ๋์ผ ์ ์๋ต๋๋ค.
6. ๋์ ์ค์ผ์ค๋ง
๋๋ก๋ ๋ฐํ์์ ๋์ ์ผ๋ก Job์ ์ถ๊ฐํ๊ฑฐ๋ ์์ ํด์ผ ํ ๋๊ฐ ์์ด์. Quartz.NET์ ์ด๋ฐ ๋์ ์ค์ผ์ค๋ง๋ ์ง์ํฉ๋๋ค.
public async Task AddDynamicJob(string jobName, string cronExpression)
{
IJobDetail job = JobBuilder.Create<MyDynamicJob>()
.WithIdentity(jobName, "dynamicGroup")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity($"{jobName}Trigger", "dynamicGroup")
.WithCronSchedule(cronExpression)
.Build();
await scheduler.ScheduleJob(job, trigger);
}
์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ ์คํ ์ค์ ์๋ก์ด Job์ ๋์ ์ผ๋ก ์ถ๊ฐํ ์ ์์ด์. ์๋ฅผ ๋ค์ด, ๊ด๋ฆฌ์ ํ์ด์ง์์ ์๋ก์ด ์ ๊ธฐ ์์ ์ ์ถ๊ฐํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ฃ .
7. ์ค์ผ์ค ์ผ์ ์ค์ง์ ์ฌ๊ฐ
Quartz.NET์ ์ฌ์ฉํ๋ฉด ์ ์ฒด ์ค์ผ์ค๋ฌ๋ ํน์ Job์ ์ผ์ ์ค์งํ๊ณ ์ฌ๊ฐํ ์ ์์ด์.
// ์ ์ฒด ์ค์ผ์ค๋ฌ ์ผ์ ์ค์ง
await scheduler.PauseAll();
// ํน์ Job ์ผ์ ์ค์ง
await scheduler.PauseJob(new JobKey("myJob", "group1"));
// ์ ์ฒด ์ค์ผ์ค๋ฌ ์ฌ๊ฐ
await scheduler.ResumeAll();
// ํน์ Job ์ฌ๊ฐ
await scheduler.ResumeJob(new JobKey("myJob", "group1"));
์ด ๊ธฐ๋ฅ์ ์์คํ ์ ์ง๋ณด์๋ ๊ธด๊ธ ์ํฉ ์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ด์. ์ฌ๋ฅ๋ท์์ ์๋ฒ ์ ๊ฒ์ด ํ์ํ ๋, ๋ชจ๋ ์๋ํ ์์ ์ ์ผ์ ์ค์งํ๋ค๊ฐ ์ ๊ฒ ์๋ฃ ํ ์ฌ๊ฐํ๋ ์์ผ๋ก ํ์ฉํ ์ ์๊ฒ ์ฃ ?
๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง Quartz.NET์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ดค์ด์. ์ด ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด ์์ฃผ ๋ณต์กํ๊ณ ๊ฐ๋ ฅํ ์ค์ผ์ค๋ง ์์คํ ์ ๊ตฌ์ถํ ์ ์๋ต๋๋ค. Quartz.NET์ ์ ๋ง ๋ค์ฌ๋ค๋ฅํ ๋๊ตฌ์์. ๋จ์ํ ๋ฐ๋ณต ์์ ๋ถํฐ ๋ณต์กํ ์ํฐํ๋ผ์ด์ฆ๊ธ ์ค์ผ์ค๋ง๊น์ง, ๋ค์ํ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑ์ํฌ ์ ์์ฃ .
์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์ Quartz.NET์ ๋์ ํ๋ค๋ฉด, ์๊ฐ ๊ธฐ๋ฐ์ ์์ ์ฒ๋ฆฌ๊ฐ ํ๊ฒฐ ์์ํด์ง ๊ฑฐ์์. ์ฌ๋ฅ๋ท์ฒ๋ผ ๋ค์ํ ์ฃผ๊ธฐ์ ์์ ์ด ํ์ํ ํ๋ซํผ์์๋ ํนํ ์ ์ฉํ ๊ฑฐ์์. ์ฌ์ฉ์ ํต๊ณ ์ง๊ณ, ์ฃผ๊ฐ ๋ด์ค๋ ํฐ ๋ฐ์ก, ์๊ฐ ์ ์ฐ ์ฒ๋ฆฌ ๋ฑ ๋ค์ํ ์์ ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ ํ ๋๊น์.
Quartz.NET์ ์ธ๊ณ๋ ์ ๋ง ๋๊ณ ๊น์ด์. ์ด ๊ธ์์ ๋ค๋ฃฌ ๋ด์ฉ์ ๋น์ฐ์ ์ผ๊ฐ์ ๋ถ๊ณผํฉ๋๋ค. ๋ ๋ง์ ๊ธฐ๋ฅ๊ณผ ํ์ฉ๋ฒ์ ์๊ณ ์ถ๋ค๋ฉด ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด๋ณด๋ ๊ฒ๋ ์ข๊ฒ ์ด์. ์ฌ๋ฌ๋ถ๋ง์ ์ฐฝ์์ ์ธ ๋ฐฉ์์ผ๋ก Quartz.NET์ ํ์ฉํด๋ณด์ธ์. ๋ถ๋ช ๋ฉ์ง ๊ฒฐ๊ณผ๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ ๊ฑฐ์์! ๐
์, ์ด์ ์ฌ๋ฌ๋ถ์ Quartz.NET์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค๊น์ง ๋ง์คํฐํ์ จ์ด์. ์ด ๊ฐ๋ ฅํ ๋๊ตฌ๋ก ๋ฌด์์ ๋ง๋ค์ด๋ณผ๊น์? ์ฌ๋ฌ๋ถ์ ์์๋ ฅ์ด ํ๊ณ์์. ์ฝ๋ฉ ์ฆ๊ฒ๊ฒ ํ์ธ์! ๐๐จโ๐ป๐ฉโ๐ป
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ