์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

๊ธฐ์ž…

ะŸั€ะธะฒะตั‚!

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์‹ ๊ฒฝ๋ง์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ตฌ์ถ•ํ•œ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

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

๋…์„œ๋ฅผ ์ฆ๊ธฐ์‹ญ์‹œ์˜ค!

๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ช‡ ๋งˆ๋””

์ฃผ์š” ์•„์ด๋””์–ด๋Š” ์‚ฌ์ง„์„ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ๋žŒ์˜ ๋งค๋ ฅ์„ XNUMX์  ์ฒ™๋„๋กœ ํ‰๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

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

๋งค๋ ฅ๋„ ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ ์ž‘์—… ์‹œ ์ž‘์—…์€ ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ถ„ํ•ด๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ์‚ฌ์ง„์—์„œ ์–ผ๊ตด ์„ ํƒ
  2. ๊ฐ ์‚ฌ๋žŒ์˜ ํ‰๊ฐ€
  3. ๊ฒฐ๊ณผ ๋ Œ๋”๋ง

์ฒซ ๋ฒˆ์งธ๋Š” ์‚ฌ์ „ ํ›ˆ๋ จ๋œ ํž˜์— ์˜ํ•ด ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. MTCNN. ๋‘ ๋ฒˆ์งธ๋กœ, ์ปจ๋ณผ๋ฃจ์…”๋„ ์‹ ๊ฒฝ๋ง์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ PyTorch์—์„œ ํ›ˆ๋ จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ ˆ์Šค๋„ท34 โ€“ "CPU์˜ ์ถ”๋ก  ํ’ˆ์งˆ/์†๋„" ๊ท ํ˜•์—์„œ

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ธฐ๋Šฅ ๋‹ค์ด์–ด๊ทธ๋žจ

ํ”„๋กœ์ ํŠธ ์•„ํ‚คํ…์ฒ˜ ์š”๊ตฌ ์‚ฌํ•ญ ๋ถ„์„

์ˆ˜๋ช…์ฃผ๊ธฐ์—์„œ ML ๋ชจ๋ธ ๋ฐฐํฌ์˜ ์•„ํ‚คํ…์ฒ˜ ๋ฐ ์ž๋™ํ™”์— ๋Œ€ํ•œ ์ž‘์—…์˜ ํ”„๋กœ์ ํŠธ ๋‹จ๊ณ„๋Š” ์ข…์ข… ๊ฐ€์žฅ ์‹œ๊ฐ„๊ณผ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋งŽ์ด ์†Œ์š”๋˜๋Š” ๋‹จ๊ณ„ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

ML ํ”„๋กœ์ ํŠธ์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ

์ด ํ”„๋กœ์ ํŠธ๋„ ์˜ˆ์™ธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์„ ์˜จ๋ผ์ธ ์„œ๋น„์Šค๋กœ ๋ž˜ํ•‘ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์œผ๋ฉฐ, ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์•„ํ‚คํ…์ฒ˜์— ๋ชฐ์ž…ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ ์š”๊ตฌ ์‚ฌํ•ญ์ด ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ํ†ตํ•ฉ ๋กœ๊ทธ ์ €์žฅ โ€“ ๋ชจ๋“  ์„œ๋น„์Šค๋Š” ํ•œ ๊ณณ์— ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฉฐ, ๋ถ„์„ํ•˜๊ธฐ ํŽธ๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ํ‰๊ฐ€ ์„œ๋น„์Šค์˜ ์ˆ˜ํ‰์  ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ - ๋ณ‘๋ชฉ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๊ฐ€์žฅ ๋†’์Œ
  3. ์ถ”๋ก  ์‹œ๊ฐ„ ๋ถ„๋ฐฐ์—์„œ ์ด์ƒ๊ฐ’์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ๊ฐ ์ด๋ฏธ์ง€๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ๋ฐ ๋™์ผํ•œ ์–‘์˜ ํ”„๋กœ์„ธ์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ• ๋‹นํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  4. ํŠน์ • ์„œ๋น„์Šค์™€ ์Šคํƒ ์ „์ฒด์˜ ๋น ๋ฅธ (์žฌ)๋ฐฐํฌ
  5. ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค์—์„œ ๊ณตํ†ต ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ

๊ตฌ์กฐ

์š”๊ตฌ ์‚ฌํ•ญ์„ ๋ถ„์„ํ•œ ํ›„ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜๊ฐ€ ๊ฑฐ์˜ ์™„๋ฒฝํ•˜๊ฒŒ ์ ํ•ฉํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ถ„๋ช…ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

๋ถˆํ•„์š”ํ•œ ๊ณจ์น˜ ์•„ํ”ˆ ๋ฌธ์ œ๋ฅผ ์—†์• ๊ธฐ ์œ„ํ•ด Telegram API๊ฐ€ ํ”„๋ŸฐํŠธ์—”๋“œ๋กœ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ์™„์„ฑ๋œ ์•„ํ‚คํ…์ฒ˜์˜ ๊ตฌ์กฐ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ์‚ดํŽด๋ณธ ๋‹ค์Œ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ์ด๋™ํ•˜๊ณ  ์„ฑ๊ณต์ ์ธ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ํ˜•์‹ํ™”ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

์™„์„ฑ๋œ ์•„ํ‚คํ…์ฒ˜์˜ ๊ตฌ์กฐ ๋‹ค์ด์–ด๊ทธ๋žจ

์ด๋ฏธ์ง€ ํ‰๊ฐ€ ๊ณผ์ •์—์„œ ๋‹จ์ผ ์ฑ…์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ์˜ ๊ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค โ€œattrai-telegram-botโ€

์ด ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” Telegram API์™€์˜ ๋ชจ๋“  ์ƒํ˜ธ ์ž‘์šฉ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • ์ด๋ฏธ์ง€ ์ž‘์—…๊ณผ ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ ๊ฒฐ๊ณผ ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์šฉ์–ด๋กœ ๋‘ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋ชจ๋‘ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋œ ๋งž์ถค ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ:

  1. ๋‹ค์Œ ๊ฒ€์‚ฌ๋กœ ๊ตฌ์„ฑ๋œ ํ•„ํ„ฐ๋ง์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
    • ์ตœ์ ์˜ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๊ฐ€์šฉ์„ฑ
    • ์ด๋ฏธ ๋Œ€๊ธฐ์—ด์— ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ด๋ฏธ์ง€ ์ˆ˜
  2. ์ดˆ๊ธฐ ํ•„ํ„ฐ๋ง์„ ํ†ต๊ณผํ•˜๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ๋„์ปค ๋ณผ๋ฅจ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
  3. ์ž‘์—…์€ ๋ฌด์—‡๋ณด๋‹ค๋„ ๋ณผ๋ฅจ์— ์žˆ๋Š” ์ด๋ฏธ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•˜๋Š” "to_estimate" ๋Œ€๊ธฐ์—ด์—์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  4. ์œ„ ๋‹จ๊ณ„๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด ์‚ฌ์šฉ์ž๋Š” ๋Œ€๊ธฐ์—ด์˜ ์ž‘์—… ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐ๋œ ๋Œ€๋žต์ ์ธ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์ด ํฌํ•จ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฌด์—‡์ด ์ž˜๋ชป๋˜์—ˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ช…์‹œ์ ์œผ๋กœ ์•Œ๋ฆฝ๋‹ˆ๋‹ค.

๋˜ํ•œ ์…€๋Ÿฌ๋ฆฌ ์ž‘์—…์ž์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ต๊ณผํ•œ ์ž‘์—…์„ ์œ„ํ•œ "after_estimate" ๋Œ€๊ธฐ์—ด์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.

"after_estimate"์—์„œ ์ƒˆ ์ž‘์—…์„ ๋ฐ›์„ ๋•Œ:

  1. ์ด๋ฏธ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „์†กํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜ค๋ฅ˜๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
  2. ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ฒฐ๊ณผ์ธ ์ด๋ฏธ์ง€ ์ œ๊ฑฐ

ํ‰๊ฐ€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค โ€œattrai-estimatorโ€

์ด ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋Š” ์…€๋Ÿฌ๋ฆฌ ์ž‘์—…์ž์ด๋ฉฐ ์ด๋ฏธ์ง€ ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ฒƒ์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์ž‘๋™ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ํ•˜๋‚˜๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

"to_estimate"๋กœ๋ถ€ํ„ฐ ์ƒˆ ์ž‘์—…์„ ๋ฐ›์„ ๋•Œ:

  1. ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
    1. ์ด๋ฏธ์ง€๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ
    2. ์ด๋ฏธ์ง€๋ฅผ ํ•„์š”ํ•œ ํฌ๊ธฐ๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    3. ๋ชจ๋“  ์–ผ๊ตด ์ฐพ๊ธฐ(MTCNN)
    4. ๋ชจ๋“  ์–ผ๊ตด์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. (๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์—์„œ ์ฐพ์€ ์–ผ๊ตด์„ ์ผ๊ด„ ์ฒ˜๋ฆฌํ•˜๊ณ  ResNet34๋ฅผ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.)
    5. ์ตœ์ข… ์ด๋ฏธ์ง€ ๋ Œ๋”๋ง
      1. ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ทธ๋ ค ๋ด…์‹œ๋‹ค
      2. ํ‰์  ๊ทธ๋ฆฌ๊ธฐ
  2. ์‚ฌ์šฉ์ž ์ •์˜(์›๋ณธ) ์ด๋ฏธ์ง€ ์‚ญ์ œ
  3. ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ถœ๋ ฅ ์ €์žฅ
  4. ์œ„์—์„œ ์„ค๋ช…ํ•œ "attrai-telegram-bot" ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๊ฐ€ ์ˆ˜์‹ ํ•˜๋Š” "after_estimate" ๋Œ€๊ธฐ์—ด์— ์ž‘์—…์„ ๋„ฃ์Šต๋‹ˆ๋‹ค.

Graylog(+ mongoDB + Elasticsearch)

๊ทธ๋ ˆ์ด๋กœ๊ทธ ์ค‘์•™ํ™”๋œ ๋กœ๊ทธ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. ๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์˜๋„ํ•œ ๋ชฉ์ ์— ๋งž๊ฒŒ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์„ ํƒ์€ ๊ทธ์—๊ฒŒ ๋–จ์–ด์กŒ๊ณ  ํ‰์†Œ์˜ ์„ ํƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ณ ๋ผ๋‹ˆ Python์—์„œ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํƒ์ž…๋‹ˆ๋‹ค. Graylog์— ๋กœ๊ทธ์ธํ•˜๊ธฐ ์œ„ํ•ด ํ•ด์•ผ ํ•  ์ผ์€ ํŒจํ‚ค์ง€์—์„œ GELFTCPHandler๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ˆ์ดํ”ผ Python ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์˜ ๋‚˜๋จธ์ง€ ๋ฃจํŠธ ๋กœ๊ฑฐ ํ•ธ๋“ค๋Ÿฌ์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

์ด์ „์— ELK ์Šคํƒ์œผ๋กœ๋งŒ ์ž‘์—…ํ–ˆ๋˜ ์‚ฌ๋žŒ์œผ๋กœ์„œ ์ €๋Š” Graylog๋กœ ์ž‘์—…ํ•˜๋ฉด์„œ ์ „๋ฐ˜์ ์œผ๋กœ ๊ธ์ •์ ์ธ ๊ฒฝํ—˜์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ค๋ง์Šค๋Ÿฌ์šด ์œ ์ผํ•œ ์ ์€ Graylog ์›น ์ธํ„ฐํŽ˜์ด์Šค์— ๋น„ํ•ด Kibana ๊ธฐ๋Šฅ์ด ์šฐ์›”ํ•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

RabbitMQ

RabbitMQ AMQP ํ”„๋กœํ† ์ฝœ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค์ž…๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์•ˆ์ •์ ์ด๊ณ  ์‹œ๊ฐ„ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑฐ์นœ Celery์šฉ ๋ธŒ๋กœ์ปค์ด๋ฉฐ ๋‚ด๊ตฌ์„ฑ ๋ชจ๋“œ์—์„œ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

Redis

Redis ํ‚ค-๊ฐ’ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ์ž‘๋™ํ•˜๋Š” NoSQL DBMS์ž…๋‹ˆ๋‹ค.

๋•Œ๋กœ๋Š” ๋‹ค์–‘ํ•œ Python ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณตํ†ต ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Redis๋Š” "telegram_user_id => ๋Œ€๊ธฐ์—ด์˜ ํ™œ์„ฑ ์ž‘์—… ์ˆ˜" ํ˜•์‹์˜ ํ•ด์‹œ๋งต์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•œ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ ์ˆ˜๋ฅผ ํŠน์ • ๊ฐ’์œผ๋กœ ์ œํ•œํ•˜์—ฌ DoS ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์ธ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๊ณผ์ •์„ ๊ณต์‹ํ™”ํ•ด๋ณด์ž

  1. ์‚ฌ์šฉ์ž๊ฐ€ ํ…”๋ ˆ๊ทธ๋žจ ๋ด‡์— ์ด๋ฏธ์ง€๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  2. "attrai-telegram-bot"์€ Telegram API๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ด๋ฏธ์ง€๊ฐ€ ํฌํ•จ๋œ ์ž‘์—…์ด ๋น„๋™๊ธฐ ๋Œ€๊ธฐ์—ด "to_estimate"์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
  4. ์‚ฌ์šฉ์ž๋Š” ๊ณ„ํš๋œ ํ‰๊ฐ€ ์‹œ๊ฐ„์ด ํฌํ•จ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.
  5. "attrai-estimator"๋Š” "to_estimate" ๋Œ€๊ธฐ์—ด์—์„œ ์ž‘์—…์„ ๊ฐ€์ ธ์™€์„œ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ตํ•ด ์ถ”์ •์น˜๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ž‘์—…์„ "after_estimate" ๋Œ€๊ธฐ์—ด์— ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  6. "after_estimate" ๋Œ€๊ธฐ์—ด์„ ์ˆ˜์‹ ํ•˜๋Š” "attrai-telegram-bot"์€ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž

๋งˆ์ง€๋ง‰์œผ๋กœ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ฒ€ํ† ํ•œ ํ›„ ๋˜‘๊ฐ™์ด ํฅ๋ฏธ๋กœ์šด ๋ถ€๋ถ„์ธ DevOps๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„์ปค ์Šค์›œ

 

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

๋„์ปค ์Šค์›œ  โ€” ๊ธฐ๋Šฅ์ด Docker ์—”์ง„ ๋‚ด๋ถ€์— ๊ตฌํ˜„๋˜์–ด ์ฆ‰์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ง ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.

"swarm"์„ ์‚ฌ์šฉํ•˜๋ฉด ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ž‘์—…์ž์™€ ๊ด€๋ฆฌ์ž์˜ ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์œ ํ˜•์˜ ๋จธ์‹ ์—์„œ๋Š” ์ปจํ…Œ์ด๋„ˆ ๊ทธ๋ฃน(์Šคํƒ)์ด ๋ฐฐํฌ๋˜๊ณ , ๋‘ ๋ฒˆ์งธ ์œ ํ˜•์˜ ๋จธ์‹ ์€ ํ™•์žฅ, ๊ท ํ˜• ์กฐ์ • ๋ฐ ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฉ‹์ง„ ๊ธฐ๋Šฅ. ๊ด€๋ฆฌ์ž๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ทผ๋กœ์ž์ž…๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

๋ฆฌ๋” ๊ด€๋ฆฌ์ž XNUMX๋ช…๊ณผ ์ž‘์—…์ž XNUMX๋ช…์ด ์žˆ๋Š” ํด๋Ÿฌ์Šคํ„ฐ

๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ํด๋Ÿฌ์Šคํ„ฐ ํฌ๊ธฐ๋Š” ๋…ธ๋“œ 1๊ฐœ์ด๋ฉฐ, ๋‹จ์ผ ๋จธ์‹ ์€ ๋ฆฌ๋” ๊ด€๋ฆฌ์ž์™€ ์ž‘์—…์ž ์—ญํ• ์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ์™€ ๋‚ด๊ฒฐํ•จ์„ฑ์— ๋Œ€ํ•œ ์ตœ์†Œ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์•ž์œผ๋กœ๋Š” XNUMX์›” ์ค‘์ˆœ์— ์žˆ์—ˆ๋˜ ์ฒซ ๋ฒˆ์งธ ์ œํ’ˆ ์ธ๋„ ์ดํ›„ ์ด ํด๋Ÿฌ์Šคํ„ฐ ์กฐ์ง๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋‹ค๊ณ  ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. (๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ๊ทธ๋Ÿฌํ•œ ์กฐ์ง์ด ์–ด๋–ค ์ค‘๋Œ€ํ˜• ์กฐ์ง์—์„œ๋„ ํ—ˆ์šฉ๋œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ๋‚ด๊ฒฐํ•จ์„ฑ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์ ์šฉ๋˜๋Š” ํ”„๋กœ์ ํŠธ).

๋„์ปค ์Šคํƒ

์Šค์›œ ๋ชจ๋“œ์—์„œ๋Š” ์Šคํƒ(๋„์ปค ์„œ๋น„์Šค ์„ธํŠธ) ๋ฐฐํฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋„์ปค ์Šคํƒ

docker-compose ๊ตฌ์„ฑ์„ ์ง€์›ํ•˜๋ฏ€๋กœ ๋ฐฐํฌ ์˜ต์…˜์„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  

์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Ÿฌํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ํ‰๊ฐ€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค(N ์ธ์Šคํ„ด์Šค์— N ์ฝ”์–ด๋ฅผ ํ• ๋‹นํ•˜๊ณ  ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์ž์ฒด์—์„œ๋Š” PyTorch์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”์–ด ์ˆ˜๋ฅผ ํ•˜๋‚˜๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค).

attrai_estimator:
  image: 'erqups/attrai_estimator:1.2'
  deploy:
    replicas: 4
    resources:
      limits:
        cpus: '4'
    restart_policy:
      condition: on-failure
      โ€ฆ

Redis, RabbitMQ ๋ฐ Graylog๋Š” ์ƒํƒœ ์ €์žฅ ์„œ๋น„์Šค์ด๋ฉฐ "attrai-estimator"๋งŒํผ ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์งˆ๋ฌธ์„ ์˜ˆ์‹œํ•ฉ๋‹ˆ๋‹ค. Kubernetes๋Š” ์™œ ์•ˆ ๋ฉ๋‹ˆ๊นŒ?

์ค‘์†Œ ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ Kubernetes๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์˜ค๋ฒ„ํ—ค๋“œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๋ชจ๋“  ๊ธฐ๋Šฅ์€ ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ์—๊ฒŒ ๋งค์šฐ ์‚ฌ์šฉ์ž ์นœํ™”์ ์ด๊ณ  ์ง„์ž… ์žฅ๋ฒฝ๋„ ๋‚ฎ์€ Docker Swarm์—์„œ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋ถ€ ๊ตฌ์กฐ

์ด ๋ชจ๋“  ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์„ฑ์„ ๊ฐ€์ง„ VDS์— ๋ฐฐํฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • CPU: 4์ฝ”์–ด Intelยฎ Xeonยฎ Gold 5120 CPU @ 2.20GHz
  • RAM : 8 GB
  • SSD : 160GB

๋กœ์ปฌ ๋กœ๋“œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑฐ์นœ ํ›„ ์‚ฌ์šฉ์ž๊ฐ€ ๋งŽ์ด ์œ ์ž…๋˜๋ฉด ์ด ๋จธ์‹ ์ด๋ฉด ์ถฉ๋ถ„ํ•  ๊ฒƒ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ฐฐํฌ ์งํ›„ CIS์—์„œ ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๋Š” ์ด๋ฏธ์ง€ ๋ณด๋“œ ์ค‘ ํ•˜๋‚˜(์˜ˆ, ๊ฐ™์€ ์ด๋ฏธ์ง€)์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ๊ฒŒ์‹œํ–ˆ๊ณ  ๊ทธ ํ›„ ์‚ฌ๋žŒ๋“ค์ด ๊ด€์‹ฌ์„ ๊ฐ–๊ฒŒ ๋˜์—ˆ๊ณ  ๋ช‡ ์‹œ๊ฐ„ ๋งŒ์— ์„œ๋น„์Šค๊ฐ€ ์ˆ˜๋งŒ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋™์‹œ์—, ํ”ผํฌ ์ˆœ๊ฐ„์—๋Š” CPU์™€ RAM ๋ฆฌ์†Œ์Šค๊ฐ€ ์ ˆ๋ฐ˜๋„ ์‚ฌ์šฉ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”
์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

์ถ”๊ฐ€ ๊ทธ๋ž˜ํ”ฝ

๋ฐฐํฌ ์ดํ›„ ๋‚ ์งœ์— ๋”ฐ๋ฅธ ๊ณ ์œ  ์‚ฌ์šฉ์ž ์ˆ˜ ๋ฐ ํ‰๊ฐ€ ์š”์ฒญ ์ˆ˜

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ ์ถ”๋ก  ์‹œ๊ฐ„ ๋ถ„ํฌ

์‹ ๊ฒฝ๋ง ๊ธฐ๋ฐ˜ ์™ธ๊ด€ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์ผ๋ฐ˜ ๊ฐœ์š”

์กฐ์‚ฌ ๊ฒฐ๊ณผ

์š”์•ฝํ•˜์ž๋ฉด, ์ปจํ…Œ์ด๋„ˆ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์— ๋Œ€ํ•œ ์•„ํ‚คํ…์ฒ˜์™€ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์™„์ „ํžˆ ์ •๋‹นํ™”๋˜์—ˆ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด ํ”ผํฌ ์ˆœ๊ฐ„์—๋„ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์ด ๋–จ์–ด์ง€๊ฑฐ๋‚˜ ๋Š๋ ค์ง€๋Š” ์ผ์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค. 

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

์ฒ˜์Œ์—๋Š” ๊ธฐ์‚ฌ๊ฐ€ ๋” ๊ธธ์—ˆ์ง€๋งŒ ๊ธธ๊ฒŒ ์ฝ์€ ๋‚ด์šฉ์„ ๊ฒŒ์‹œํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ์ด ๊ธฐ์‚ฌ์—์„œ ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ์ƒ๋žตํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ–ฅํ›„ ๋ฐœํ–‰๋ฌผ์—์„œ ์ด์— ๋Œ€ํ•ด ๋‹ค์‹œ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Telegram - @AttraiBot์—์„œ ๋ด‡์„ ์ฐŒ๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ ์–ด๋„ 2020๋…„ ๊ฐ€์„ ๋ง๊นŒ์ง€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์›๋ณธ ์ด๋ฏธ์ง€๋‚˜ ํ‰๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ฒฐ๊ณผ ๋“ฑ ์–ด๋–ค ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋„ ์ €์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ ๋ชจ๋“  ๊ฒƒ์ด ์ฒ˜๋ฆฌ ํ›„์— ํ๊ธฐ๋ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€