Skip to content

Commit

Permalink
feat: 메시지 저장을 위한 MongoDB, MySQL 연동 #39
Browse files Browse the repository at this point in the history
  • Loading branch information
ypjun100 committed Aug 9, 2024
1 parent 1c6093d commit d66147c
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ public Message<?> preSend(@NonNull Message<?> message, @NonNull MessageChannel
String userId = String.valueOf(userEmail.hashCode());
String userName = String.valueOf(userId.hashCode());

// 테스트용 코드
if (userEmail.equals("[email protected]")) {
userId = "1";
userName = "로미오";
}
if (userEmail.equals("[email protected]")) {
userId = "2";
userName = "줄리엣";
}

// STOMP 패킷 헤더에 유저 ID와 유저 이름 추가
accessor.addNativeHeader("userId", userId);
accessor.addNativeHeader("userName", userName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.team13.servicechat.controller.ws;

import com.team13.servicechat.dto.ChatroomMessage;
import com.team13.servicechat.entity.ChatroomMessages;
import com.team13.servicechat.service.ChatroomMessagesService;
import com.team13.servicechat.service.ws.ChatroomService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
Expand All @@ -19,7 +21,8 @@
@RequiredArgsConstructor
public class ChatroomController {

private final ChatroomService service;
private final ChatroomService service; // 채팅방 웹 소켓 서비스
private final ChatroomMessagesService messagesService; // 채팅방 메시지 서비스

private final SimpMessagingTemplate template;

Expand Down Expand Up @@ -62,7 +65,16 @@ public void messageHandler(@DestinationVariable String chatroomId,
if (response.isPresent()) {
log.info("OUT : " + response);

// TODO: DB에 메시지 저장
// MySQL 서버에 메시지 저장
ChatroomMessages savedMessage = messagesService.saveMessage(ChatroomMessages.builder()
.chatroomsId(chatroomId)
.type(response.get().getType().toString())
.message(response.get().getMessage())
.senderUsersId(Long.parseLong(message.getSenderUserId()))
.build());

// MongoDB 서버에 해당 메시지의 ID 저장
service.addMessageIdInChatroom(chatroomId, savedMessage);

template.convertAndSend("/ws/subscribe/chatroom/" + chatroomId, response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
Expand All @@ -10,16 +11,17 @@

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Messages {
public class ChatroomMessages {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

private String chatroomsId;
private long senderUsersId;
private int type;
private String type;

@Column(columnDefinition = "TEXT")
private String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.util.List;

@Data
@Builder
@AllArgsConstructor
@Document(collection = "chatrooms")
public class Chatrooms {
Expand All @@ -25,5 +27,12 @@ public class Chatrooms {
private String lastMessage;

@Field("messages")
private List<Long> messages;
private List<Long> messageIds;

// 유저 목록에 유저 ID 저장
public void addUserId(Long userId) {
if (userId != null) {
usersIds.add(userId);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.team13.servicechat.repository;

import com.team13.servicechat.entity.ChatroomMessages;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ChatroomMessagesRepository extends CrudRepository<ChatroomMessages, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.team13.servicechat.repository;

import com.team13.servicechat.entity.Chatrooms;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ChatroomsRepository extends MongoRepository<Chatrooms, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.team13.servicechat.service;

import com.team13.servicechat.entity.ChatroomMessages;
import com.team13.servicechat.repository.ChatroomMessagesRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class ChatroomMessagesService {

private final ChatroomMessagesRepository repository;

// 특정 채팅방의 메시지 목록 가져오기
public List<ChatroomMessages> getAllMessagesByChatroomId(String chatroomId) {
return List.of();
}

// 채팅방 메시지 저장
public ChatroomMessages saveMessage(ChatroomMessages message) {
return repository.save(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.team13.servicechat.service;

import com.team13.servicechat.entity.Chatrooms;
import com.team13.servicechat.repository.ChatroomsRepository;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

@Service
@RequiredArgsConstructor
public class ChatroomsService {

private final ChatroomsRepository repository; // 채팅방 메시지 데이터를 저장하는 레포지토리

@PostConstruct
private void init() {
// 테스트 전용 채팅방이 존재하지 않는 경우, 채팅방 생성
if (!repository.existsById("test-chatroom")) {
repository.save(Chatrooms.builder()
.id("test-chatroom")
.postsId(0)
.messageIds(new ArrayList<>())
.usersIds(new ArrayList<>())
.build());
}
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.team13.servicechat.service.ws;

import com.team13.servicechat.dto.ChatroomMessage;
import com.team13.servicechat.entity.ChatroomMessages;
import com.team13.servicechat.entity.Chatrooms;
import com.team13.servicechat.repository.ChatroomsRepository;
import com.team13.servicechat.service.ChatroomMessagesService;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

Expand All @@ -10,21 +14,27 @@
@Service
public class ChatroomService {

// 채팅방 ID에 속한 유저 ID 목록
private final Map<String, List<String>> chatrooms;
// 채팅방 메시지 데이터를 저장하는 레포지토리
private final ChatroomsRepository repository;

public ChatroomService() {
chatrooms = new HashMap<>();
// 채팅방 목록 (repository와의 잦은 통신을 줄이기 위한 캐싱을 담당함)
private final HashSet<String> chatroomIds;

// 테스트 채팅방 개설
chatrooms.put("test-chatroom", new ArrayList<>());
public ChatroomService(ChatroomsRepository repository) {
this.repository = repository;

chatroomIds = new HashSet<>();
}

// 채팅방 입장
public Optional<ChatroomMessage> messageEnter(String chatroomId, ChatroomMessage message) {
// 존재하는 채팅방인 경우 메시지 발신자를 해당 채팅방에 입장시킴
if (chatrooms.containsKey(chatroomId)) {
chatrooms.get(chatroomId).add(message.getSenderUserId());
if (verifyChatroomId(chatroomId)) {
// DB에 해당 유저 정보 추가
Chatrooms chatroom = repository.findById(chatroomId).orElseThrow();

chatroom.addUserId(Long.parseLong(message.getSenderUserId()));
repository.save(chatroom);

return Optional.of(ChatroomMessage.builder()
.type(ChatroomMessage.MessageType.NOTICE)
Expand All @@ -38,7 +48,7 @@ public Optional<ChatroomMessage> messageEnter(String chatroomId, ChatroomMessage
// 채팅 메시지
public Optional<ChatroomMessage> messageTextAndImage(String chatroomId, ChatroomMessage message) {
// 채팅방이 존재하는 경우에만 메시지를 반환함(반환한다는 의미는 이 메시지를 DB에 저장한다는 의미임)
if (chatrooms.containsKey(chatroomId)) {
if (verifyChatroomId(chatroomId)) {
return Optional.of(message);
}

Expand All @@ -48,19 +58,25 @@ public Optional<ChatroomMessage> messageTextAndImage(String chatroomId, Chatroom
// 채팅방에서 유저 퇴장
public Optional<ChatroomMessage> messageExitUser(String chatroomId, ChatroomMessage message) {
// 나가려는 채팅방이 존재하는지 확인
if (chatrooms.containsKey(chatroomId)) {
if (verifyChatroomId(chatroomId)) {
// 채팅방 데이터를 가져옴
Chatrooms chatroom = repository.findById(chatroomId).orElseThrow();

// 해당 채팅방에서 유저가 포함되어 있는지 확인
int userIndex = chatrooms.get(chatroomId).indexOf(message.getSenderUserId());
int userIndex = chatroom.getUsersIds().indexOf(Long.valueOf(message.getSenderUserId()));

if (userIndex != -1) {
// 퇴장 유저 정보를 채팅방 내에서 제거
chatrooms.get(chatroomId).remove(message.getSenderUserId());
chatroom.getUsersIds().remove(userIndex);

// 만약 모든 유저가 채팅방에서 나간 경우, 해당 채팅방 제거
if (chatrooms.get(chatroomId).isEmpty()) {
chatrooms.remove(chatroomId);
if (chatroom.getUsersIds().isEmpty()) {
repository.deleteById(chatroomId);
chatroomIds.remove(chatroomId);

// TODO: DB에서 채팅방 삭제
// TODO: feign을 통한 다른 서비스들에게도 채팅방 삭제 메시지 전달

return Optional.empty();
}

return Optional.of(ChatroomMessage.builder()
Expand All @@ -73,7 +89,7 @@ public Optional<ChatroomMessage> messageExitUser(String chatroomId, ChatroomMess
return Optional.empty();
}

// 공동구매 완료
// TODO: 공동구매 완료
public Optional<ChatroomMessage> messageComplete(String chatroomId, ChatroomMessage message) {
/*
공동구매 완료 기능은 공동구매 게시자만 요청할 수 있으며, 게시자가 완료 요청시 해당 메시지를 전체 클라이언트에게 전송합니다.
Expand All @@ -83,4 +99,43 @@ public Optional<ChatroomMessage> messageComplete(String chatroomId, ChatroomMess

return Optional.empty();
}

// 채팅방에 해당 메시지 아이디 추가
public void addMessageIdInChatroom(String chatroomId, ChatroomMessages message) {
if (verifyChatroomId(chatroomId)) {
Chatrooms chatroom = repository.findById(chatroomId).orElseThrow();

// 해당 메시지를 저장한 뒤, 채팅방의 마지막 메시지를 해당 메시지로 설정
chatroom.getMessageIds().add(message.getId());
chatroom.setLastMessage(message.getMessage());

repository.save(chatroom);
}
}

// 존재하는 채팅방인지 확인
// 가장 먼저, 캐쉬에 저장된 채팅방 ID인지 확인한 후 캐쉬에 없으면, DB를 확인하여 존재하는 아이디인지 확인
private boolean verifyChatroomId(String chatroomId) {
log.info(repository.findAll());

if (chatroomIds.contains(chatroomId)) {
// 해당 채팅방의 ID가 캐시 채팅방 목록에 저장되어 있는 경우
return true;

} else if (repository.existsById(chatroomId)) {
// 채팅방의 ID가 캐시 채팅방에는 없으나 DB에 있는 경우 해당 아이디를 캐쉬에 저장
chatroomIds.add(chatroomId);
return true;
}

// 두 저장소 모두 해당 아이디가 없는 경우 false 반환
return false;
}

// TODO: 채팅방 내에 존재하는 유저인지 확인
// verifyChatroomId와 마찬가지로 캐시에서 유저 ID를 확인한 뒤, DB를 확인하여 유저 검증 진행
private boolean verifyUserIdInChatroom(String chatroomId, String userId) {
return false;
}

}
6 changes: 5 additions & 1 deletion service-chat/src/main/resources/templates/chat.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
<link rel="stylesheet" href="chat.css"/>
<script>
// 로그인 후 받은 로그인 토큰 쿠기값을 채팅 시에 매번 보내줘야 함
const LOGIN_TOKEN = 'LTK=eyJhbGciOiJIUzM4NCJ9.eyJlbWFpbCI6InlwanVuMTAwQG5hdmVyLmNvbSIsImV4cCI6MTcyNTQ1MjgzNX0.Vu7MrazHC3o5fxjcgPgqPfmp7uhP4fNpFL2EuihRbXccV1cInieheIxL66MEc7vE';
let LOGIN_TOKEN = 'LTK=eyJhbGciOiJIUzM4NCJ9.eyJlbWFpbCI6InlwanVuMTAwQG5hdmVyLmNvbSIsImV4cCI6MTcyNTQ1MjgzNX0.Vu7MrazHC3o5fxjcgPgqPfmp7uhP4fNpFL2EuihRbXccV1cInieheIxL66MEc7vE';
// 채팅방 ID ('test-chatroom-id'는 테스트용 채팅방)
const chatroomId = 'test-chatroom';
// 웹소켓 통신용 클라이언트 (해당 클라이언트를 바탕으로 웹소켓 통신을 진행하게 됨)
let client;

window.onload = function() {
if (localStorage.getItem("LTK")) {
LOGIN_TOKEN = localStorage.getItem("LTK").replaceAll("\n", "");
console.log(LOGIN_TOKEN);
}
/*
// 초기 채팅방 메시지 데이터 수신
// 해당 채팅방 내의 모든 메시지들을 불러옵니다.
Expand Down

0 comments on commit d66147c

Please sign in to comment.