ActiveMQ์˜ Virtual Destinations๋ฅผ ํ™œ์šฉํ•œ ๋ฉ”์‹œ์ง€ ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ

๋ธ”๋กœ๊ทธ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค! ๐Ÿก’ integer.blog

AmazonMQ(ActiveMQ)์˜ Virtual Destinations๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€ ์ค‘๋ณต์ฒ˜๋ฆฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ๊ฒฝํ—˜์— ๋Œ€ํ•œ ๊ธ€์ด๋‹ค.

ํšŒ์‚ฌ์˜ ์„œ๋น„์Šค ๊ฐ„ ์ปจํ…์ธ  ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋˜ AWS SQS๋ฅผ AmazonMQ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ฉด์„œ,
AmazonMQ(ActiveMQ)์˜ Topic์„ ์ด์šฉํ•œ Pub-Sub ๋ฐฉ์‹์˜ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ ๊ตฌ์„ฑํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ชจ๋“  Subscriber์— ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์‹œ์ง€ ์ค‘๋ณต์ฒ˜๋ฆฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ,
์ด ๋ฌธ์ œ๋ฅผ ActiveMQ์˜ Virtual Topics ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•œ ๊ณผ์ •์„ ์ •๋ฆฌํ•œ๋‹ค.

๋ชฉ์ฐจ

  1. Queue ๋ฐฉ์‹๊ณผ Topic ๋ฐฉ์‹ ๊ฐœ๋… ์ดํ•ด
  2. ๊ธฐ์กด ์ƒํ™ฉ
  3. ๋ณ€๊ฒฝ๋œ ์ƒํ™ฉ
  4. AmazonMQ(ActiveMQ) ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
  5. ๋ฌธ์ œ ๋ฐœ์ƒ
  6. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 1 - Batch ์„œ๋ฒ„๋ฅผ 1๋Œ€๋งŒ ์‚ฌ์šฉ
  7. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 2 - UUID ์‚ฌ์šฉ
  8. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 3 - Virtual Destinations ํ™œ์šฉ
  9. Virtual Topics ๊ฐœ๋… ์ดํ•ด
  10. Virtual Topics ์ ์šฉ ๊ฒฐ๊ณผ
  11. Virtual Topics ์‚ฌ์šฉ ๋ฐฉ๋ฒ• (with Spring Boot)
  12. ๋งบ์œผ๋ฉฐ


1. Queue ๋ฐฉ์‹๊ณผ Topic ๋ฐฉ์‹ ๊ฐœ๋… ์ดํ•ด

์‹œ์ž‘ํ•˜๊ธฐ์— ์•ž์„œ, ์•ž์œผ๋กœ ๊ณ„์† ์–ธ๊ธ‰๋  Queue ๋ฐฉ์‹๊ณผ Topic ๋ฐฉ์‹ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœํ‚น์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

1-1. Queue

ActiveMQ์˜ Queue๋Š” Producer๊ฐ€ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋ฅผ 1๊ฐœ์˜ Consumer๊ฐ€ ๋ฐ›๋Š”๋‹ค.
๋ฉ”์‹œ์ง€๋Š” Queue์— ์Œ“์ด๊ณ , Consumer๋Š” Queue์—์„œ ํ•˜๋‚˜์”ฉ ์†Œ๋น„ํ•œ๋‹ค.

1:1 ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœํ‚น

1-2. Topic

ActiveMQ์˜ Topic์€ Producer(Publisher)๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰(publish)ํ•˜๊ณ ,
N๊ฐœ์˜ Consumer(Subscriber)๊ฐ€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌ๋…(subscribe) ํ•œ๋‹ค.

1:N ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœํ‚น (Pub-Sub)

Topic ๋ฐฉ์‹์€ ๋ชจ๋“  Consumer๊ฐ€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š”๋‹ค.


2. ๊ธฐ์กด ์ƒํ™ฉ

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

์ฆ‰, ๋‰ด์Šค์คŒ - ํ—ˆ๋ธŒ์คŒ ๊ฐ„ ์ปจํ…์ธ  ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ–ˆ๊ณ ,
์•„๋ž˜์™€ ๊ฐ™์ด AWS SQS๋ฅผ ํ™œ์šฉํ•ด์„œ ๋‰ด์Šค์คŒ-ํ—ˆ๋ธŒ์คŒ ๊ฐ„ ์ปจํ…์ธ  ๋™๊ธฐํ™”๋ฅผ ์ž๋™ํ™”ํ•œ ์ƒํƒœ์˜€๋‹ค.

์œ„์˜ ๋„์‹์—์„œ AWS SQS๋ฅผ ์‚ฌ์šฉํ•œ ๋ถ€๋ถ„๋งŒ ๊ฐ„๋‹จํžˆ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.


3. ๋ณ€๊ฒฝ๋œ ์ƒํ™ฉ

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


4. AmazonMQ(ActiveMQ) ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

๋ฌผ๋ก  ์œ„์˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ AWS SQS ํ๋ฅผ ํ•˜๋‚˜ ๋” ์ƒ์„ฑํ•ด์„œ ์šด์˜ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ,
๋‰ด์Šค ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” ์„œ๋น„์Šค๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ ๋งˆ๋‹ค Queue๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‰ด์Šค์คŒ์—์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๋ฐœํ–‰ํ•˜๊ณ ,
N๊ฐœ์˜ ์„œ๋น„์Šค์—์„œ ๊ฐ์ž ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„๊ฐˆ ์ˆ˜ ์žˆ๋Š” Pub-Sub ๋ฐฉ์‹์˜ ๊ตฌ์„ฑ์ด ํ•„์š”
ํ–ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ์•ž์„œ ์„ค๋ช…ํ•œ Topic ๋ฐฉ์‹ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœํ‚น์ด๋ฉฐ,
Topic ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด AmazonMQ(ActiveMQ)๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ–ˆ๋‹ค.

AmazonMQ๋งŒ Pub-Sub ๋ฐฉ์‹์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค!
๋งŽ์€ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๊ฐ€ Pub-Sub ๋ฐฉ์‹์„ ์ง€์›ํ•˜์ง€๋งŒ, ํŒ€ ๋‚ด๋ถ€ ํšŒ์˜๋ฅผ ํ†ตํ•ด AmazonMQ๊ฐ€ ์„ ํƒ๋˜์—ˆ๋‹ค.

*ํฌํ„ธ๊ฐœ๋ฐœํŒ€์—์„œ AmazonMQ๋ฅผ ์„ ํƒํ•œ ์ด์œ 

  • AWS SQS์™€ SNS๋ฅผ ํ˜ผ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณต์žก๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ๋ฌธ์ œ
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹Œ ์ปจํ…์ธ  ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ๋ฉ”์‹œ์ง€์ด๊ธฐ ๋•Œ๋ฌธ์— AmazonMQ๋กœ ์ถฉ๋ถ„
  • ์„œ๋ฒ„ ์ด์ค‘ํ™” ๋ฐ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ ์ฐจ์ ์œผ๋กœ Severless๋ฅผ ์ง€ํ–ฅํ•˜๋Š” ํŒ€์˜ ๋ฐฉํ–ฅ์„ฑ์— ๋ถ€ํ•ฉํ•จ
  • AmazonMQ์˜ ๊ฐ„๋‹จํ•œ ์„ค์ •์œผ๋กœ ์ธํ•ด, ์ตœ๋Œ€ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์—ˆ์Œ
  • IDC ํ™˜๊ฒฝ์—์„œ RabbitMQ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ–ˆ์œผ๋‚˜, ํŒ€์—์„œ ์ ์šฉ์ค‘์ธ ํด๋ผ์šฐ๋“œ ํ‘œ์ค€ํ™”์— ๋งž์ถ”์–ด AmazonMQ๋ฅผ ์„ ํƒ


5. ๋ฌธ์ œ ๋ฐœ์ƒ

AmazonMQ์˜ Topic ๋ฐฉ์‹์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•œ ํ›„,
ํ—ˆ๋ธŒ์คŒ์˜ Batch ์„œ๋ฒ„๋ฅผ ๋Œ๋ ค๋ณด๋‹ˆ, ๊ฐ™์€ ์ปจํ…์ธ ๊ฐ€ 2๋ฒˆ์”ฉ ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

ActiveMQ์˜ Topic ๋ฐฉ์‹์€ ๋ชจ๋“  Subscriber๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—,
2๋Œ€๋กœ ๊ตฌ์„ฑ๋œ ํ—ˆ๋ธŒ์คŒ์˜ Batch ์„œ๋ฒ„๊ฐ€ ๊ฐ๊ฐ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•œ ๊ฒƒ์ด๋‹ค.

๊ธฐ์กด์— AWS SQS๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ค‘๋ณต์ฒ˜๋ฆฌ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋‹ค.
SQS๋Š” Queue ๋ฐฉ์‹์ด๋ผ์„œ 2๋Œ€์˜ Batch ์„œ๋ฒ„๊ฐ€ 1๊ฐœ์˜ Queue๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ฌผ๋ก  ๋ฉ”์‹œ์ง€ ์ค‘๋ณต์ฒ˜๋ฆฌ๊ฐ€ ์‹ค์ œ ์„œ๋น„์Šค์—๋Š” ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š์•˜์ง€๋งŒ,
2๋Œ€์˜ ์„œ๋ฒ„๊ฐ€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ๊ฐ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„๋ฅผ ๋ฐฉ๊ด€ํ•˜๋Š” ๊ฒƒ์€ ์ •์‹  ๊ฑด๊ฐ•์— ํ•ด๋กœ์› ๋‹ค.
๊ทธ๋ž˜์„œ ์–ด๋–ป๊ฒŒ๋“  ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.


6. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 1 - Batch ์„œ๋ฒ„๋ฅผ 1๋Œ€๋งŒ ์‚ฌ์šฉ

์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž์˜ ์ข์€ ์‹œ์•ผ๋กœ๋Š” ๋‹ค์–‘ํ•œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์ด ๋– ์˜ค๋ฅด์ง€ ์•Š์•˜๋‹ค.
๊ฐ€์žฅ ๋จผ์ € ๋– ์˜ค๋ฅธ ๋ฐฉ๋ฒ•์€ TV์คŒ ์ฒ˜๋Ÿผ 1๋Œ€์˜ Batch ์„œ๋ฒ„๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

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

๊ฒŒ๋‹ค๊ฐ€ ํ—ˆ๋ธŒ์คŒ์˜ Batch ์„œ๋ฒ„๋“ค์€ ๋‰ด์Šค์ปจํ…์ธ  ๋™๊ธฐํ™” ์ด์™ธ์—๋„ ๊ฐ์ข… Batch ์ž‘์—…์ด ๋Œ์•„๊ฐ€๋Š” ์„œ๋ฒ„๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ํ—ˆ๋ธŒ์คŒ์„ ๋‹ด๋‹นํ•œ์ง€ ์–ผ๋งˆ ์•ˆ๋œ ์ƒํ™ฉ์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์„œ๋ฒ„ ์Šค์ผ€์ผ ์ถ•์†Œ(Scale in)๊ฐ€ ๊ฐ€์ ธ์˜ฌ ๋ถ€์ž‘์šฉ์€ ์˜ˆ์ƒํ•˜๊ธฐ ํž˜๋“ค์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด ๋ฐฉ๋ฒ•์€ ๋” ์ด์ƒ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜๋‹ค.


7. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 2 - UUID ์‚ฌ์šฉ

๋งŒ์•ฝ ํ—ˆ๋ธŒ์คŒ์˜ Batch ์„œ๋ฒ„๋“ค์ด ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค๋ฉด,
๋‰ด์Šค์คŒ์—์„œ ๋ฉ”์‹œ์ง€(๋‰ด์Šค ๋ฐ์ดํ„ฐ)์— UUID๋ฅผ ํฌํ•จ์‹œ์ผœ์„œ Publish ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ–ˆ๋‹ค.

์ด ๊ฒฝ์šฐ Batch ์„œ๋ฒ„๋“ค์€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋˜,
๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹œ์ ์— UUID๋กœ ๊ฒ€์ฆํ•ด์„œ ์ค‘๋ณต์ฒ˜๋ฆฌ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ UUID๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ˆœ๊ฐ„, ๊ด€๋ จ ๋ชจ๋“  ์„œ๋น„์Šค์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ด€๋ฆฌ ํฌ์ธํŠธ๊ฐ€ ํ•˜๋‚˜ ๋Š˜์–ด๋‚œ๋‹ค.
(Publisher์™€ Subscriber ์–‘์ชฝ DB์— UUID์ปฌ๋Ÿผ ์ถ”๊ฐ€, ๊ด€๋ จ ํด๋ž˜์Šค์— UUID ๊ฒ€์ฆ ๋กœ์ง ์ถ”๊ฐ€…๋“ฑ๋“ฑ)

๋˜ํ•œ UUID๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ค‘๋ณต์ฒ˜๋ฆฌ๋ฅผ ๋ฐฉ์–ดํ•˜๋Š” ๋กœ์ง์€ DB์ ‘๊ทผ์„ ๋น„์•ฝ์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์—,
๊ฒฐ๊ตญ ์„œ๋ฒ„๋ฅผ 1๋Œ€๋งŒ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ ๋ณด๋‹ค๋„ ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๊ณ  DB์ ‘๊ทผ์„ ์ค„์ด๊ณ ์ž Redis๋กœ UUID๋ฅผ ์บ์‹ฑํ•˜๋Š” ๊ฒƒ์€, ๋˜ ๋‹ค๋ฅธ ๊ด€๋ฆฌ ํฌ์ธํŠธ๋ฅผ ๋Š˜๋ฆฌ๋Š” ์ผ์ด์—ˆ๋‹ค.

๊ฒฐ๊ตญ, ์ด ๋ฐฉ๋ฒ•๋„ ์ ์ ˆํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์•„๋‹ˆ์—ˆ๋‹ค.


8. ํ•ด๊ฒฐ ๋ฐฉ์•ˆ 3 - Virtual Destinations ํ™œ์šฉ

ActiveMQ ์™ธ์ ์œผ๋กœ๋งŒ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ๋‹ค๊ฐ€,
ActiveMQ ์ž์ฒด์— ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์— ActiveMQ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๋’ค์ ๊ฑฐ๋ ธ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ, Destination Features ์นดํ…Œ๊ณ ๋ฆฌ์—์„œ Virtual Destinations๋ฅผ ์ฐพ์•˜๋‹ค.
๋‚ด์šฉ์„ ์ฒœ์ฒœํžˆ ์ฝ์–ด๋ณด๋‹ˆ, ๋ฉ”์‹œ์ง€ ์ค‘๋ณต์ฒ˜๋ฆฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ค„ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

๊ณง๋ฐ”๋กœ Virtual Topics์˜ ๊ฐœ๋…๊ณผ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ณ ,
QA์„œ๋ฒ„์™€ ๋กœ์ปฌ์„œ๋ฒ„๋ฅผ ๊ฐ๊ฐ Batch ์„œ๋ฒ„1, 2๋กœ ์ƒ๊ฐํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ, ๋ฉ”์‹œ์ง€ ์ค‘๋ณต์ฒ˜๋ฆฌ ๋ฌธ์ œ๊ฐ€ ๋ง๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค!
(์ƒ์„ธ ๋‚ด์šฉ์€ ๋’ค์—์„œ ์„ค๋ช…)


9. Virtual Topics ๊ฐœ๋… ์ดํ•ด

๋“œ๋””์–ด Virtual Topics์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

Virtual Topics์€ ๊ธฐ์กด์˜ Topic ๋ฐฉ์‹๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ,
ํ•ต์‹ฌ์€ Logical Topic๊ณผ Physical Queue๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

Publisher๋Š” ๊ฐ€์ƒ์˜(Logical) Topic์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๊ณ ,
์ด ๊ฐ€์ƒ์˜ Topic์„ Subscriber๊ฐ€ ๊ตฌ๋…ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด, (์ฆ‰, Listening์„ ์‹œ์ž‘ํ•˜๋ฉด)
ActiveMQ ๋ธŒ๋กœ์ปค์— ํ•ด๋‹น Subscriber๋งŒ์„ ์œ„ํ•œ ๋ฌผ๋ฆฌ์ ์ธ(Physical) Queue๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Subscriber๋Š” ์ž๋™์ƒ์„ฑ๋œ ๋ฌผ๋ฆฌ Queue๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

๋˜ํ•œ, ๊ฐ Consumer๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด Topic์—์„œ ์ง์ ‘ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ๊ณ , Queue๋กœ๋ถ€ํ„ฐ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ๋‹ค.
์•„๋ž˜๋Š” Batch ์„œ๋ฒ„๊ฐ€ 1๋Œ€์ธ TV์คŒ๊ณผ 2๋Œ€์ธ ํ—ˆ๋ธŒ์คŒ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š” ๋ฐฉ์‹์„ ํ‘œํ˜„ํ•œ๋‹ค.

[๋‰ด์Šค์คŒ] --> [VirtualTopic.news] --> [TV์คŒ Batch 1]
                               --> [Consumer.hub.VirtualTopic.news] --> [ํ—ˆ๋ธŒ์คŒ Batch 1]
                                                                    --> [ํ—ˆ๋ธŒ์คŒ Batch 2]


10. Virtual Topics ์ ์šฉ ๊ฒฐ๊ณผ

์•ž์„œ ์„ค๋ช…ํ•œ Virtual Topics๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค.

๋‰ด์Šค์คŒ์€ Topic ๋ฐฉ์‹ ๊ทธ๋Œ€๋กœ ๋ฉ”์‹œ์ง€๋ฅผ Publishํ•˜๊ณ , (Topic ์ด๋ฆ„๋งŒ ๋ณ€๊ฒฝ)
Batch ์„œ๋ฒ„๊ฐ€ 1๋Œ€์ธ TV์คŒ์€ Topic ๋ฐฉ์‹ ๊ทธ๋Œ€๋กœ ๋ฉ”์‹œ์ง€๋ฅผ Subscribe ํ•œ๋‹ค. (Topic ์ด๋ฆ„๋งŒ ๋ณ€๊ฒฝ)

Batch ์„œ๋ฒ„๊ฐ€ 2๋Œ€์ธ ํ—ˆ๋ธŒ์คŒ์€ Topic ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ Subscribe ํ•˜๋˜,
Logical Topic์„ Listening ํ•  ๋•Œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” Physical Queue๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ•œ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, ํ—ˆ๋ธŒ์คŒ์˜ Batch ์„œ๋ฒ„ 2๋Œ€๊ฐ€ ํ•˜๋‚˜์˜ Queue๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ•˜๋„๋ก ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋ฐฉ์‹์€ ํฌ๊ฒŒ 3๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ๋‹ค.

  1. ๊ธฐ์กด์˜ Topic๋ฐฉ์‹์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ด€๋ฆฌํฌ์ธํŠธ๊ฐ€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๋Š”๋‹ค. Topic ์ด๋ฆ„๋งŒ ๋ณ€๊ฒฝ
  2. Pub-Sub ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์— Subscriber๊ฐ€ ์ฆ๊ฐ€ํ•ด๋„ Publisher๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  3. Batch ์„œ๋ฒ„๊ฐ€ 999๊ฐœ๋กœ ๋Š˜์–ด๋‚˜๊ฑฐ๋‚˜, 1๊ฐœ๋กœ ์ค„์–ด๋“ค์–ด๋„ ํ•˜๋‚˜์˜ Queue์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์†Œ๋น„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šค์ผ€์ผ out/in ์— ์ž์œ ๋กญ๋‹ค.


11. Virtual Topics ์‚ฌ์šฉ ๋ฐฉ๋ฒ• (with Spring Boot)

์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๋„ˆ๋ฌด๋‚˜ ๊ฐ„๋‹จํ•˜๋‹ค. out-of-the-box(๊บผ๋‚ด์„œ ๋ฐ”๋กœ ์“ฐ๋Š”) ๊ธฐ๋Šฅ์ด๊ธฐ ๋•Œ๋ฌธ์—
๊ธฐ์กด์˜ Topic ๋ฐฉ์‹์—์„œ Topic ์ด๋ฆ„๋งŒ Convention์— ๋งž๊ฒŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

์˜ˆ์ „์—๋Š” activemq.xml์— <DestinationInterceptor> ์„ค์ •๋„ ํ•ด์•ผ
ํ•ด๋‹น Topic ์ด๋ฆ„์œผ๋กœ ๋“ค์–ด์˜จ ๋ฉ”์‹œ์ง€๋ฅผ Interceptor๊ฐ€ ๊ฐ€๋กœ์ฑ„์„œ VirtualTopic์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์ง€๋งŒ,
์ด์ œ๋Š” ์ด ์„ค์ •๋งˆ์ € Default๊ฐ€ ๋˜์—ˆ๋‹ค.

11-1. Publisher์˜ ๊ฒฝ์šฐ

๊ธฐ์กด Topic ๋ฐฉ์‹์œผ๋กœ Topic์„ ์ƒ์„ฑํ•˜๋˜, Topic ์ด๋ฆ„ ์•ž์— VirtualTopic.์„ ๋ถ™์—ฌ์„œ
VirtualTopic.{Topic์ด๋ฆ„}์œผ๋กœ ์ƒ์„ฑํ•˜๋ฉด ๋์ด๋‹ค.

private JmsTemplate jmsTemplate;

// Message ์ƒ์„ฑ
jmsTemplate.convertAndSend(new ActiveMQTopic("VirtualTopic.ํ† ํ”ฝ์ด๋ฆ„", ์ƒ์„ฑํ•œ Message)) 

11-2. ๋‹จ์ผ ์„œ๋ฒ„ Subscriber์˜ ๊ฒฝ์šฐ

๋‹จ์ผ ์„œ๋ฒ„์˜ ๊ฒฝ์šฐ Topic์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ”๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์•„๋„ ๋˜๋ฏ€๋กœ, Topic ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ Listening ํ•œ๋‹ค.
์ด ๋•Œ, destination์„ Publisher๊ฐ€ ์ƒ์„ฑํ•œ Topic ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋์ด๋‹ค.

@JmsListener(destination = "VirtualTopic.{Topic์ด๋ฆ„}")
public void amazonMqNewsListener(@Payload MessageDto messageDto) {
    
    // ๋กœ์ง ์ฒ˜๋ฆฌ
}

11-3. ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ์ด ํ•„์š”ํ•œ Subscriber์˜ ๊ฒฝ์šฐ

๋ฐ˜๋“œ์‹œ jms์˜ pub-sub-domain ์„ค์ •์„ false๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

# application.yml

spring:
  jms:
    pub-sub-domain: false

๊ทธ๋ฆฌ๊ณ  N๊ฐœ์˜ ์„œ๋ฒ„๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚˜๋ˆ„์–ด ๋ฐ›์•„์•ผ ํ•˜๋ฏ€๋กœ ๊ธฐ์กด Topic ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ Listening ํ•˜๋˜,
์ด ๋•Œ, Publisher๊ฐ€ ์ƒ์„ฑํ•œ Topic ์ด๋ฆ„ ์•ž์— Consumer.{clientId}.๋ฅผ ๋ถ™์—ฌ์„œ
destination์„ Consumer.{clientId}.VirtualTopic.{Topic์ด๋ฆ„}์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋์ด๋‹ค.

๋งŒ์•ฝ clientId๋ฅผ ๋”ฐ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ํ•ด๋‹น ๋ถ€๋ถ„์— ์›ํ•˜๋Š” ์ด๋ฆ„์„ ๋„ฃ์–ด๋„ ๋ฌด๊ด€ํ•˜๋‹ค.

@JmsListener(destination = "Consumer.{clientId}.VirtualTopic.{Topic์ด๋ฆ„}")
public void amazonMqNewsListener(@Payload MessageDto messageDto) {

    // ๋กœ์ง ์ฒ˜๋ฆฌ
}

11-4. Topic ์ด๋ฆ„ ์ƒ์„ฑ ๊ทœ์น™์„ ๋ฐ”๊พธ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

์ด ๊ฒฝ์šฐ, activemq.xml ํŒŒ์ผ์— ์•„๋ž˜ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์„œ, name๊ณผ prefix๋ฅผ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.

<destinationInterceptors> 
  <virtualDestinationInterceptor> 
    <virtualDestinations> 
      <virtualTopic name=">" prefix="VirtualTopicConsumers.*." selectorAware="false"/>   
    </virtualDestinations>
  </virtualDestinationInterceptor> 
</destinationInterceptors>

์œ„์˜ ๋‚ด์šฉ์ด Default ์„ค์ •์ด๋ฉฐ, AmazonMQ์—์„œ๋Š” ํ•ด๋‹น ๋ถ€๋ถ„์ด ์ฃผ์„์ฒ˜๋ฆฌ๋œ ์ฑ„๋กœ activemq.xml์ด ์ƒ์„ฑ๋œ๋‹ค.

11-5. AmazonMQ์˜ activemq.xml ์„ค์ •

๊ธฐ์กด์—๋Š” AmazonMQ์—์„œ Virtual Destinations๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด
activemq.xml์— ์•„๋ž˜์— ๋™๊ทธ๋ผ๋ฏธ ์นœ ๋ถ€๋ถ„๊ณผ ๊ฐ™์ด useVirtualTopics="true"์™€
<destinationInterceptors>...</>๋ถ€๋ถ„์˜ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ–ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์ด ๋Œ€ํ™”์˜ AWS ์—”์ง€๋‹ˆ์–ด์— ์˜ํ•˜๋ฉด Virtual Destinations๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ enabled ๋œ ์ƒํƒœ๋กœ activemq.xml์ด ์ƒ์„ฑ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

We’ve changed the way default configurations are created. By default virtual destinations are now enabled (an empty element is no longer present in the default XML configuration). ์ฆ‰, Topic ๋ช…๋ช…๊ทœ์น™์„ ๋ณ€๊ฒฝํ•  ์ƒ๊ฐ์ด ์—†์œผ๋ฉด, ์•„๋ฌด๋Ÿฐ ์„ค์ •์ด ํ•„์š” ์—†๋‹ค.

๊ทธ์•ผ๋ง๋กœ out-of-the-box ๊ธฐ๋Šฅ์ด๋‹ค.


12. ๋งบ์œผ๋ฉฐ

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

ํŒ€์˜ ๋ชจ๋˜ํ•œ(?) ํ™˜๊ฒฝ ๋•๋ถ„์—, ์ฃผ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž๋กœ์„œ ๋‹ค์–‘ํ•œ ๊ฒฝํ—˜๋“ค์„ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ,
์ด๋ฒˆ์—๋Š” Message Broker์˜ ์‚ฌ์šฉ ๊ฒฝํ—˜๊ณผ ์ง€์‹์ด 1๋„ ์—†๋Š” ์ƒํƒœ์—์„œ
AmazonMQ์˜ Virtual Destinations๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์„ ๊ฒฝํ—˜ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์žฌ๋ฏธ์žˆ๊ณ  ์œ ์ตํ–ˆ๋‹ค :)

์–ธ์  ๊ฐ€ ๋” ํฌ๊ณ  ๋ณต์žกํ•œ ํ™˜๊ฒฝ์—์„œ Message Broker๋ฅผ ์‚ฌ์šฉํ•  ์ผ์ด ์ƒ๊ธด๋‹ค๋ฉด, ์ด ๊ฒฝํ—˜์ด ํฐ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

ํ˜น์‹œ๋‚˜ ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด, ๊ผญ ์ง€์ ํ•ด์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.


* Reference