Spring/Spring Stomp

[Stomp] Spring Boot with React 채팅 서버 : 1. Entity 디자인

noahkim_ 2022. 3. 2. 00:47

이번에 하는 토이프로젝트에서 DM 기능을 구현하는 파트를 맡게 되었다. 

약 한달간 일정을 소모하여 여기저기서 찾아보고 강의도 들어가며 구현은 어느정도 완성이 되었다.

해당 토이프로젝트는 JPA를 사용하였으나 동작원리를 공부하고자 DDL은 직접 생성하였다. (도메인 파트별로 sql문 있음)

 

일단 도메인 객체 디자인부터

0. ERD Diagram

  • 진한 글씨는 PK
  • 테이블간 선으로 연결된 컬럼은 FK
  • many to many : (ChatRoom - ChatRoom_Members - User)

 

1. ChatRoom

@Data
@Entity
@Table(name = "ChatRoom")
@DynamicUpdate
@Builder
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
@AllArgsConstructor
public class ChatRoom {

    @EqualsAndHashCode.Include
    @Id
    @Column(name = "id")
    private String id;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "lastChatMesgId")
    private ChatMessage lastChatMesg;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "ChatRoom_Members",
            joinColumns = @JoinColumn(name = "chatRoomId"),
            inverseJoinColumns = @JoinColumn(name = "memberId"))
    private Set<User> chatRoomMembers = new HashSet<>();

    @Column(name = "createdAt")
    private LocalDateTime createdAt;

    public static ChatRoom create() {

        ChatRoom room = new ChatRoom();
        room.setId(UUID.randomUUID().toString());

        return room;
    }

    public void addMembers(User roomMaker, User guest) {
        this.chatRoomMembers.add(roomMaker);
        this.chatRoomMembers.add(guest);
    }
}
  • ChatRoom 의 ID는 String 타입이며 UUID.randomUUID()로 생성하여 기본키 값으로 사용하였다.
  • lastChatMesg 필드값은 채팅방에서 채팅이 오갈경우, 가장 최신의 채팅메시지를 저장한다.
    사용자의 채팅방 목록을 화면에 보여줄 때, 최신 채팅메시지를 보여주기 위해 선언하였다.
  • chatRoomMembers 필드는 방별 사용자를 저장하는 테이블로  @ManyToMany를 사용함
create table ChatRoom
(
    id             VARCHAR(255) PRIMARY KEY COMMENT '채팅방 id key',
    lastChatMesgId int,
    createdAt      datetime,

    FOREIGN KEY (lastChatMesgId) REFERENCES ChatMessage (id) ON DELETE CASCADE
)
create table ChatRoom_Members
(
    chatRoomId VARCHAR(255) NOT NULL,
    memberId   int          NOT NULL,

    PRIMARY KEY (chatRoomId, memberId),
    FOREIGN KEY (chatRoomId) REFERENCES ChatRoom (id) ON DELETE CASCADE,
    FOREIGN KEY (memberId) REFERENCES User (id) ON DELETE CASCADE
)

 

2. ChatMessage

@Data
@Entity
@Table(name = "ChatMessage")
@Builder
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
@AllArgsConstructor
public class ChatMessage {

    @EqualsAndHashCode.Include
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @JoinColumn(name = "roomId", insertable = false, updatable = false)
    private String roomId;

    @JoinColumn(name = "authorId", insertable = false, updatable = false)
    private Long authorId;

    @Column(name = "message")
    private String message;

    @Column(name = "createdAt")
    private LocalDateTime createdAt;
}
  • ChatMessage의 id를 자동생성 전략을 적용하여 선언하였다
  • roomId, authorId 는 모두 FK 컬럼들이다.
  • message 내용과 createdAt 필드 선언
create table ChatMessage
(
    id        int AUTO_INCREMENT PRIMARY KEY COMMENT '채팅 메시지 id key',
    roomId    VARCHAR(255) NOT NULL,
    authorId  int          NOT NULL,
    message   VARCHAR(255) NOT NULL,
    createdAt datetime,

    FOREIGN KEY (roomId) REFERENCES ChatRoom (id) ON DELETE CASCADE,
    FOREIGN KEY (authorId) REFERENCES User (id) ON DELETE CASCADE
)