Skip to content

Commit 420b227

Browse files
authored
[refactor] 알림 도메인 전면 수정 (#331)
* [refactor] Notification 도메인 v1, v2 모두 존재하는 상태 * [refactor] Notification 도메인 : v1 제거 후 v2만 남긴 상태 * [refactor] Notification 도메인 : v1 제거, v2만 존재 + 코드 정리 * [refactor] 코드 수정 및 불필요 코드 제거 * [refactor] 알림 도메인 v2 : 이름에서 V2 제거 * [fix] Optional 처리 * [refactoring] : 알림 도메인 - 사전등록 취소 알림 추가 * [refactoring] : 알림 도메인 - flyway 파일 추가
1 parent a7412ef commit 420b227

33 files changed

Lines changed: 703 additions & 812 deletions

backend/src/main/java/com/back/api/auth/service/AuthService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.time.LocalDate;
44

55
import org.apache.commons.lang3.StringUtils;
6+
import org.springframework.context.ApplicationEventPublisher;
67
import org.springframework.security.crypto.password.PasswordEncoder;
78
import org.springframework.stereotype.Service;
89
import org.springframework.transaction.annotation.Transactional;
@@ -22,6 +23,7 @@
2223
import com.back.domain.auth.entity.RefreshToken;
2324
import com.back.domain.auth.repository.ActiveSessionRepository;
2425
import com.back.domain.auth.repository.RefreshTokenRepository;
26+
import com.back.domain.notification.systemMessage.NotificationMessage;
2527
import com.back.domain.store.entity.Store;
2628
import com.back.domain.user.entity.User;
2729
import com.back.domain.user.entity.UserActiveStatus;
@@ -49,6 +51,7 @@ public class AuthService {
4951
private final ActiveSessionRepository activeSessionRepository;
5052
private final AuthStore authStore;
5153
private final StoreService storeService;
54+
private final ApplicationEventPublisher eventPublisher;
5255
private final OAuthExchangeCodeStore codeStore;
5356

5457
@Transactional
@@ -89,6 +92,14 @@ public AuthResponse signup(SignupRequest request) {
8992

9093
JwtDto tokens = loginAsSingleDevice(savedUser);
9194

95+
// 알림 메시지 발행
96+
eventPublisher.publishEvent(
97+
NotificationMessage.signUp(
98+
savedUser.getId(),
99+
savedUser.getNickname()
100+
)
101+
);
102+
92103
return buildAuthResponse(savedUser, tokens);
93104
}
94105

backend/src/main/java/com/back/api/notification/controller/NotificationApi.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ ApiResponse<Void> markAsRead(
4747
})
4848
ApiResponse<Void> markAllAsRead(
4949
);
50+
5051
}

backend/src/main/java/com/back/api/notification/controller/NotificationController.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818

1919
@RestController
2020
@RequiredArgsConstructor
21-
@RequestMapping("/api/v1/notifications")
21+
@RequestMapping("/api")
2222
public class NotificationController implements NotificationApi {
2323

2424
private final NotificationService notificationService;
2525
private final HttpRequestContext httpRequestContext;
2626

2727
@Override
28-
@GetMapping
28+
@GetMapping("/v2/notifications")
2929
public ApiResponse<List<NotificationResponseDto>> getNotifications(
3030
) {
3131
Long userId = httpRequestContext.getUserId();
@@ -39,8 +39,7 @@ public ApiResponse<List<NotificationResponseDto>> getNotifications(
3939
/**
4040
* 읽지 않은 알림 개수 조회
4141
*/
42-
@Override
43-
@GetMapping("/unread-count")
42+
@GetMapping("/v2/notifications/unread-count")
4443
public ApiResponse<UnreadCountResponseDto> getUnreadCount(
4544
) {
4645
Long userId = httpRequestContext.getUserId();
@@ -51,8 +50,7 @@ public ApiResponse<UnreadCountResponseDto> getUnreadCount(
5150
/**
5251
* 개별 알림 읽음 처리
5352
*/
54-
@Override
55-
@PatchMapping("/{notificationId}/read")
53+
@PatchMapping("/v2/notifications/{notificationId}/read")
5654
public ApiResponse<Void> markAsRead(
5755
@PathVariable Long notificationId
5856
) {
@@ -65,8 +63,7 @@ public ApiResponse<Void> markAsRead(
6563
/**
6664
* 전체 알림 읽음 처리
6765
*/
68-
@Override
69-
@PatchMapping("/read-all")
66+
@PatchMapping("/v2/notifications/read-all")
7067
public ApiResponse<Void> markAllAsRead() {
7168
Long userId = httpRequestContext.getUserId();
7269
notificationService.markAllAsRead(userId);

backend/src/main/java/com/back/api/notification/dto/NotificationResponseDto.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,24 @@
44

55
import com.back.domain.notification.entity.Notification;
66

7-
import io.swagger.v3.oas.annotations.media.Schema;
8-
9-
@Schema(description = "알림 조회 응답용 DTO")
107
public record NotificationResponseDto(
118
Long id,
12-
String type, // enum name
13-
String typeDetail,
9+
String type,
1410
String title,
15-
String message,
16-
boolean isRead,
11+
String content,
1712
LocalDateTime createdAt,
13+
Boolean isRead,
1814
LocalDateTime readAt
1915
) {
2016
public static NotificationResponseDto from(Notification notification) {
17+
2118
return new NotificationResponseDto(
2219
notification.getId(),
23-
notification.getType().name(),
24-
notification.getTypeDetail().name(),
20+
notification.getType().getFrontType().name(),
2521
notification.getTitle(),
26-
notification.getMessage(),
27-
notification.isRead(),
22+
notification.getContent(),
2823
notification.getCreateAt(),
24+
notification.isRead(),
2925
notification.getReadAt()
3026
);
3127
}

backend/src/main/java/com/back/api/notification/listener/NotificationEventListener.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,17 @@ public void handleNotificationMessage(NotificationMessage message) {
3737
.orElseThrow(
3838
() -> new NoSuchElementException("ID " + message.getUserId() + "에 해당하는 사용자가 존재하지 않습니다."))
3939
)
40-
.type(message.getNotificationType())
41-
.typeDetail(message.getTypeDetail())
40+
.type(message.getNotificationVar())
4241
.domainName(message.getDomainName())
43-
.domainId(message.getDomainId())
44-
.title(message.getTitle())
45-
.message(message.getMessage())
42+
.title(message.getNotificationVar().getTitle())
43+
.content(message.getNotificationVar().formatMessage(message.getContext()))
4644
.isRead(false)
4745
.build();
4846

4947
notificationRepository.save(notification);
5048

5149
// 웹소켓으로 실시간 알림 전송
52-
sendNotificationViaWebSocket(message.getUserId(), notification);
50+
v2_sendNotificationViaWebSocket(message.getUserId(), notification);
5351

5452
} catch (Exception e) {
5553
}
@@ -61,7 +59,7 @@ public void handleNotificationMessage(NotificationMessage message) {
6159
* @param userId 대상 사용자 ID
6260
* @param notification 전송할 알림 엔티티
6361
*/
64-
private void sendNotificationViaWebSocket(Long userId, Notification notification) {
62+
private void v2_sendNotificationViaWebSocket(Long userId, Notification notification) {
6563

6664
boolean isOnline = sessionManager.isUserOnline(userId);
6765

backend/src/main/java/com/back/api/payment/payment/service/PaymentService.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import com.back.api.payment.order.service.OrderService;
1010
import com.back.api.payment.payment.client.PaymentClient;
11-
import com.back.domain.payment.order.entity.V2_Order;
1211
import com.back.api.payment.payment.dto.request.PaymentConfirmCommand;
1312
import com.back.api.payment.payment.dto.request.V2_PaymentConfirmRequest;
1413
import com.back.api.payment.payment.dto.response.PaymentConfirmResult;
@@ -17,8 +16,9 @@
1716
import com.back.api.payment.payment.dto.response.V2_PaymentConfirmResponse;
1817
import com.back.api.queue.service.QueueEntryProcessService;
1918
import com.back.api.ticket.service.TicketService;
20-
import com.back.domain.notification.systemMessage.OrderSuccessMessage;
19+
import com.back.domain.notification.systemMessage.NotificationMessage;
2120
import com.back.domain.payment.order.entity.Order;
21+
import com.back.domain.payment.order.entity.V2_Order;
2222
import com.back.domain.payment.payment.entity.ApproveStatus;
2323
import com.back.domain.ticket.entity.Ticket;
2424
import com.back.global.error.code.PaymentErrorCode;
@@ -96,11 +96,10 @@ public PaymentReceiptResponse confirmPayment(
9696

9797
// 알림 메시지 발행
9898
eventPublisher.publishEvent(
99-
new OrderSuccessMessage(
99+
NotificationMessage.paymentSuccess(
100100
userId,
101-
orderId,
102-
order.getAmount(),
103-
eventTitle
101+
eventTitle,
102+
order.getAmount()
104103
)
105104
);
106105

backend/src/main/java/com/back/api/payment/payment/service/PaymentTransactionService.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.back.api.payment.payment.dto.response.V2_PaymentConfirmResponse;
99
import com.back.api.queue.service.QueueEntryProcessService;
1010
import com.back.api.ticket.service.TicketService;
11-
import com.back.domain.notification.systemMessage.OrderSuccessV2Message;
11+
import com.back.domain.notification.systemMessage.NotificationMessage;
1212
import com.back.domain.payment.order.entity.OrderStatus;
1313
import com.back.domain.payment.order.entity.V2_Order;
1414
import com.back.domain.payment.order.repository.V2_OrderRepository;
@@ -109,13 +109,12 @@ public V2_PaymentConfirmResponse handleSuccess(
109109
userId
110110
);
111111

112-
// 알림 발행
112+
// 알림 메시지 발행
113113
eventPublisher.publishEvent(
114-
new OrderSuccessV2Message(
114+
NotificationMessage.paymentSuccess(
115115
userId,
116-
orderId,
117-
order.getAmount(),
118-
ticket.getEvent().getTitle()
116+
ticket.getEvent().getTitle(),
117+
order.getAmount()
119118
)
120119
);
121120

backend/src/main/java/com/back/api/preregister/service/PreRegisterService.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import com.back.api.s3.service.S3PresignedService;
1616
import com.back.domain.event.entity.Event;
1717
import com.back.domain.event.repository.EventRepository;
18-
import com.back.domain.notification.systemMessage.PreRegisterDoneMessage;
18+
import com.back.domain.notification.systemMessage.NotificationMessage;
1919
import com.back.domain.preregister.entity.PreRegister;
2020
import com.back.domain.preregister.entity.PreRegisterStatus;
2121
import com.back.domain.preregister.repository.PreRegisterRepository;
@@ -121,9 +121,8 @@ public PreRegisterResponse register(Long eventId, Long userId, PreRegisterCreate
121121
deleteSmsVerificationFlag(request.phoneNumber());
122122

123123
eventPublisher.publishEvent(
124-
new PreRegisterDoneMessage(
124+
NotificationMessage.preRegisterDone(
125125
userId,
126-
savedPreRegister.getId(),
127126
event.getTitle()
128127
)
129128
);
@@ -158,6 +157,15 @@ public void cancel(Long eventId, Long userId) {
158157
}
159158

160159
preRegister.cancel();
160+
161+
eventPublisher.publishEvent(
162+
NotificationMessage.preRegisterCancel(
163+
userId,
164+
eventRepository.findById(eventId)
165+
.map(Event::getTitle)
166+
.orElse("제목 없음")
167+
)
168+
);
161169
}
162170

163171
public boolean isRegistered(Long eventId, Long userId) {
@@ -172,7 +180,7 @@ public List<PreRegisterResponse> getMyPreRegister(Long userId) {
172180
.map(preRegister -> {
173181
Event event = preRegister.getEvent();
174182
String imageUrl = null;
175-
if(event.getImageUrl() != null && !event.getImageUrl().isBlank()) {
183+
if (event.getImageUrl() != null && !event.getImageUrl().isBlank()) {
176184
imageUrl = s3PresignedService.issueDownloadUrl(event.getImageUrl());
177185
}
178186

backend/src/main/java/com/back/api/queue/service/QueueEntryProcessService.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
import com.back.api.ticket.service.TicketService;
2121
import com.back.domain.event.entity.Event;
2222
import com.back.domain.event.repository.EventRepository;
23-
import com.back.domain.notification.systemMessage.QueueEntriesMessage;
24-
import com.back.domain.notification.systemMessage.QueueExpiredMessage;
23+
import com.back.domain.notification.systemMessage.NotificationMessage;
2524
import com.back.domain.queue.entity.QueueEntry;
2625
import com.back.domain.queue.entity.QueueEntryStatus;
2726
import com.back.domain.queue.repository.QueueEntryRedisRepository;
@@ -72,9 +71,8 @@ public void processEntry(Long eventId, Long userId) {
7271
publishEnteredEvent(queueEntry); // 입장 처리 웹소켓 이벤트 발행
7372

7473
eventPublisher.publishEvent(
75-
new QueueEntriesMessage(
74+
NotificationMessage.queueEntered(
7675
userId,
77-
enqueue.getId(),
7876
eventRepository.findById(eventId)
7977
.map(Event::getTitle)
8078
.orElse("제목 없음")
@@ -320,7 +318,7 @@ public void expireEntry(Long eventId, Long userId) {
320318
}
321319

322320
queueEntry.expire();
323-
QueueEntry deque = queueEntryRepository.save(queueEntry);
321+
QueueEntry expired = queueEntryRepository.save(queueEntry);
324322

325323
try {
326324
queueEntryRedisRepository.removeFromEnteredQueue(eventId, userId);
@@ -332,9 +330,8 @@ public void expireEntry(Long eventId, Long userId) {
332330
publishExpiredEvent(queueEntry); // 만료 처리 웹소켓 이벤트 발행
333331

334332
eventPublisher.publishEvent(
335-
new QueueExpiredMessage(
333+
NotificationMessage.queueExpired(
336334
userId,
337-
deque.getId(),
338335
eventRepository.findById(eventId)
339336
.map(Event::getTitle)
340337
.orElse("제목 없음")
@@ -364,15 +361,6 @@ public void expireWaitingAndEnteredEntry(Long eventId, Long userId) {
364361

365362
publishExpiredEvent(queueEntry); // 만료 처리 웹소켓 이벤트 발행
366363

367-
eventPublisher.publishEvent(
368-
new QueueExpiredMessage(
369-
userId,
370-
deque.getId(),
371-
eventRepository.findById(eventId)
372-
.map(Event::getTitle)
373-
.orElse("제목 없음")
374-
)
375-
);
376364
}
377365

378366
@Transactional

backend/src/main/java/com/back/api/queue/service/QueueShuffleService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.back.api.event.service.EventService;
1313
import com.back.domain.event.entity.Event;
1414
import com.back.domain.event.entity.EventStatus;
15+
import com.back.domain.notification.systemMessage.NotificationMessage;
1516
import com.back.domain.queue.entity.QueueEntry;
1617
import com.back.domain.queue.entity.QueueEntryStatus;
1718
import com.back.domain.queue.repository.QueueEntryRedisRepository;
@@ -20,6 +21,7 @@
2021
import com.back.domain.user.repository.UserRepository;
2122
import com.back.global.error.code.QueueEntryErrorCode;
2223
import com.back.global.error.exception.ErrorException;
24+
import com.back.global.event.EventPublisher;
2325

2426
import lombok.RequiredArgsConstructor;
2527
import lombok.extern.slf4j.Slf4j;
@@ -30,6 +32,7 @@
3032
* 자동으로 섞기 + 관리자 전용 수동 섞기
3133
* 공정한 대기열 생성 로직 논의 필요 -> 현재는 SecureRandom 이용한 랜덤 섞기 로직으로 구현
3234
*/
35+
3336
@Service
3437
@RequiredArgsConstructor
3538
@Slf4j
@@ -39,6 +42,7 @@ public class QueueShuffleService {
3942
private final QueueEntryRedisRepository queueEntryRedisRepository;
4043
private final UserRepository userRepository;
4144
private final EventService eventService;
45+
private final EventPublisher eventPublisher;
4246

4347
@Transactional
4448
public void shuffleQueue(Long eventId, List<Long> preRegisteredUserIds) {
@@ -57,6 +61,8 @@ public void shuffleQueue(Long eventId, List<Long> preRegisteredUserIds) {
5761
saveToRedis(eventId, shuffledUserIds);
5862
saveToDatabase(event, users, shuffledUserIds);
5963

64+
publishQueueWaitingNotifications(event, shuffledUserIds);
65+
6066
event.changeStatus(EventStatus.QUEUE_READY);
6167

6268
}
@@ -126,4 +132,17 @@ private void saveToDatabase(Event event, List<User> users, List<Long> shuffledUs
126132
}
127133
queueEntryRepository.saveAll(entries);
128134
}
135+
136+
private void publishQueueWaitingNotifications(Event event, List<Long> shuffledUserIds) {
137+
for (int i = 0; i < shuffledUserIds.size(); i++) {
138+
Long userId = shuffledUserIds.get(i);
139+
Long rank = (long)(i + 1);
140+
141+
eventPublisher.publishEvent(
142+
NotificationMessage.queueWaiting(userId, event.getTitle(), rank)
143+
);
144+
}
145+
}
146+
129147
}
148+

0 commit comments

Comments
 (0)