Cloud Stream Configuration

์ž‘์„ฑ์ผ์‹œ2025-09-05 09:34

๊ฐœ์š”

์ด์ „์— ์Šคํ”„๋ง ํด๋ผ์šฐ๋“œ ์ŠคํŠธ๋ฆผ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์—ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์‹ค์ œ ์„œ๋น„์Šค ์ ์šฉ์„ ์œ„ํ•ด ์–ด๋–ค ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , ์–ด๋–ป๊ฒŒ ๋™์ž‘์ด ๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

Cloud Stream Properties

Spring Cloud Stream(์ดํ•˜ SCS)์—์„œ๋Š” ๋ฐ”์ธ๋”ฉ ๊ด€๋ จ ๊ตฌ์„ฑ์„ ์ž๋™ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ์˜ ๊ณผ์ •์œผ๋กœ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ์—ฐ๊ฒฐ ํ•  ํ•จ์ˆ˜ ์ •์˜(spring.cloud.function)
  2. Cloud Stream ๋ ˆ๋ฒจ์˜ ์ถ”์ƒํ™” ๋ฐ”์ธ๋”ฉ ์ •์˜(spring.cloud.stream.bindings)
  3. ๋ฉ”์‹œ์ง• ํ”Œ๋žซํผ ๋ฐ”์ธ๋” ์„ค์ •(spring.cloud.stream.{name})

1. ์—ฐ๊ฒฐ ํ•จ์ˆ˜ ์ •์˜

definition ํ”„๋กœํผํ‹ฐ(์ดํ•˜ definition)๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค. ์ •ํ™•ํžˆ๋Š” ํ•จ์ˆ˜์˜ ์ด๋ฆ„, ํŒŒ์ดํ”„๋ผ์ธ์„ ์ •์˜ ํ•œ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ ๋‚ด๋ถ€์ ์œผ๋กœ definition์ด ํ•ด์„๋  ๋•Œ ๋‘ ๊ฐ€์ง€์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

SCS์—์„œ๋Š” ์ถ”์ƒํ™”๋œ ํ•จ์ˆ˜๋ฅผ ๊ธฐ์ฐจ๋†€์ด์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๋ถ™์—ฌ์„œ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์ˆ˜ ๋„ ์žˆ๊ณ , ๋…๋ฆฝ์ ์œผ๋กœ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋งŒ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ๊ธฐ์–ตํ• ๊ฒƒ์€ ํ•จ์ˆ˜(ํ•œ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ํ•จ์ˆ˜๋“ , ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ํ•ฉ์ณ์„œ ๋งŒ๋“  ํ•จ์ˆ˜๋“ )๋Š” ;๋กœ ๊ตฌ๋ถ„๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋…๋ฆฝ์ ์œผ๋กœ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋งŒ ์ •์˜ํ•˜๊ธฐ

spring:
  cloud:
    funtion:
      definition: create-schedule;

์œ„ ๊ฒฝ์šฐ ์Šค์ผ€์ค„ ์ƒ์„ฑ(create-schedule)์ด๋ผ๋Š” ๋…๋ฆฝ์ ์ธ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋งŒ ๋™์ž‘ํ•œ๋‹ค.

ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜์—ฌ ํ•œ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ธฐ

spring:
  cloud:
    function:
      definition: create-schedule|alert-operation;

ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๋ ค๋ฉด, |ํŒŒ์ดํ”„ ๋ฌธ์ž์—ด(, ์‰ผํ‘œ๋„ ๊ฐ€๋Šฅ)๋กœ ํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ๋ฌถ์–ด ์ •์˜ํ•  ์ˆ˜์žˆ๋‹ค.

๋‹จ์ผ ํ•จ์ˆ˜
โ•ญโ”€โ”€โ”€โ”€ Function โ”€โ”€โ”€โ•ฎ
โ”‚ create-schedule โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
ํŒŒ์ดํ”„๋ผ์ธ ํ•จ์ˆ˜
โ•ญโ”€โ”€โ”€ Function1 โ”€โ”€โ”€โ•ฎ    โ•ญโ”€โ”€โ”€ Function2 โ”€โ”€โ”€โ•ฎ
โ”‚ create-schedule โ”‚ โ”€โ†’ โ”‚ alert-operation โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

ํŒŒ์ดํ”„๋ผ์ธ ํ•จ์ˆ˜๋Š” ์ฒ˜๋ฆฌํ•œ ํ•จ์ˆ˜์˜ ์ถœ๋ ฅ๊ฐ’๊ณผ ๋‹ค์Œ ํ•จ์ˆ˜์—์„œ ๋ฐ›์„ ์ž…๋ ฅ๊ฐ’์ด ๊ฐ™์•„์•ผํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

์—ฌ๋Ÿฌ์ข…๋ฅ˜์˜ ํ•จ์ˆ˜๋ฅผ ์ •์˜
spring:
  cloud:
    function:
      definition: create-schedule|alert-operation; modify-schedule
๊ฐ ํ•จ์ˆ˜ ๊ตฌ๋ถ„์ž(;)๋Š” ์•ž๋’ค๋กœ ๊ณต๋ฐฑ์ด ์žˆ์–ด๋„ ๋˜์ง€๋งŒ, ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ๋ถ„์ž(|)๋Š” ์•ž, ๋’ค๋กœ ๊ณต๋ฐฑ์ด ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค. ๋˜ํ•œ, spring.cloud.function.routing.enabled ์˜ต์…˜์ด ํ™œ์„ฑ๋˜ ๋œ๋‹ค๋ฉด definition์ด functionRouter๋กœ ๋ฎ์–ด์จ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
ํ•จ์ˆ˜ ๊ตฌ๋ถ„์ž(;)๋Š” ๊ตฌ๋ถ„์— ์“ฐ์ด๊ธฐ ๋•Œ๋ฌธ์—, create-schedule|alert-operation; modify-schedule;์ฒ˜๋Ÿผ ์„ค์ •ํ•˜๋ฉด ์‹ค์ œ๋กœ ๊ตฌ์„ฑ์‹œ์— ["create-schedule|alert-operation", "modify-schedule", ""] ์ฒ˜๋Ÿผ 3 ๊ฐœ์˜ ์„ค์ •์œผ๋กœ ์ธ์‹๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

2. ์ถ”์ƒํ™” ๋ฐ”์ธ๋”ฉ ์ •์˜

๋จผ์ € ์ถ”์ƒํ™” ๋ฐ”์ธ๋”ฉ์ด ๋ญ”์ง€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ง‘๊ณ  ๋„˜์–ด๊ฐ€์ž๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. SCS๋Š” ๋งŽ์€ ๋ฉ”์‹œ์ง• ํ”Œ๋žซํผ์„ ์ง€์›ํ•˜์ง€๋งŒ, ์‹ค์ œ ๊ทธ ๊ตฌํ˜„๊นŒ์ง€๋Š” ๊ด€์—ฌํ•˜์ง€ ์•Š์Œ.
  2. SCS๋Š” ๊ฐ ๊ตฌํ˜„์ฒด์ธ Binder์— ์ œ์–ด ๋„˜๊ธฐ๊ธฐ ์ „๊นŒ์ง€ ์Šคํ”„๋ง์— ๊ตฌ์„ฑ๋œ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ์—ฐ๊ฒฐ๋˜๋Š” ๋ฐ”์ธ๋”ฉ์„ ์„ค์ •๊ธฐ๋ฐ˜์œผ๋กœ ์ค€๋น„ํ•จ.

๋ฉ”์„ธ์ง• ํ”Œ๋žซํผ๊ณผ ์—ฐ๊ฒฐ๋˜๋ ค๋ฉด ๊ฐ Binder(RabbitMQ, Kafka)๋“ค๊ณผ ์—ฐ๊ฒฐ๋˜๋Š” ์ƒ์œ„๋ ˆ๋ฒจ ๊ตฌ์„ฑ์ด ํ•„์š”ํ•˜๊ณ , ์ด๋ฅผ SCS๊ฐ€ ์ œ๊ณตํ•œ๋‹ค.

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ     โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Funtion 1 โ”‚     โ”‚ Function 2 โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ•ฏ     โ•ฐโ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€
 โ•ญโ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€ Function โ”€โ”€โ”€โ”˜โ””โ”€โ”€โ”€โ•ฎ
 โ”‚   Spring Cloud Stream    โ”‚
 โ•ฐโ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ•ฏ
โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”œโ”€โ”€โ”€โ”€โ”€โ”€
     โ”‚โ”‚                โ”‚โ”‚ 
โ•ญโ”€ Kafka โ”€โ•ฎ    โ•ญโ”€โ”€โ”€ Rabbit MQ โ”€โ”€โ”€โ•ฎ
โ”‚  Topic  โ”‚    โ”‚ Exchange, Queue โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
application.yaml
spring:
  cloud:
    function:
      definition: create-schedule; modify-schedule
    stream:
      #SCS ์ถ”์ƒํ™”๋ฅผ ์œ„ํ•œ ๋ฐ”์ธ๋”ฉ
      bindings:
        create-schedule-in-0:
          destination: schedule-consume-exchange
          group: create-schedule-queue
        modify-schedule-in-0:
          destination: schedule-consume-exchange
          group: modify-schedule-queue

SCS์˜ ๋ฐ”์ธ๋”ฉ ์ถ”์ƒํ™”๋Š” ์‹ค์ œ ๊ทธ ๋ฐ”์ธ๋”ฉ๋Œ€์ƒ์ด ์–ด๋–ค ๋ฐฉํ–ฅ(์ƒ์‚ฐ ๋˜๋Š” ์†Œ๋น„)์ธ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ์„ค์ •์—๋Œ€ํ•œ ๊ตฌ์„ฑ์„ ๋ฐ›๋Š”๋‹ค. ์ถ”๊ฐ€์ ์ธ ์†์„ฑ์€ ๋ฐ”์ธ๋”ฉ ์ •๋ณด๋กœ์„œ ์ถ”์ƒํ™”๋˜๋ฉฐ ์•„๋ž˜์˜ ๋‚ด์šฉ์„ ํฌํ•จํ•œ๋‹ค:

  • destination: ๋ฐ”์ธ๋”๊ฐ€ ๋ฐ”์ธ๋“œํ•˜๋Š” ๋ธŒ๋กœ์ปค์—์„œ์˜ ๋ฌผ๋ฆฌ์ ์ธ ์ด๋ฆ„์„ ์˜๋ฏธํ•œ๋‹ค.
    • RabbitMq์˜ ๊ฒฝ์šฐ Exchange์˜ ์ด๋ฆ„์œผ๋กœ, Kafka์˜ ๊ฒฝ์šฐ Topic์˜ ์ด๋ฆ„์œผ๋กœ ์ •์˜ํ•œ๋‹ค.
  • group
    • ๊ทธ๋ฃน์˜ ๊ฒฝ์šฐ Consumer์—๊ฒŒ๋งŒ ์ ์šฉ๋˜๋ฉฐ, ์†Œ์†๋  ๋ฐ”์ธ๋”ฉ์˜ ๊ณ ์œ ํ•œ ์ด๋ฆ„์ด๋‹ค. ๋งŽ์€ ์ปจ์Šˆ๋จธ๊ฐ€ ๊ฐ™์€ ๊ทธ๋ฃน ๋‚ด์—์„œ ๊ตฌ๋…์„ ๊ณต์œ ํ•œ๋‹ค.
    • null, ๋นˆ ๋ฌธ์ž์—ด ๊ฐ’์€ ์ต๋ช…๊ทธ๋ฃน์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ ๊ณต์œ  ๋˜์ง€์•Š๋Š”๋‹ค.
    • ์ฆ‰ ๊ทธ๋ฃน์€ ๊ฐ ๋ฏธ๋“ค์›จ์–ด์—์„œ ์ปจ์Šˆ๋จธ๋ฅผ ๋ฌถ๋Š” ๊ทธ๋ฃน์œผ๋กœ ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค. RabbitMQ์˜ ๊ฒฝ์œ  Queue, Kafka์˜ ๊ฒฝ์šฐ Consumer Group๊ณผ ์—ฐ๊ฒฐ๋œ๋‹ค.
  • contentType
    • ์ด๋ฒคํŠธ ๋‚ด์—์„œ ์ด ๋ฐ”์ธ๋”ฉ์œผ๋กœ ์‚ฌ์šฉ๋  ์ฝ˜ํ…์ธ ์˜ ์œ ํ˜•์„ ์˜๋ฏธํ•œ๋‹ค. HTTP ์ŠคํŽ™์—์„œ ์‚ฌ์šฉ๋˜๋Š” MIME Type๊ณผ ๋™์ผํ•˜๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ application/json
    • ๋ฉ”์„ธ์ง€ ํ—ค๋”์— ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ด ๋ฐ”์ธ๋”ฉ์—์„œ ์‚ฌ์šฉ๋  ์ฝ˜ํ…์ธ  ์œ ํ˜•์„ ์ง€์ •ํ•œ๋‹ค.
  • bindier
    • ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฐ”์ธ๋”๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ ์ด ๋ฐ”์ธ๋”ฉ์—์„œ ์‚ฌ์šฉํ•  ๋ฐ”์ธ๋”๋ช…
    • ์˜ˆ: rabbit
  • consumer
    • ์ถ”๊ฐ€์ ์ธ ์ปจ์Šˆ๋จธ ํ”„๋กœํผํ‹ฐ (ConsumerProperties)
  • producer
    • ์ถ”๊ฐ€์ ์ธ ํ”„๋กœ๋“€์„œ ํ”„๋กœํผํ‹ฐ (ProducerProperties)

3. ๋ฉ”์‹œ์ง• ํ”Œ๋žซํผ ๋ฐ”์ธ๋” ์„ค์ •

SCS๋Š” ์‹ค์ œ ๋ฉ”์‹œ์ง• ํ”Œ๋žซํผ๊ณผ ์œ ์—ฐํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋˜๊ธฐ ์œ„ํ•ด Binder์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๋˜ํ•œ ๊ฐ ํ”Œ๋žซํผ ๋ฐ”์ธ๋” ๋ชจ๋“ˆ์€ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋ธŒ๋กœ์ปค์™€ ํ†ต์‹ ํ•˜๋ฉฐ, ์‹ค์ œ ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณตํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด RabbitMQ๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

application.yaml
spring:
  cloud:
    function:
      definition: create-schedule
    stream:
      #SCS ์ถ”์ƒํ™”๋ฅผ ์œ„ํ•œ ๋ฐ”์ธ๋”ฉ
      bindings:
        create-schedule-in-0:
          destination: create-schedule-exchange
          group: create-schedule-queue
          binder: rabbit
      rabbit:
        bindings:
          create-schedule-in-0:
            consumer:
              auto-bind-dlq: false

create-schedule(์Šค์ผ€์ค„ ์ƒ์„ฑ)์˜ ๊ฒฝ์šฐ DLQ(Dead Letter Queue)๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  Exchange์™€ Queue๋งŒ ์ง€์ •ํ•ด์ฃผ์—ˆ๋‹ค. SCS์—์„œ๋Š” ์ฑ„๋„์˜ ์ด๋ฆ„(*-out-0, *-in-0)์ด ์•ฝ์†๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋ฆ„์„ ์œ„ํ•ด ์ปค์Šคํ…€ ์„ค์ •์„ ํ•˜์ง€์•Š๋Š” ์ด์ƒ ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜์„ ๋”ฐ๋ผ์•ผํ•œ๋‹ค. ์ปจ์Šˆ๋จธ(Consumer)๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ *-in-0๋ฃฐ์„ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์ด ์ง€์ •ํ•˜์˜€๋‹ค.

๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •๋œ ๋ช…๋ช… ๋ฐฉ์‹์€ BindingFunctionProxyFactory#buildInputNameForIndex(int)์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
DLQ๊ฐ€ ํ™œ์„ฑํ™” ๋˜์ง€ ์•Š์€ ์„ค์ •
DLQ๊ฐ€ ํ™œ์„ฑํ™” ๋˜์ง€ ์•Š์€ Exchange
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Exchange โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ create-schedule-exchange โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
          โ†“  โ”‚โ”‚  โ†“ 
  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€ Queue โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
  โ”‚ create-schedule-queue โ”‚
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€//โ”€โ”€โ”€\\โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
          //     \\
      โ•ญโ”€โ”€โ”€โ”˜โ””โ•ฎ   โ•ญโ”˜โ””โ”€โ”€โ”€โ•ฎ
      โ”‚ App โ”‚   โ”‚ App โ”‚
      โ•ฐโ”€โ”€โ”€โ”€โ”€โ•ฏ   โ•ฐโ”€โ”€โ”€โ”€โ”€โ•ฏ

์œ„ ๋ฐ”์ธ๋”ฉ์˜ ํ๋ฆ„์„ ๊ฐ„๋žตํžˆ ๋ณธ๋‹ค๋ฉด ์œ„์™€ ๊ฐ™๋‹ค App์—์„œ๋Š” ์ฒ˜๋ฆฌํ•  ๋ฉ”์„ธ์ง€์˜ Exchange ์ •๋ณด๋ฅผ ์ •์˜(App ๊ตฌ๋™์‹œ ๋™์ผํ•œ ์ •๋ณด๊ฐ€ ์—†๋‹ค๋ฉด ์ƒ์„ฑ)ํ•œ๋‹ค. auto-bind-dlq ์˜ต์…˜์„ ํ™œ์„ฑํ™” ํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ Dead Letter๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” Exchange๋ฅผ DLX๋กœ ์‚ฌ์šฉ(์—†์œผ๋ฉด ์ƒ์„ฑ)ํ•œ๋‹ค.

dlq ์„ค์ • ํ™œ์„ฑํ™”
DLQ ๊ตฌ์„ฑ์„ ํ™œ์„ฑํ™” ํ•˜์˜€๋‹ค.

์œ„ ์ด๋ฏธ์ง€๋Š” auto-bind-dlq ์˜ต์…˜์„ ํ†ตํ•ด DLQ ๋ฐ”์ธ๋”ฉ์„ ์ง„ํ–‰ํ•˜์˜€๋‹ค. DLX๋Š” dead-letter-exchange ์˜ต์…˜์œผ๋กœ dlq ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š๋Š”์ด์ƒ, ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ํ๋“ค๊ณผ ํ•จ๊ป˜ DLX๊ฐ€ ๊ณต์œ ๋˜๋ฉฐ Queue์˜ ์ด๋ฆ„์ด Routing Key๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๊ฐ ๋ฐ”์ธ๋”์—์„œ๋Š” ์ถ”์ƒํ™”๋œ ์„ค์ •์„ ๊ตฌํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, spring.cloud.streamํ•˜์œ„์˜ ๊ฐœ๋ณ„ ์„ค์ •์€ ๋‹ค์Œ์˜ Properties๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค:

  • RabbitMQ: RabbitExtendedBindingProperties.class
  • Kafka: KafkaExtendedBindingProperties.class

์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ๊ฒฐํ•ฉํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์€ ํ•จ์ˆ˜ ์„ค์ •์—์„œ ์„ ์–ธํ•  ์ˆ˜ ์•˜๋‹ค.

์„ค์ •๊ธฐ๋ฐ˜ ๋‚ด๋ถ€ ๋™์ž‘

SCS์˜ ๋‹ค์–‘ํ•œ ๊ตฌ์„ฑ์„ ์ถ”์ƒํ™” ํ•˜๊ธฐ ์œ„ํ•ด ๋‚ด๋ถ€์ ์œผ๋กœ ์—ฌ๋Ÿฌ ์„ค์ •๋“ค์ด ์ด๋ฃจ์–ด์ง„๋‹ค.

์„ค์ • ์˜ˆ์‹œ
spring:
  cloud:
    function:
      definition: > 
        create-schedule,alert-operation; 
        create-user
    stream:
      bindings:
        create-schedule,alert-schedule-in-0:
          destination: create-schedule-exchange
          group: create-schedule-queue
          binder: rabbit
      ...

๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์€ ์„ค์ •์œผ๋กœ ์ ์šฉ๋œ๋‹ค๋ฉด, ์‹ค์ œ ๋ฉ”์„ธ์ง€ ๋ธŒ๋กœ์ปค์™€ ์˜ ์—ฐ๊ฒฐ์ด ์ด๋ฃจ์–ด์ง€๊ธฐ ๊นŒ์ง€ ๋‹ค์Œ์˜ ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค:

      Created!                 Created!
โ•ญโ”€โ”€ Function Bean โ”€โ”€โ•ฎ    โ•ญโ”€ Function Bean โ”€โ•ฎ
โ”‚ (create-schedule) โ”‚    โ”‚  alert-schedule โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

์œ„ ์ฒ˜๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด FunctionConfiguration์—์„œ ์„ค์ •ํ•˜์—ฌ ์ถ”์ƒํ™” ํ•จ์ˆ˜๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•˜๋Š” BindableFunctionProxyFactory๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋จผ์ € ์„ค์ •์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ•จ์ˆ˜ ๋‹จ์œ„๋กœ ์ง„ํ–‰ํ•œ๋‹ค:

FunctionConfiguration.java
@Override
public void afterPropertiesSet() throws Exception {
    //spring.cloud.function.definition ํ”„๋กœํผํ‹ฐ๋กœ ํ•จ์ˆ˜์ด๋ฆ„ ๊ฒฐ์ •.
    //spring.cloud.stream.function.routing.enabled ํ™œ์„ฑํ™” ์‹œ ๋ชจ๋‘ functionRouter๋กœ ๋ฎ์–ด์จ์ง 
    this.determineFunctionName(functionCatalog, environment);

    if (StringUtils.hasText(streamFunctionProperties.getDefinition())) {
        String[] functionDefinitions = this.filterEligibleFunctionDefinitions();
        //funtionDefinition = "create-schedule,alert-schedule"
        for (String functionDefinition : functionDefinitions) {
            //ํ•จ์ˆ˜ ์กฐํšŒ
            FunctionInvocationWrapper function = functionCatalog.lookup(functionDefinition);
            if (function != null) {
                if (function.isSupplier(
                ...

                AtomicReference<BindableFunctionProxyFactory> proxyFactory = new AtomicReference<>();
                
                ...
                
                //"create-schedule,alert-schedule_binding"์œผ๋กœ Bean ๋“ฑ๋ก
                ((GenericApplicationContext) this.applicationContext).registerBean(functionDefinition + "_binding",
                    BindableFunctionProxyFactory.class, proxyFactory::get);
            }
            else {
                logger.warn("The function definition '" + streamFunctionProperties.getDefinition() +
                        "' is not valid. The referenced function bean or one of its components does not exist");
            }
        }
    }

    this.createStandAloneBindingsIfNecessary(applicationContext.getBean(BindingServiceProperties.class));

}     

์—ฌ๊ธฐ์„œ functionDefinition + "_binding"์ด๋ผ๊ณ  ๋“ฑ๋ก๋œ BindableFunctionProxyFactory๋ฅผ ๋ฐ”์ธ๋”ฉ ๋นˆ์ด๋ผ๊ณ  ํ•œ๋‹ค. ๋ฐ”์ธ๋”ฉ ๋นˆ์€ ๋ฐ”์ธ๋”ฉ์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ , ์™ธ๋ถ€์—์„œ createAndBindInputs์œผ๋กœ ์ปจ์Šˆ๋จธ ๋ฐ”์ธ๋”ฉ์„, createAndBindOutputs์œผ๋กœ ํผ๋ธ”๋ฆฌ์…” ๋ฐ”์ธ๋”ฉ์„ ํ˜ธ์ถœํ•  ์ˆ˜์žˆ๋„๋ก ์ œ๊ณตํ•œ๋‹ค.

์œ„์—์„œ ์†Œ๊ฐœ ํ–ˆ๋˜ ๊ฐ ์—ญํ• ์„ ๋‚˜์—ดํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

SpringApplication.run()์—์„œ ๋ผ์ดํ”„ ์‚ฌ์ดํด ์‹คํ–‰ (RabbitMQ ๊ธฐ์ค€)
โ•ญโ”€ DefaultLifecycleProcessor โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚โ•ญโ”€ Binding Lifecycle Bean Start โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎโ”‚
โ”‚โ”‚ โ•ญโ”€ Bindable (Create And Bind)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎโ”‚โ”‚
โ”‚โ”‚ โ”‚โ•ญโ”€ BindingService โ”€โ”€โ•ฎ โ•ญโ”€ Provisioner โ”€โ”€โ”€โ”€โ”€โ•ฎโ”‚โ”‚โ”‚   
โ”‚โ”‚ โ”‚โ”‚ Request Binding   โ”‚ โ”‚ Request Provision โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚โ”‚ โ”‚โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏโ”‚โ”‚    (Provisioning)   
โ”‚โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏโ”‚โ”‚  Create Exchange, Queue 
โ”‚โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏโ”‚         โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ         โ”‚
              โ–ผ                                            โ”‚
  โ•ญโ”€ Binder (Lifecycle Start) โ”€โ”€โ•ฎ                          โ–ผ
  โ”‚โ•ญโ”€ AMQP Listener Container โ”€โ•ฎโ”‚           โ•ญโ”€โ”€โ”€โ”€โ”€ RabbitMQ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ 
  โ”‚โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”‚โ”‚           โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚
  โ”‚โ”‚  โ”‚ Consumer Instance 1 โ”œโ”€โ”€โ”€โ”€โ”€ Binding! โ”€โ”€โ–ถโ”‚ Queue 1 โ– โ– โ– โ–  Exchange 1 โ”‚โ”‚  
  โ”‚โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ”‚โ”‚           โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚ 
  โ”‚โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”‚โ”‚           โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚
  โ”‚โ”‚  โ”‚ Consumer Instance 2 โ”œโ”€โ”€โ”€โ”€โ”€ Binding! โ”€โ”€โ–ถโ”‚ Queue 1 โ– โ– โ– โ–  Exchange 1 โ”‚โ”‚
  โ”‚โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ”‚โ”‚           โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚
  โ”‚โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”‚โ”‚           โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚
  โ”‚โ”‚  โ”‚ Consumer Instance 3 โ”œโ”€โ”€โ”€โ”€โ”€ Binding! โ”€โ”€โ–ถโ”‚ Queue 1 โ– โ– โ– โ–  Exchange 1 โ”‚โ”‚
  โ”‚โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ”‚โ”‚           โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚
  โ”‚โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏโ”‚           โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ 
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
     RabbitMessageChannelBinder
                

Exchange์™€ Queue ๋‚ด๋ถ€์ ์œผ๋กœ ์„ค์ •์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋กœ๋น„์ €๋‹ํ•˜๊ณ , ๊ตฌ์„ฑ๋œ ํ•จ์ˆ˜์™€ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. AMQP Listener Conainer์—์„œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Consumer Instance (AsyncMessageProcessingConsumer)๋ฅผ ํ†ตํ•ด RabbitMQ์™€ ํ†ต์‹ ํ•œ๋‹ค. ๋ฉ”์„ธ์ง€ ์ˆ˜์‹  ์ปดํฌ๋„ŒํŠธ(SimpleMessageListenerContainer)๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ BlockingQueueConsumer๋ฅผ ํ†ตํ•ด TransactionTemplate์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์˜ ์›์ž์„ฑ์„ ๋ณด์žฅํ•˜๋ฉฐ, ๋™์‹œ์„ฑ ์ œ์–ด๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ปจ์Šˆ๋จธ ์ธ์Šคํ„ด์Šค๋Š” ๋ฐ”์ธ๋”ฉ์ด ๋œ ์ดํ›„๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ๊ด€๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค.

Copyright ยฉ 2019-2025 Alloc ยท MIT License