사용자 경험 향상을 위해 새로운 이벤트(댓글, 작업 할당 등) 발생 시 사용자가 즉시 인지할 수 있는 실시간 알림은 필수적이었습니다. 이를 위해 몇 가지 기술을 고려했습니다.
SSE 연결 자체를 위한 기본 인프라(SseEmitter 생성, 관리, 생명주기 처리)는 Spring MVC의 기능을 활용하여 비교적 수월하게 구축했습니다. (EmitterService 와 관련 컨트롤러/서비스 로직)
SSE 통로를 만들고 나니 진짜 고민이 시작되었습니다. "댓글 생성", "작업 할당", "승인 요청" 등 알림이 필요한 다양한 비즈니스 로직이 완료되었을 때, 어떻게 알림 시스템에 이를 알리고 SSE로 메시지를 보낼 것인가? 였습니다.
가장 단순한 방법은 알림이 필요한 모든 서비스(CommentService, TaskService 등)에 NoticeService (실제 SSE 전송 담당)를 직접 주입하고 호출하는 것입니다.
// 예시: CommentService 내부에 직접 NoticeService 호출 (안티 패턴)
@Service
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository commentRepository;
private final NoticeService noticeService; // <<< 직접 주입
public Comment createComment(...) {
Comment savedComment = commentRepository.save(...);
// ... 알림 대상자 찾고, 메시지 만들고 ...
noticeService.sendNotification(targetUserId, "new_comment", data); // <<< 직접 호출
return savedComment;
}
}
하지만 이 방식은 다음과 같은 명확한 문제점이 있었습니다.
NoticeService)에 직접 의존하게 됩니다. 알림 시스템의 변경이 모든 관련 서비스에 영향을 미칠 수 있습니다.CommentService의 주 책임은 댓글 관리인데, 알림 전송 책임까지 가지게 됩니다 (SRP 위배).NoticeService를 호출하는 코드가 반복될 수 있습니다."서비스 로직 안에 이벤트 발행 로직이 너무 크게 들어가는 것 같아서, 이게 맞나 싶다" 는 제 고민의 핵심이었습니다.
핵심 서비스와 알림 시스템을 분리하기 위한 해결책으로 이벤트 기반 아키텍처(Event-Driven Architecture) 를 도입하기로 결정했습니다. 즉, 어떤 일이 발생하면 "이벤트"를 발행하고, 이 이벤트에 관심 있는 다른 컴포넌트가 이를 받아서 처리하는 방식입니다. 여기서 몇 가지 구현 방식을 고민했습니다.
CommentService) 완료 후, ApplicationEventPublisher를 주입받아 명시적으로 애플리케이션 이벤트(예: CommentCreatedEvent)를 발행합니다. 별도의 NotificationEventListener가 이 이벤트를 받아 처리합니다.