현재 kafka를 통하여 message에서
이 값을 받고 createdAt 이라는 필드에 대해 값을 생성하여 mongoDB에 저장
feed의 경우에는 mediaUrl이 추가로 존재
feed, chatting의 경우는 List 형식으로 receiver 값 필요
알림 클릭 시 적절한 페이지로 이동하기 위해 이에 대한 uuid/code값도 추가 필요
@Bean
public ConsumerFactory<String, NotificationFeedRequestDto> notificationFeedConsumerFactory() {
Map<String, Object> props = new HashMap<>();
// Kafka 브로커 주소 설정
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
// Consumer 그룹 ID 설정
// 같은 그룹의 consumer들은 토픽의 파티션을 분배하여 메시지를 소비
props.put(ConsumerConfig.GROUP_ID_CONFIG, "notification-consumer");
// 메시지 키의 역직렬화 설정 (String 타입)
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
// 메시지 값의 역직렬화 설정 (JSON -> KafkaFeedRequestDto)
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
// JSON을 자바 객체로 변환할 때 신뢰할 패키지 설정 ("*"는 모든 패키지 허용)
props.put(JsonDeserializer.TRUSTED_PACKAGES, "*");
//props.put(JsonDeserializer.TYPE_MAPPINGS, "lookids.commentread.comment.adaptor.in.kafka.vo.CommentEventVo");
// Consumer Factory 생성
// StringDeserializer: 키를 String으로 역직렬화
// ErrorHandlingDeserializer: 역직렬화 실패 시 에러 처리
// JsonDeserializer: JSON을 KafkaFeedRequestDto로 변환
return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(),
new ErrorHandlingDeserializer<>(new JsonDeserializer<>(NotificationFeedRequestDto.class, false)));
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, NotificationFeedRequestDto> notificationFeedEventListenerContainerFactory() {
// @KafkaListener 어노테이션이 사용할 Factory 설정
ConcurrentKafkaListenerContainerFactory<String, NotificationFeedRequestDto> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(notificationFeedConsumerFactory());
return factory;
}
notificationFeedEventListenerContainerFactory
ConcurrentKafkaListenerContainerFactory
**를 생성@KafkaListener
메서드가 사용할 컨테이너 팩토리ConsumerFactory
**를 설정하여 컨슈머 동작과 역직렬화 방식 정의notificationFeedConsumerFactory
@KafkaListener
**를 통해 실행되는 컨슈머가 메시지를 처리하는 데 필요한 설정을 제공bootstrapServers
**를 통해 브로커와 통신할 수 있도록 설정notification-consumer
**라는 그룹으로 설정, 같은 그룹에 속한 컨슈머들은 토픽의 파티션을 나누어 처리 (현재는 모든 알림 컨슈머가 한개의 그룹으로 설정됨)TRUSTED_PACKAGES
: JSON 직렬화 시 신뢰할 패키지 설정, **"*"
**로 설정해 모든 패키지의 JSON 직렬화를 허용notification-favorite-consumer
**에서만 처리되고, 다른 그룹에 영향을 주지 않음@Document(collection = "notification")
@Getter
@NoArgsConstructor
public class Notification {
@Id
private ObjectId id;
private String senderUuid;
private List<String> receiverUuidList;
private String title;
private String content;
private String mediaUrl;
private String feedCode;
private String roomId;
private NotificationType type; // 직렬화, 역직렬화? -> Enum으로 변경
private LocalDateTime createdAt; // 값은 dto에서 추가, 가져올때는 LocalDateTime으로 변환해서 가져오기
@Builder
public Notification(
ObjectId id,
String senderUuid,
List<String> receiverUuidList,
String title,
String content,
String mediaUrl,
String feedCode,
String roomId,
NotificationType type,
LocalDateTime createdAt
) {
this.id = id;
this.senderUuid = senderUuid;
this.receiverUuidList =receiverUuidList;
this.title = title;
this.content = content;
this.mediaUrl = mediaUrl;
this.feedCode = feedCode;
this.roomId = roomId;
this.type = type;
this.createdAt = createdAt;
}
}
mongoDB로 문서를 저장하기 위한 필드, 각 알림에 따라 필요한 필드값만 db 로 저장할 수 있는 등의 유연한 처리가 가능
아래부터는 각 알림을 위한 dto 이며 위에서부터 follow, feed, favorite, comment, chatting
@Getter
@NoArgsConstructor
public class NotificationFollowRequestDto {
private String senderUuid;
private String receiverUuid;
private String type;
@Builder
public NotificationFollowRequestDto(
String senderUuid,
String receiverUuid,
String type
) {
this.senderUuid = senderUuid;
this.receiverUuid = receiverUuid;
this.type = type;
}
}
Getter
@NoArgsConstructor
public class NotificationFeedRequestDto {
private String senderUuid;
private List<String> receiverUuidList;
private String content;
private String mediaUrl;
private String feedCode;
private String type;
@Builder
public NotificationFeedRequestDto(
String senderUuid,
List<String> receiverUuidList,
String content,
String mediaUrl,
String feedCode,
String type
) {
this.senderUuid = senderUuid;
this.receiverUuidList = receiverUuidList;
this.content = content;
this.mediaUrl = mediaUrl;
this.feedCode = feedCode;
this.type = type;
}
@Getter
@NoArgsConstructor
public class NotificationFavoriteRequestDto {
private String senderUuid;
private String receiverUuid;
private String feedCode;
private String type;
@Builder
public NotificationFavoriteRequestDto(
String senderUuid,
String receiverUuid,
String feedCode,
String type
) {
this.senderUuid = senderUuid;
this.receiverUuid = receiverUuid;
this.feedCode = feedCode;
this.type = type;
}
}
@Getter
@NoArgsConstructor
public class NotificationCommentRequestDto {
private String senderUuid;
private String receiverUuid;
private String content;
private String feedCode;
private String type;
@Builder
public NotificationCommentRequestDto(
String senderUuid,
String receiverUuid,
String content,
String feedCode,
String type
) {
this.senderUuid = senderUuid;
this.receiverUuid = receiverUuid;
this.content = content;
this.feedCode = feedCode;
this.type = type;
}
}
@Getter
@NoArgsConstructor
public class NotificationChattingRequestDto {
private String senderUuid;
private List<String> receiverUuidList;
private String roomId;
private String content;
private String mediaUrl; // url 정보 대부분 지우고 마지막의 몇 글자 정보만 받음
private String type;
@Builder
public NotificationChattingRequestDto(
String senderUuid,
List<String> receiverUuidList,
String roomId,
String content,
String mediaUrl,
String type
) {
this.senderUuid = senderUuid;
this.receiverUuidList = receiverUuidList;
this.roomId = roomId;
this.content = content;
this.mediaUrl = mediaUrl;
this.type = type;
}
}