챗팅 NoSql로 개선하기

이상혁·2024년 4월 23일
0

문제 상황

채팅을 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를 사용할 수 있는 준비를 해준다.

MongDB entity

chat entity

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 값으로 표현할 수 있다.

chatRoom entity

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이 없기 때문에 딱 정해진 많큼만 초대를 할 수 있는 것이 아니라 유연하게 채팅 멤버들을 초대할 수 있다.

Repository

chatRepository

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중 어느 데이터베이스가 더 좋고 나쁨은 없다. 내가 구현하고 하는 기능의 데이터가 어떠한 형태로 저장이 되는 것이 유리한 지에 따라 판단해서 선택하는 것이 좋다.

profile
개발 공부 하기 위해 만든 블로그

0개의 댓글