Conversation
- UserSummary 클래스 분리
개요팔로우 알림 기능을 이벤트 기반 아키텍처로 리팩토링했습니다. 변경 사항
시퀀스 다이어그램sequenceDiagram
participant FollowService as FollowService
participant EventPublisher as ApplicationEventPublisher
participant FollowEventListener as FollowEventListener
participant NotificationDispatcher as NotificationDispatcher
participant NotificationRepository as NotificationRepository
participant SseEmitterService as SseEmitterService
FollowService->>FollowService: follow(follower, follow)
FollowService->>EventPublisher: publishEvent(FollowEvent)
Note over EventPublisher: Transaction commit 대기
EventPublisher->>FollowEventListener: handleFollowEvent(FollowEvent)<br/>(AFTER_COMMIT phase)
FollowEventListener->>NotificationDispatcher: dispatch(follower, follow)
NotificationDispatcher->>NotificationDispatcher: createFollowNotification(follow, follower)
NotificationDispatcher->>NotificationRepository: save(notification)
NotificationDispatcher->>SseEmitterService: sendNotification(NotificationFollowResponse)
SseEmitterService-->>SseEmitterService: SSE 전송 완료
예상 코드 리뷰 난이도🎯 3 (보통) | ⏱️ ~25분 관련될 수 있는 PR
시
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/main/java/team/wego/wegobackend/notification/application/dispatcher/NotificationDispatcher.javasrc/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationFollowResponse.javasrc/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationItemResponse.javasrc/main/java/team/wego/wegobackend/notification/application/dto/response/UserSummary.javasrc/main/java/team/wego/wegobackend/user/application/FollowService.javasrc/main/java/team/wego/wegobackend/user/application/event/FollowEvent.javasrc/main/java/team/wego/wegobackend/user/application/listener/FollowEventListener.java
💤 Files with no reviewable changes (1)
- src/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationItemResponse.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/team/wego/wegobackend/notification/application/dto/response/UserSummary.java (2)
src/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationFollowResponse.java (1)
Getter(8-30)src/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationItemResponse.java (2)
Getter(12-98)Getter(30-40)
🔇 Additional comments (6)
src/main/java/team/wego/wegobackend/user/application/event/FollowEvent.java (1)
5-7: 이벤트 레코드 구조가 적절합니다.팔로우 이벤트를 표현하는 간단하고 명확한 레코드입니다. 불변 객체로 설계되어 이벤트의 안정성이 보장됩니다.
src/main/java/team/wego/wegobackend/user/application/FollowService.java (2)
41-41: 이벤트 발행을 위한 의존성이 올바르게 주입되었습니다.ApplicationEventPublisher가 적절하게 추가되어 이벤트 기반 아키텍처를 지원합니다.
66-67: 이벤트 리스너 설정이 올바르게 구성되어 있습니다.FollowEventListener의 handleFollowEvent 메서드가
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)으로 정확하게 구성되어 있어, 팔로우 트랜잭션 커밋 후에만 알림이 발송됩니다. 이벤트 발행을 통한 리팩토링으로 팔로우 서비스의 책임이 명확해졌으며, 동시성 문제를 효과적으로 방지하고 있습니다.src/main/java/team/wego/wegobackend/notification/application/dto/response/UserSummary.java (1)
6-13: 내부 클래스를 독립적인 DTO로 적절하게 추출했습니다.
UserSummary를 별도 클래스로 분리하여 팔로우 도메인에서 재사용할 수 있게 되었습니다. 불변 객체로 설계되어 있고 구조가 명확합니다.src/main/java/team/wego/wegobackend/notification/application/dto/response/NotificationFollowResponse.java (1)
8-30: 팔로우 알림을 위한 응답 DTO가 적절하게 구현되었습니다.
NotificationFollowResponse는 팔로우 알림에 필요한 데이터를 명확하게 표현하고 있으며, 추출된UserSummary를 활용하여 일관성을 유지합니다.NotificationTypeMapper를 통한 타입 변환도 기존 패턴을 따르고 있습니다.src/main/java/team/wego/wegobackend/user/application/listener/FollowEventListener.java (1)
16-21:dispatch()메서드에 이미@Transactional주석이 있습니다검증 결과,
NotificationDispatcher.dispatch(User follower, User follow)메서드는@Transactional어노테이션으로 이미 표시되어 있으므로 트랜잭션 경계는 올바르게 처리됩니다. AFTER_COMMIT 단계 이후에도 새로운 트랜잭션 컨텍스트가 생성되어 알림 영속화가 안전합니다.다만, 코드 일관성 측면에서 개선 가능한 부분이 있습니다. 같은 클래스의 다른
dispatch()메서드들은 SSE 발송 결과를 확인하여 로깅하지만(boolean ok = sseEmitterService.sendNotificationIfConnected(...)), 팔로우 알림 발송 메서드는 반환값을 확인하지 않습니다. SSE 발송 실패를 명시적으로 처리하도록 일관성을 맞추는 것이 좋습니다.
| @Transactional | ||
| public void dispatch( | ||
| User follower, | ||
| User follow | ||
| ) { | ||
|
|
||
| Notification notification = Notification.createFollowNotification(follow, follower); | ||
|
|
||
| notificationRepository.save(notification); | ||
|
|
||
|
|
||
| sseEmitterService.sendNotificationIfConnected(follow.getId(), new NotificationFollowResponse(notification, follower)); | ||
|
|
||
| } |
There was a problem hiding this comment.
트랜잭션 전파 설정이 기존 메서드와 일관되지 않습니다.
기존의 다른 dispatch 메서드들(26-61, 63-95번 줄)은 모두 @Transactional(propagation = Propagation.REQUIRES_NEW)를 사용하여 독립적인 트랜잭션에서 알림을 저장합니다.
새로 추가된 메서드가 기본 전파 설정(REQUIRED)을 사용하면 호출자의 트랜잭션에 참여하게 되어, 호출 컨텍스트에 따라 예상치 못한 동작이 발생할 수 있습니다. 이벤트 리스너가 AFTER_COMMIT으로 설정되어 있더라도, 일관성을 위해 동일한 전파 설정을 사용하는 것이 좋습니다.
🔎 일관된 트랜잭션 전파 설정 적용
- @Transactional
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
public void dispatch(
User follower,
User follow
) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Transactional | |
| public void dispatch( | |
| User follower, | |
| User follow | |
| ) { | |
| Notification notification = Notification.createFollowNotification(follow, follower); | |
| notificationRepository.save(notification); | |
| sseEmitterService.sendNotificationIfConnected(follow.getId(), new NotificationFollowResponse(notification, follower)); | |
| } | |
| @Transactional(propagation = Propagation.REQUIRES_NEW) | |
| public void dispatch( | |
| User follower, | |
| User follow | |
| ) { | |
| Notification notification = Notification.createFollowNotification(follow, follower); | |
| notificationRepository.save(notification); | |
| sseEmitterService.sendNotificationIfConnected(follow.getId(), new NotificationFollowResponse(notification, follower)); | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/team/wego/wegobackend/notification/application/dispatcher/NotificationDispatcher.java
around lines 97 to 110, the dispatch method uses the default @Transactional
(REQUIRED) whereas the other dispatch methods (lines 26-61 and 63-95) use
@Transactional(propagation = Propagation.REQUIRES_NEW); update this method to
use @Transactional(propagation = Propagation.REQUIRES_NEW) so notification save
runs in an independent transaction consistent with the other methods, and ensure
the appropriate Propagation import is present.
📝 Pull Request
📌 PR 종류
해당하는 항목에 체크해주세요.
✨ 변경 내용
기존 팔로우 알림이 Service 트랜잭션 -> 이벤트 기반 분리된 트랜잭션으로 변경되었습니다.
UserSummary 이너 클래스 분리하여 팔로우 도메인에서 재활용가능하도록 조치하였습니다.
🔍 관련 이슈
해당 PR이 해결하는 이슈가 있다면 연결해주세요.
🧪 테스트
변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.
프론트 통합 테스트 진행 예정
🚨 확인해야 할 사항 (Checklist)
PR을 제출하기 전에 아래 항목들을 확인해주세요.
🙋 기타 참고 사항
리뷰어가 참고하면 좋을 만한 추가 설명이 있다면 적어주세요.
Summary by CodeRabbit
릴리스 노트
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.