채팅 프로그램 with mongoDB

haruceki·2024년 11월 12일
0

관계형 데이터베이스(RDBMS) 방식을 MongoDB로 바꾸기위한 NoSQL에서 관계 설정 방법


기본 참조 방식(reference annotation)

직접 참조 방식 : 내장된 문서(Embedded document)


1. @DBRef (MongoDB의 기본 참조 방식)

기본 참조 방식은 참조된 문서의 ID를 다른 문서에 저장하여 관계를 맺는 방식이다. MongoDB에서는 DBRef를 사용하거나, 단순히 다른 문서의 _id 값을 저장하는 방식이 있다.

  • 참조되는 문서의 ID를 저장하여 해당 문서의 데이터를 참조함
  • MongoDB가 제공하는 레퍼런스 방식으로, 실제로 문서를 가져오려면 추가적인 데이터 조회가 필요.
  • @DBRef는 관계형 데이터베이스의 외래키(foreign key)와 유사한 개념이다.
  • MongoDB에서는 @DBRef가 기본적으로 지연 로딩(Lazy Loading) 방식으로 동작하는데, 즉 @DBRef로 참조된 데이터는 실제로 해당 데이터를 조회할 때 로드된다.
장점
  • 데이터 중복 방지: 동일한 데이터가 여러 곳에서 중복 저장되지 않으므로 데이터의 일관성을 유지하기 좋습니다.
  • 유연성: @DBRef로 참조된 문서는 다른 문서들에서 재사용 가능하며, 참조하는 문서가 변경되더라도 참조하는 모든 문서에서 그 변경 사항을 자동으로 반영할 수 있습니다.
단점
  • 추가적인 조회가 필요: @DBRef로 참조된 문서를 가져올 때, MongoDB는 해당 문서를 다시 조회해야 하므로 성능상 오버헤드가 발생할 수 있습니다.
  • 성능 문제: 데이터 조회 시마다 참조된 문서를 추가로 쿼리해야 하므로, 다수의 참조를 가진 문서를 자주 조회할 때 성능 문제가 발생할 수 있습니다.
예시
@Document(collection = "chatmessages")
public class ChatMessage {
    @Id
    private String id;
    private String message;
    
    @DBRef
    private Chatroom chatroom; // 참조된 문서 ID
}
컬렉션 예시
  • chatroom 컬렉션
{
  "_id": "chatroom1",
  "name": "General Chat",
  "members": [
    { "$ref": "Member", "$id": "member1" },
    { "$ref": "Member", "$id": "member2" }
  ],
  "messages": [
    { "$ref": "ChatMessage", "$id": "msg1" },
    { "$ref": "ChatMessage", "$id": "msg2" }
  ]
}
  • member 컬렉션
{
  "_id": "member1",
  "userId": "user123",
  "isDeleted": false
}
  • chatMessage 컬렉션
{
  "_id": "msg1",
  "userId": "user123",
  "content": "Hello, everyone!",
  "timestamp": "2024-11-13T10:00:00"
}

2. 직접 참조 (Embedded document방식)

직접 참조는 다른 문서를 필드로 포함하는 방식으로, 다른 문서의 전체 객체를 필드로 넣어 하나의 문서 내에 완전한 데이터를 포함시키는 방식이다. 이 방법은 임베디드 문서(Embedded Document)로도 불린다.

예를 들어, Chatroom 문서 안에 ChatMessage를 배열로 내장시켜 저장한다.

  • 참조된 문서의 ID가 아니라 전체 문서를 필드로 포함시킨다.
  • 데이터가 중복될 수 있으며, 모든 관련 데이터가 하나의 문서에 저장된다.
  • @DBRef와 달리, 임베디드 문서는 쿼리 시에 한 번의 조회로 모든 정보를 가져올 수 있다.
장점
  • 빠른 조회: 임베디드된 데이터는 한 번의 쿼리로 가져올 수 있으므로 조회 성능이 빠르다.
  • 데이터 일관성: 데이터를 한 번에 관리할 수 있기 때문에 일관성 유지가 쉽다.
    중복이 용인되는 경우 유리: 데이터가 중복되는 것에 문제가 없다면, 한 번의 쿼리로 관련된 데이터를 모두 가져올 수 있어 성능적으로 유리하다.
단점
  • 데이터 중복: 데이터가 여러 번 중복되어 저장될 수 있다. 예를 들어, ChatMessage가 여러 Chatroom에 포함되면, 동일한 메시지가 여러 곳에 저장된다.
  • 데이터 크기 증가: 임베디드 문서가 커지면 문서 크기가 증가하여 성능에 영향을 미칠 수 있다. 특히 큰 데이터 집합을 임베디드하면 단일 문서 크기 제한(16MB)에 도달할 수 있다.
  • 업데이트 문제: 데이터가 여러 곳에 중복되어 저장되기 때문에 하나의 데이터를 수정할 때, 모든 문서를 업데이트해야 할 수 있다.
코드 예시
@Document(collection = "chatrooms")
public class Chatroom {
    @Id
    private String id;
    private String roomname;

    private List<ChatMessage> chatMessages; // 임베디드된 ChatMessage 객체
}
컬렉션 예시
{
  "_id": "chatroom1",
  "name": "General Chat",
  "members": [
    {
      "memberId": "member1",
      "userId": "user123",
      "isDeleted": false
    },
    {
      "memberId": "member2",
      "userId": "user456",
      "isDeleted": false
    }
  ],
  "messages": [
    {
      "messageId": "msg1",
      "userId": "user123",
      "content": "Hello, everyone!",
      "timestamp": "2024-11-13T10:00:00"
    },
    {
      "messageId": "msg2",
      "userId": "user456",
      "content": "Hi there!",
      "timestamp": "2024-11-13T10:05:00"
    }
  ]
}

3. 기본 참조 (@DBRef) vs 직접 참조 (Embedded 방식) 비교

기준기본 참조 (@DBRef)직접 참조 (Embedded 방식)
데이터 중복중복을 방지, 참조된 문서만 ID로 저장데이터 중복 가능, 동일 데이터가 여러 문서에 포함될 수 있음
조회 성능참조된 문서를 추가로 조회해야 하므로 성능에 영향을 미침한 번의 조회로 모든 데이터를 가져오기 때문에 성능이 빠름
문서 크기 제한제한 없음 (ID만 저장하므로 크기가 작음)문서 크기가 커지면 16MB 제한에 도달할 수 있음
데이터 일관성참조된 문서가 변경되면 자동으로 반영됨중복 데이터 수정 시 일관성 문제 발생 가능
유연성더 유연한 데이터 모델링 (중복 없이 참조 가능)중복이 허용되는 경우 더 적합
성능쿼리가 두 번 발생할 수 있어 성능에 영향을 줄 수 있음쿼리 한 번으로 데이터를 모두 가져올 수 있어 성능이 좋음
profile
희망도 절망도 없이 매일 코딩을 한다.

0개의 댓글