만능 도구는 없다, 적절한 선택은 있다: Spring Statemachine으로 완성한 알림 2.0
알림 상태 관리를 직접 구현하다가 Spring Statemachine으로 전환한 이유와 교훈.
카카오뱅크의 알림 발송 시스템은 접수, 예약, 필터링, 발송, 재처리까지 여러 단계를 거치며, 각 메시지의 상태를 정확하게 관리해야 한다. RECEIVED, SENT_SUCCEEDED, SENT_FAILED 같은 상태가 명확히 정의되어야 하고, 전이마다 발송 전달이나 실패 알림 같은 후속 작업도 함께 수행돼야 했다.
복잡한 전이 규칙을 다루기 위해 FSM(Finite State Machine) 을 직접 구현하는 방식도 검토했지만, 상태별 전이 경로를 Map으로 관리하고, 전이 전후 로직을 모두 직접 작성해야 해서 규모가 커질수록 유지보수 부담이 커졌다. 프레임워크 의존성은 줄일 수 있지만, 그만큼 상태 관리의 체계성과 확장성은 직접 책임져야 했다.
이후 Spring Statemachine 을 도입해 상태와 이벤트를 enum 으로 정의하고, StateMachineConfigurerAdapter 기반으로 초기 상태, 전이, Guard, Action을 구성했다. 특히 Guard 와 Action 을 그대로 노출하지 않고 내부 인터페이스로 한 번 감싸서 DIP(Dependency Inversion Principle) 를 지키고, 프레임워크 교체 가능성을 열어두는 방식으로 결합도를 낮췄다.
구현에서는 이벤트 메시지의 Header 에 메시지 ID 같은 필요한 데이터를 실어 보내고, Guard나 Action에서 이를 꺼내 사용하는 구조를 택했다. 또한 상태 머신 인스턴스는 Redis 로 영속화해 분산 환경에서도 상태를 일관되게 유지하도록 했고, StateMachineService 와 RedisPersistingStateMachineInterceptor 를 함께 사용했다.
도입 결과 상태 전이 로직은 훨씬 명확해지고 개발 생산성도 높아졌지만, 프레임워크 자체의 학습 비용과 제약도 분명했다. 특히 기본 TTL이 없어 상태 머신 인스턴스가 명시적으로 삭제되지 않으면 Redis에 계속 남는 문제처럼, 프레임워크가 제공하지 않는 운영 책임은 별도로 관리해야 했다.
결론은 분명하다. Spring Statemachine은 복잡한 상태 관리를 체계화하는 강력한 도구지만, 모든 상황에 정답은 아니다. 핵심은 기능의 많고 적음이 아니라, 현재 문제의 규모와 맥락에 맞는 도구를 고르는 일이다.
이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.
요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.
