채팅을 MySql로 구현을 하였다.
MySql은 관계형 데이터베이스로 테이블 형식으로 이루어져있다.
column과 row으로 이루어졌다.
그래서 고정된 스키마를 가지고 있다.
그러다보니 딱 정해진 수 만큼에 인원 만을 초대해 채팅을 할 수 밖에 없고 채팅의 데이터를 유연하게 담지 못 하고 정해진 대로만 담을 수 있는 단점이 존재를 했다.
특히, NoSql로 개선을 해야 겠다고 생각했던 부분은 바로 채팅에 채팅 멤버를 초대하는 것이다.
mySql에 경우 딱 정해진 수 많큼만 멤버를 초대해야 한다.
NoSql로 하게 되면 정해진 수에 상관이 없이 원하는 멤버 만큼 채팅에 초대를 할 수 있다.
NoSql은 관계형DB와 달리 정해진 데이터 구조가 없기 때문에 데이터를 유연하게 저장하는 것이 가능하다.
그래서 데이터가 구조가 달라도 같은 collection에 document로 저장이 되는 것이 가능하다.
나는 NoSql 중 MongoDB를 사용해서 개선을 하고자 한다.
개선을 하고자 하는 부분은 엔티티와 Repository를 MongoDB로 바꿔어 주면 개선이 가능하다.
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
의존성 추가로 mongoDB를 사용할 수 있는 준비를 해준다.
package com.github.riset_backend.chating.entity.chat;
import com.github.riset_backend.chating.dto.MongoMessageSendDto;
import com.github.riset_backend.login.employee.entity.Employee;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "chat")
public class MongoChat {
@Id
private String id;
private String roomId;
private String msg;
private List<Long> members;
private Employee sender;
private List<String> filesName;
private LocalDateTime date;
public MongoChat(MongoMessageSendDto mongoMessageSendDto, LocalDateTime date, Employee sender) {
this.roomId = mongoMessageSendDto.getRoomId();
this.msg = mongoMessageSendDto.getMsg();
this.members = mongoMessageSendDto.getMembers();
this.sender = sender;
this.date = date;
this.filesName = mongoMessageSendDto.getBase64File();
}
}
채팅 데이터의 엔티티이다.
@Document(collection = "chat")를 통해서 데이터베이스의 chat이라는 컬렉션에 document를 저장한다는 의미이다.
기존의 채팅 엔티티와의 차이가 있다면 List를 사용할 수 있다는 것이다.
List 저장을 할 수 있어서 이 채팅을 보낼을 때 받는 멤버가 누군이지 column을 계속 추가하지 않고 하나의 key 값으로 표현할 수 있다.
package com.github.riset_backend.chating.entity.chatRoom;
import com.github.riset_backend.login.employee.entity.Employee;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "chatRoom")
public class MongoChatRoom {
@Id
private String id;
private List<Employee> members;
private LocalDateTime date;
public MongoChatRoom(List<Employee> members, LocalDateTime date) {
this.members = members;
this.date = date;
}
}
채팅방의 엔티티이다.
이 채팅방의 엔티티에서 column이 없기 때문에 딱 정해진 많큼만 초대를 할 수 있는 것이 아니라 유연하게 채팅 멤버들을 초대할 수 있다.
package com.github.riset_backend.chating.repository.chat;
import com.github.riset_backend.chating.entity.chat.MongoChat;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface MongoChatRepository extends MongoRepository<MongoChat, String> {
List<MongoChat> findAllByRoomId(String roomId);
List<MongoChat> findByRoomIdAndMsgContaining(String roomId, String msg);
}
package com.github.riset_backend.chating.repository.chatRoom;
import com.github.riset_backend.chating.entity.ChatRoomEmployee;
import com.github.riset_backend.chating.entity.chatRoom.ChatRoom;
import com.github.riset_backend.login.employee.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface ChatRoomRepository extends JpaRepository<ChatRoom, Long> {
Optional<ChatRoom> findByChatRoomIdAndChatRoomEmployeesContains(Long chatRoomId, Employee employee);
}
chat 엔티티와 chatRoom 엔티티를 기반으로 한 mongoDB에 repository이다. jpa와 마찬가지로 사용이 가능하다.
이를 토대로 controller와 service의 repository를 바꿔주기만 하면 된다.
그리고 데이터를 저장을 해보면 아래와 같이 저장이 된다.
채팅 멤버를 관계형 DB에서는 저장을 할 수 없는 List로 저장을 해서 유연하게 대처할 수 있다.
관계형 DB, NoSql중 어느 데이터베이스가 더 좋고 나쁨은 없다. 내가 구현하고 하는 기능의 데이터가 어떠한 형태로 저장이 되는 것이 유리한 지에 따라 판단해서 선택하는 것이 좋다.