내가 주로 담당하는 기능들은 이벤트로 무료 주식을 나눠주는 기능이다. 그런데 이 무료 주식들에 대해 취소해달라는 CS가 생각보다 많이 들어온다 (소수점 주식을 보는게 거추장스럽거나, 다른 증권사 직원들인 경우). 이 CS 때문에 컨텍스트 스위칭도 자주 발생하고, cs 직군 분들도 요청 후 기다려야 하는 시간이 발생하니 서로에게 좋지 않았다. 그래서 여러 이벤트들로 받은 주식들을 한번에 조회하고, cs 직군 분들이 취소도 할 수 있는 기능을 만들려고 했다.
문제는 각 이벤트들이 만든 사람들이 다르다보니 일괄적으로 조회/취소 기능을 붙이기가 쉽지 않았다. 그래서 핸들러 패턴을 이용해봤다.
이벤트로 받은 리워드 조회/회수 컨트롤러
@RestApiController
class EventRewardController(
private val eventStockManager: EventStockManager
) {
...
@ApiOperation("이벤트로 받은 리워드 회수")
@PostMapping("/stock")
fun cancelReward(@PathVariable userId: Long, @PathVariable promotionCode: String): ApiResponse<Boolean> {
eventStockManager.cancelReward(userId, promotionCode)
...
}
}
보면 EventStockManager를 호출하고 있다.
EventStockManager
@Component
class EventStockManager(
private val eventStockHandlers: List<EventStockHandler>,
...
) {
...
fun cancelReward(userId: Long, promotionCode: String) {
...
}
}
EventStockManager를 보면 List로 Handler들을 받고 있다.
EventStockHandler
interface EventStockHandler {
fun getEventStocks(userDto: UserDto): List<StockRewardDto>
fun cancel(userDto: UserDto, promotionCode: String)
fun isResponsiblePromotion(promotionCode: String): Boolean
...
}
EventStockHandler는 이런 인터페이스를 구현해두고 각각의 이벤트마다 EventStockHandler를 구현하게 했다.
StockProphecyEventStockController
@Component
class StockProphecyEventStockHandler(
val stockProphecyRewardService: StockProphecyRewardService,
val usaStockPromotionAdaptor: UsaStockPromotionAdaptor,
val stockProphecyCacheEvictor: StockProphecyCacheEvictor,
) : EventStockHandler {
...
override fun getEventStocks(userDto: UserDto): List<StockRewardDto> =
stockProphecyRewardService...
}
override fun cancel(userDto: UserDto, promotionCode: String) {
...
}
override fun isResponsiblePromotion(promotionCode: String): Boolean =
promotionCode.contains(PROMOTION_CODE)
}
이런식으로 구현하니 내가 만들지 않은 서비스에 관해서도 다른 사람들이 붙이기가 수월했다. 이렇게 다양한 구현체들이 이미 만들어진 상황에서 공통으로 묶고 싶을때 핸들러 패턴을 이용하면 통일된 방식으로 내가 다룰 수 있다.