챗팅 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개의 댓글

관련 채용 정보