์๋ก
์ต๊ทผ ๋ง์ดํฌ๋ก๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ์๋น์ค์ ์ ์ ์นด์ดํธ๋ฅผ ํ์ํ ๊น ํด๋ดค๋ค. (์ค๋ก์ง ํฅ๋ฏธ ์์ฃผ๋ก..)
์ฒ์์๋ MeterRegistry ์ Counter ๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ ํด๋น ๋ฉ์๋์ ์ถ๊ฐํด์ฃผ๋ ์์ผ๋ก ๊ตฌํํ์๋ค.
๊ตฌํํ๊ณ ๋ณด๋ ์ ์ ์ด๊ฑฐ counter ๋ถ๋ถ์์ ์๋ฌ๊ฐ ๋๋ฉด ์ด๋ป๊ฒ ๋์ง? ์ค์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ๋ ๋ฌด๊ดํ๊ฒ ์งํ๋์ผ ํ๋๊ฑด๋ฐ
๋ผ๋ ์๊ฐ์ด ๋ค์ด์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์์๋ณด๋ ์ฐจ์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์๊ฐํด๋ดค๋ค.
์ฒ์์๋ ์ธํฐ์ ํฐ์ afterCompletion ์ ์ฌ์ฉํด๋ดค์ผ๋, lateinit ์ ์ด์ฉํ๊ณ ํด๋ ๊ณ์ ์ด๊ธฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํด์ ์ด๋ฆฌ์ ๋ฆฌ ํด๋ณด๋ค๊ฐ ๊ฒฐ๊ตญ์ ์ด๋ ๋คํ ํด๊ฒฐ์ฑ ์ ๋ชป ์ฐพ๊ณ (์ฝํ๋ฆฐ๊ณผ ์คํ๋ง์ ๋ํ ์ง์์ด ๋ถ์กฑ…), ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฐพ๋ค๊ฐ EventListener ์ ํตํด ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค๊ณ ํ์ฌ ๋์ ํด๋ดค๋ค.
1. Events ์์ฑ
-
ํด๋น ์๋น์ค์์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํฌ ๋ ์ฌ์ฉํ๋ Events ํด๋์ค
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
object Events { private var eventPublisher: ApplicationEventPublisher? = null private val log = LoggerFactory.getLogger(this.javaClass) fun publishEvent(event: Any) { when (eventPublisher) { null -> { log.warn("no eventPublisher, so don't publish an event.") } else -> { eventPublisher!!.publishEvent(event) } } } fun setEventPublisher(eventPublisher: ApplicationEventPublisher) { Events.eventPublisher = eventPublisher } }
- object ํค์๋๋ฅผ ํตํด ์ฑ๊ธํค ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค
- ApplicationEventPublisher ์ ํตํด ์ด๋ฒคํธ๋ฅผ ํผ๋ธ๋ฆฌ์ฑ
- eventPublisher ์ null ์ธ ์ํ์ด๋ฏ๋ก ํผ๋ธ๋ฆฌ์ฑ ํ๊ธฐ ์ ์ setEventPublisher ์ ํด์ค์ผ ํจ
2. EventsInitializer ์์ฑ
-
Events ์์ eventPublisher ์ ์ฃผ์ ํด์ฃผ๊ธฐ ์ํด InitializingBean ์ ์ฌ์ฉ
1 2 3 4 5 6 7 8
@Configuration class EventsInitializer(val context: ApplicationContext) { @Bean fun initEvents(): InitializingBean { return InitializingBean { Events.setEventPublisher(context) } } }
- ์ด๋ ๊ฒ ํ๋ฉด Spring Bean Lifecycle ์ ์ํด InitializingBean ์ด ์คํ์ด ๋๊ณ , Events ๊ฐ์ฒด์ eventPublisher ์ด ์ฃผ์ ์ด ๋๋ค.
3. Events ๋ฅผ ์ฌ์ฉํ Service ๊ฐ์ฒด
-
Events ๋ ํ์ํ ๊ณณ์์ ์ฌ์ฉํ๋ฉด ๋์ง๋ง, ์ด๋ฒ์๋ ์๋น์ค ๊ฐ์ฒด์์ ์ฌ์ฉ
1 2 3 4 5 6 7 8
@Service class ListService(private val provider: DataProvider) { fun callCachedData(status: String, req: RequestDTO) : PageInfo<DTO>? { Events.publishEvent(MakedKey(status, req)) return provider.get(MakedKey(status, req)) } }
- Events.publishEvent() ๋ฅผ ํตํด ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํจ๋ค
4. EventListener ์ ํตํด ์ด๋ฒคํธ ํธ๋ค๋ฌ ๊ตฌํ
-
์ด๋ฒคํธ๋ฅผ ๋ฐ์์ ์์ผฐ์ผ๋, ๋ฐ์์ํจ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ ๊ณณ์ ๊ตฌํํด๋ณด์
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@Component class EventMetricHandler(private val meterRegistry: MeterRegistry) { private val log = LoggerFactory.getLogger(javaClass) @Async @EventListener(value = [MakedKey::class]) fun handle(evt: MakedKey) { val tags = listOf( Tag.of("status", evt.status) ) val counter = meterRegistry.counter("counter", tags) counter.increment() log.info("increment metric: tag-{}", tags) } }
- EventListener ์ ํตํด ๋ฐ์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
- status ๋ผ๋ tag ๋ฅผ ์์ฑํด์ฃผ๊ณ ๊ฐ tag ์ ๋ํ ์นด์ดํธ๋ฅผ ์ฆ๊ฐ์์ผ์ค๋ค.
- ์์ ๊ฒฝ์ฐ์์๋ list ๋ผ๋ ์กฐํ์ ๋ํด์ ์นด์ดํธ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ ํธ๋์ญ์
์ ์ ๊ฒฝ์ธ ํ์๊ฐ ์์ง๋ง, ์ ์ฅ ํน์ ์ญ์ ํ์ ๋์ ๋ํ ๋ฉํธ๋ฆญ์ ํ ๊ฒฝ์ฐ
@TransactionalEventListener
์ ์ฌ์ฉํ๋ฉด ๋๋ค. ํด๋น ์ด๋ ธํ ์ด์ ์ ๊ฒฝ์ฐ ํธ๋์ญ์ ์ปค๋ฐ ์ด์ ์ดํ ๋ฑ์ ๊ดํ ์ค์ ์ ํ ์ ์๋ค. - ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด์
@Async
์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํด์ฃผ์.
5. @EnableAsync ์ถ๊ฐ
-
์ด๋ป๊ฒ ๋ณด๋ฉด ๋น๋๊ธฐ๋ก ํ๋ค๋ ์์ ์์ ์ฒ์ ์ถ๊ฐํด์คฌ์ด์ผ ํ ๊ฒ ๊ฐ์ ์ค์ ์ด์ง๋ง…
1 2 3 4 5 6 7
@SpringBootApplication @EnableAsync class SampleEventApplication fun main(args: Array<String>) { runApplication<SampleEventApplication>(*args) }
@SpringBootApplication
์ด๋ ธํ ์ด์ ์๋ฆฌ์@EnableAsync
๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๋๋ค.
๊ฒฐ๋ก
- ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ๋ Events ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํด์ ํ๋ ๋ฐฉ๋ฒ์ ์ข์ ๋ฐฉ๋ฒ์ธ ๊ฒ ๊ฐ๊ณ ์ข์๋ณด์ธ๋ค. ๋ค๋ง, ์คํ๋ง์ ์ฌ์ฉํ๋ฉด์ ์ข์ ๊ธฐ๋ฅ์ ์ ๋ง ๋ง์๋ฐ, ๋ชจ๋ฅด๋ ๊ฒ๋ ์ ๋ง ๋ง๋ค๋ ๊ฒ๊ณผ ๊ทธ๋งํผ ์์์ผ ํ๋ ๊ฒ๋ ์ ๋ง ๋ง๋ค๋ ๊ฒ์ ํ ๋๋ง๋ค ๋๋ผ๋ ๊ฒ ๊ฐ๋ค.