๐Ÿš€ Quartz.NET์œผ๋กœ ์ž‘์—… ์Šค์ผ€์ค„๋ง ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿ•ฐ๏ธ

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ Quartz.NET์œผ๋กœ ์ž‘์—… ์Šค์ผ€์ค„๋ง ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿ•ฐ๏ธ

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”๋”ฉ ์นœ๊ตฌ๋“ค! ์˜ค๋Š˜์€ C# ๊ฐœ๋ฐœ์ž๋“ค์˜ ํ•„์ˆ˜ ๋„๊ตฌ์ธ Quartz.NET์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ž‘์—… ์Šค์ผ€์ค„๋ง์ด๋ผ๊ณ  ํ•˜๋ฉด ๋ญ”๊ฐ€ ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ๊ฑฑ์ • ๋งˆ์„ธ์š”! ์šฐ๋ฆฌ๊ฐ€ ํ•จ๊ป˜ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์›Œ๋‚˜๊ฐ€๋ฉด ๊ธˆ๋ฐฉ ๋งˆ์Šคํ„ฐํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๐Ÿ˜‰

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท์ด๋ผ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ์•„์‹œ๋‚˜์š”? ์ด๊ณณ์€ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฑฐ๋ž˜ํ•˜๋Š” ํ”Œ๋žซํผ์ธ๋ฐ์š”, ์ด๋Ÿฐ ์‚ฌ์ดํŠธ๋ฅผ ์šด์˜ํ•˜๋‹ค ๋ณด๋ฉด ์ •๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…๋“ค์ด ๋งŽ์ด ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ๋งค์ผ ๋ฐค 12์‹œ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฑ์—…์„ ํ•˜๊ฑฐ๋‚˜, ๋งค์ฃผ ์›”์š”์ผ ์•„์นจ์— ์ฃผ๊ฐ„ ๋ฆฌํฌํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ด์ฃ . ์ด๋Ÿฐ ์ž‘์—…๋“ค์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ๋ฐ”๋กœ ์—ฌ๊ธฐ์„œ Quartz.NET์ด ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค! ๐Ÿฆธโ€โ™‚๏ธ

Quartz.NET์ด๋ž€? Quartz.NET์€ .NET ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ์ž‘์—… ์Šค์ผ€์ค„๋ง ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ˆ์š”. ๋ณต์žกํ•œ ์Šค์ผ€์ค„์„ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ณ , ๋‹ค์–‘ํ•œ ํŠธ๋ฆฌ๊ฑฐ ์˜ต์…˜์„ ์ œ๊ณตํ•˜์—ฌ ์œ ์—ฐํ•œ ์ž‘์—… ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ด์š”.

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Quartz.NET์˜ ์„ธ๊ณ„๋กœ ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ์ถœ๋ฐœ~! ๐Ÿš‚

๐Ÿ› ๏ธ Quartz.NET ์„ค์น˜ํ•˜๊ธฐ

Quartz.NET์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ฒซ ๋‹จ๊ณ„๋Š” ๋ฐ”๋กœ ์„ค์น˜์˜ˆ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์— Quartz.NET์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ด์š”. NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

Visual Studio๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์‹ ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ผํ•ด๋ณด์„ธ์š”:

  1. ์†”๋ฃจ์…˜ ํƒ์ƒ‰๊ธฐ์—์„œ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์šฐํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  2. 'NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ'๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ฒ€์ƒ‰์ฐฝ์— 'Quartz'๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  4. '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์˜ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋“ค๊นŒ์ง€ ๋งˆ์Šคํ„ฐํ•˜์…จ์–ด์š”. ์ด ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋กœ ๋ฌด์—‡์„ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ์ƒ๋ ฅ์ด ํ•œ๊ณ„์˜ˆ์š”. ์ฝ”๋”ฉ ์ฆ๊ฒ๊ฒŒ ํ•˜์„ธ์š”! ๐Ÿš€๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป