๋ฐ˜์‘ํ˜•

๊ฐœ๋ฐœ ๋ฐฐ๊ฒฝ

์ €๋Š” ํšŒ์‚ฌ์—์„œ ์—…๋ฌด ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์‹œ๋†€๋กœ์ง€ ๋„์ปค์—์„œ ๋ ˆ๋“œ๋งˆ์ธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ ˆ๋“œ๋งˆ์ธ์˜ ๋ฉ”์ผ ์„ค์ •์„ ํ†ตํ•ด ์ผ๊ฐ ์ƒ์„ฑ, ํŽธ์ง‘ ์‹œ ๋ฉ”์ผ๋กœ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”์ผ์˜ ๊ฒฝ์šฐ ์•„์›ƒ๋ฃฉ์œผ๋กœ ํ™•์ธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ง€๊ธˆ๊นŒ์ง€ ๋ ˆ๋“œ๋งˆ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋„ˆ๋ฌด๋‚˜ ์•„์‰ฌ์šด ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์•Œ๋ฆผ์„ ์ฆ‰์‹œ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด์ฃ 

๋ ˆ๋“œ๋งˆ์ธ ์•Œ๋ฆผ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์•„์›ƒ๋ฃฉ์—์„œ ์ง์ ‘ ๋ณด๋‚ด๊ธฐ/๋ฐ›๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ์งง๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ PC์—์„œ๋Š” ์ด๋ ‡๊ฒŒ ํ™•์ธํ•˜๋ฉด ๋˜์ง€๋งŒ ์Šค๋งˆํŠธํฐ์—์„œ๋Š” ์•Œ๋ฆผ ๋ฐ›๊ธฐ๊ฐ€ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•Œ๋ฆผ์„ ์ผœ์ž๋‹ˆ ์ˆ˜์‹ ๋˜๋Š” ๋ชจ๋“  ๋ฉ”์ผ์— ๋Œ€ํ•ด ์•Œ๋ฆผ์ด ์˜ค๋‹ˆ ์˜ ๋ถˆํŽธํ–ˆ์Šต๋‹ˆ๋‹ค

๊ทธ๋ž˜์„œ ์ƒ๊ฐํ•œ ๊ฒƒ์ด, '๋ ˆ๋“œ๋งˆ์ธ ์ผ๊ฐ์ด ์ƒ์„ฑ๋˜๋ฉด ๋ฉ”์‹ ์ €๋กœ ์•Œ๋ฆผ์„ ์ค„ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ'์ž…๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ €๋Š” ์‚ฌ๋‚ด ๋ฉ”์‹ ์ €๋กœ ์‹œ๋†€๋กœ์ง€ ์ฑ—(Chat)์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ฑ—์œผ๋กœ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ธธ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค

๊ทธ๋Ÿฐ๋ฐ ์—ญ์‹œ๋‚˜ ์•ˆ ๋˜๋Š” ๊ฑด ์—†๋”๊ตฐ์š”. ๋ ˆ๋“œ๋งˆ์ธ์€ REST API๋ฅผ, ์ฑ—์€ Incoming Webhook์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ ˆ๋“œ๋งˆ์ธ REST API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‹ ๊ทœ ์ผ๊ฐ์„ ์กฐํšŒํ•˜๊ณ , ์ผ๊ฐ์ด ์žˆ๋‹ค๋ฉด ์ฑ—์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋ฉด ๋˜๋Š” ๊ฒƒ์ด์ฃ !

๊ตฌ์ƒ๋„

ASP.NET Core Worker Service

๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. '์–ด๋””'์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ๋Œ๋ฆฌ๋Š๋ƒ์ž…๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ํŠน์ • ์ปดํ“จํ„ฐ์— ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ด ๋ฌดํ•œ ๋ฃจํ”„๋กœ ๊ณ„์† ๋Œ๋ฆด์ง€, ์•„๋‹ˆ๋ฉด ์œˆ๋„์šฐ ์„œ๋น„์Šค๋กœ ๊ฐœ๋ฐœํ•˜์—ฌ ์ปดํ“จํ„ฐ๊ฐ€ ์ผœ์ง€๋ฉด ๊ณ„์† ๋Œ์•„๊ฐ€๊ฒŒ ํ• ์ง€ ๊ณ ๋ฏผ์„ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์ €๋Š” ์‹œ๋†€๋กœ์ง€ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์„œ๋ฒ„์— ๊ฐœ๋ฐœํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๋Œ๋ฆฌ๋ฉด ๋˜์ง€ ์•Š์„๊นŒ ์‹ถ์—ˆ์ฃ . ๊ทธ๋ž˜์„œ ์•Œ๊ฒŒ ๋œ ๊ฒƒ์ด ASP.NET Core์˜€์Šต๋‹ˆ๋‹ค.

ASP.NET Core๋Š” Windows, macOS ๋ฐ Linux์—์„œ ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ์•ฑ์„ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  C#์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๋ฉด ์ œ๊ฐ€ ์›ํ•˜๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฌผ์„ ASP.NET Core๋ฅผ ํ†ตํ•ด ์„œ๋น„์Šค๋ฅผ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ Visual Studio์—์„œ ์ œ์ž‘ ๊ฐ€๋Šฅํ•œ ASP.NET Core Worker Service(์ž‘์—…์ž ์„œ๋น„์Šค) ํ…œํ”Œ๋ฆฟ์€ ์žฅ๊ธฐ๊ฐ„ ์‹คํ–‰๋˜๋Š” ์„œ๋น„์Šค ์•ฑ์„ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ด๋ฒˆ ๊ตฌ์ƒ๊ณผ ๊ฐ™์ด ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ๊ณ„์†ํ•ด์„œ ๋Œ๋ฆด ์„œ๋น„์Šค๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๋ผ๋Š” ๊ฒƒ์ด์ฃ .

๊ฐœ๋ฐœ ์ˆœ์„œ

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ฐœ๋ฐœ์— ๋Œ์ž…ํ•˜๊ธฐ์— ์•ž์„œ, '์–ด๋–ป๊ฒŒ' ๊ฐœ๋ฐœํ•ด ๋‚˜๊ฐˆ ๊ฒƒ์ธ์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ค‘๊ฐ„ ์ค‘๊ฐ„ ๋‚ด์šฉ์ด ๊ฝค ๋งŽ์•„์„œ ํ•˜์œ„ ํฌ์ŠคํŒ…์„ ์ฒจ๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

1. ํ…Œ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ

์šฐ์„  ๋ ˆ๋“œ๋งˆ์ธ REST API์™€ ์‹œ๋†€๋กœ์ง€ ์ฑ— Incoming Webhook์„ ์—ฐ๋™ํ•  ์ค„ ์•Œ์•„์•ผ๊ฒ ์ฃ ? ๋ ˆ๋“œ๋งˆ์ธ REST API์™€ Incoming Webhook์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. 

[.Net] C# ๋ ˆ๋“œ๋งˆ์ธ REST API ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•(์˜ˆ์ œ ํฌํ•จ)

[์ฑ—๋ด‡/.NET] C#์—์„œ ์‹œ๋†€๋กœ์ง€ Chat์— ์ฑ—๋ด‡ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ(์˜ˆ์ œ ํฌํ•จ)

2. Windows Docker with Worker Service

๋„์ปค๋Š” Windows์™€ Linux ์šด์˜์ฒด์ œ ๋ชจ๋‘ ์ง€์›ํ•˜๋Š”๋ฐ์š”. ์ตœ์ข… ๋ชฉํ‘œ๋Š” ๋ฆฌ๋ˆ…์Šค ๊ธฐ๋ฐ˜์˜ ์‹œ๋†€๋กœ์ง€ ๋„์ปค์ด์ง€๋งŒ, ์ค‘๊ฐ„ ๊ฒ€์ฆ์„ ์œ„ํ•ด ์œˆ๋„์šฐ์šฉ ๋„์ปค์—์„œ ๋จผ์ € ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋„์ปค์—์„œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Visual Studio์—์„œ ์ œ๊ณตํ•˜๋Š” ์ž‘์—…์ž ์„œ๋น„์Šค(Worker Service) ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

[ASP.NET] C# Windows Docker ์šฉ ์ž‘์—…์ž ์„œ๋น„์Šค ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

3. Synology Docker with Worker Service

์œˆ๋„์šฐ ๋„์ปค์—์„œ ๊ฒ€์ฆ์ด ๋๋‹ค๋ฉด, ์‹œ๋†€๋กœ์ง€ ๋„์ปค์— ์ด๋ฏธ์ง€๋ฅผ ์˜ฌ๋ฆฌ๊ณ  ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Putty๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ๋†€๋กœ์ง€์— ์ ‘์†ํ•˜๋Š” ๊ณผ์ •์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— PuTTY ์‚ฌ์šฉ ๋ฐฉ๋ฒ•๋„ ์ˆ™์ง€ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

[Synology NAS] ํ‘ธํ‹ฐ(PuTTY)๋กœ ์‹œ๋†€๋กœ์ง€ ์ ‘์†ํ•˜๋Š” ๋ฐฉ๋ฒ•

PuTTY ์‚ฌ์šฉ๋ฒ•๋„ ์ตํ˜”๋‹ค๋ฉด ๋ฆฌ๋ˆ…์Šค ๋„์ปค์šฉ ์ž‘์—…์ž ์„œ๋น„์Šค ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

[ASP.NET] C# ์‹œ๋†€๋กœ์ง€ Linux Docker ์šฉ ์ž‘์—…์ž ์„œ๋น„์Šค ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•โ€‹

๋™์ž‘ ์„ค๊ณ„

ํ˜„์žฌ ์ œ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ ˆ๋“œ๋งˆ์ธ์—๋Š” ํƒ€ ๋ถ€์„œ์—์„œ ์—…๋ฌด๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š” '์—…๋ฌด ์š”์ฒญ' ํ”„๋กœ์ ํŠธ๊ฐ€ ๋”ฐ๋กœ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€ ๋ถ€์„œ ๋‹ด๋‹น์ž๋“ค์€ ๋ชจ๋‘ ์ด๊ณณ์—์„œ ์ผ๊ฐ์„ ์ƒ์„ฑํ•˜์—ฌ ์—…๋ฌด๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฒ˜๋ฆฌ๋œ ์ผ๊ฐ์€ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ, ์ œ๊ฐ€ ์ƒ๊ฐํ•œ ์„œ๋น„์Šค์˜ ๋™์ž‘์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
โ‘  ์—…๋ฌด ์š”์ฒญ ํ”„๋กœ์ ํŠธ์— ์กด์žฌํ•˜๋Š” '์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์ผ๊ฐ'์„ ์กฐํšŒํ•œ๋‹ค.
โ‘ก ์ผ๊ฐ ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ์–ตํ•˜์—ฌ ์ค‘๋ณต์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
โ‘ข ๋ฉ”์‹ ์ €๋กœ ์ผ๊ฐ ์›น ์‚ฌ์ดํŠธ ์ฃผ์†Œ์™€ ์ œ๋ชฉ์„ ๋ฉ”์‹œ์ง€๋กœ ์ „์†กํ•œ๋‹ค. 

์•„์ฃผ ๊ฐ„๋‹จํ•˜์ฃ ? ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฝ”๋“œ ๊ตฌํ˜„์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์„œ๋น„์Šค ๋™์ž‘

์ฝ”๋“œ ๊ตฌํ˜„

์ค‘๊ฐ„์ค‘๊ฐ„ ํ™•์ธํ•ด์•ผ ํ•  ๊ฒƒ๋“ค์ด ๊ฝค ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋ฅผ ์œ„ํ•œ ํ•ต์‹ฌ ์ฝ”๋“œ ๊ตฌํ˜„์€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class Worker : BackgroundService
{
//์‹ ๊ทœ ์ผ๊ฐ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€ ์ค‘๋ณต ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ๊ฐ์ฒด
private Dictionary<int, string> _list = new Dictionary<int, string>();
//... ์ƒ๋žต...
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
//1์ดˆ ๋งˆ๋‹ค ์ง€์—ฐ
await Task.Delay(1000, stoppingToken);
//ํ˜„์žฌ ์กด์žฌํ•˜๋Š” ์ผ๊ฐ ์กฐํšŒ
var issues = searchIssues();
//์กด์žฌํ•˜๋Š” ์ผ๊ฐ์ด ์žˆ๋‹ค๋ฉด
if (issues != null)
{
foreach (var issue in issues)
{
try
{
//์ผ๊ฐ ๋ฒˆํ˜ธ์™€ ์ œ๋ชฉ์„ _list์— ์ถ”๊ฐ€
_list.Add(issue.Id, issue.Subject);
//์‹œ๋†€๋กœ์ง€ Chat์— ๋ฉ”์‹œ์ง€ ์ „์†ก
notifyChatMessage(issue);
}
catch (Exception exc)
{
//์ด๋ฏธ _list์— ์ผ๊ฐ ์ œ๋ชฉ์ด ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๋กœ ์ฒ˜๋ฆฌ
continue;
}
}
}
//ํ˜„์žฌ ์กด์žฌํ•˜๋Š” ์ผ๊ฐ์ด ์—†๋‹ค๋ฉด
else
{
//๋ชจ๋“  ์‹ ๊ทœ ์ผ๊ฐ์„ Chat์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋ƒˆ์œผ๋ฏ€๋กœ,
//ํ˜„์žฌ ์กด์žฌํ•˜๋Š” ๋ชฉ๋ก์„ ์ง€์šด๋‹ค(์ค‘๋ณต ๋ฐฉ์ง€)
if (_list.Count != 0)
{
_list.Clear();
}
}
}
catch(Exception exc)
{
_logger.LogInformation(exc.Message);
}
}
}
}

์ฝ”๋“œ๋Š” ์ƒ๊ฐ๋ณด๋‹ค ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ณ , ์ฃผ์„์œผ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ์„ค๋ช…์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ค‘๊ฐ„์— ํ˜ธ์ถœํ•˜๋Š” searchIssues()๋Š” ๋ ˆ๋“œ๋งˆ์ธ REST API ํฌ์ŠคํŒ…์„, notifyChatMessage()๋Š” Chat์— ์ฑ—๋ด‡ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

ํ›„๊ธฐ

์‹ค์ œ ์•Œ๋ฆผ ํ™”๋ฉด

ํ•ด๋‹น ์„œ๋น„์Šค๋ฅผ ์ œ์ž‘ํ•œ ํ›„ ๋น ๋ฅด๊ฒŒ ์—…๋ฌด ์š”์ฒญ ์ผ๊ฐ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ๋‹ค๋ฅธ ์ผ์„ ํ•˜๋Š๋ผ ๋ฐ”์˜๋ฉด ๋ฉ”์ผ ํ™•์ธ์ด ๋Šฆ์–ด ์—…๋ฌด ํ™•์ธ์ด ๋Šฆ์–ด์กŒ๋Š”๋ฐ, ํ˜„์žฌ๋Š” PC ๋˜๋Š” ์Šค๋งˆํŠธํฐ์œผ๋กœ ์•Œ๋ฆผ์ด ์ฆ‰์‹œ ์˜ค๋‹ˆ ๋ฐ”์˜๋”๋ผ๋„ ๋นจ๋ฆฌ ํ™•์ธํ•˜๊ฒŒ ๋˜์–ด ์—…๋ฌด ์ง€์—ฐ์ด ์ตœ์†Œํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—ญ์‹œ ๋ถˆํŽธํ•˜๋ฉด ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์ •๋‹ต์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•