chatting DB 설계

Jaymee·2021년 9월 20일
2

현재 개발중인 프로젝트 yeomanda에서 채팅 기능을 구현하기 위해 디비를 설계할때 많은 시간을 쏟았다. 어떻게 디비를 설계해야 가장 효율적으로 빠른 시간에 데이터를 주고 받을 수 있고, 디비 과부하가 걸리지 않을까 하면서 고민을 많이 했는데...
일단은 nosql로 디비를 다뤄야겠다고 생각하였다.

  • 아무래도 데이터의 양이 많다.
  • 대화를 계속해서 누적해서 저장을 해야하기 때문에 nosql에서 배열을 저장하기에 더 수월할 것이라고 생각했다.
  • join 같은 연산이 필요없고, 단순 쓰기 읽기 작업이 주로 이뤄진다고 생각했다.

위와 같은 이유들을 바탕으로 nosql을 사용했다.
기존에 모든 디비를 aws 서비스들을 이용하고 있었기 때문에, 채팅 디비 또한 aws dynamodb를 사용했다.
그렇다면 document는 어떻게 짜야할까

여기서 두가지 고민을 했다.

  • 채팅방마다 테이블을 만들어야 하나?
  • 하나의 테이블에 모든 채팅방을 구현해야 하나?

채팅방마다 테이블을 만드는것은 너무나도 비효율적이라고 생각했기 때문에, 하나의 테이블에 모든 채팅을 기록하기로 하였다.

자 그러면 채팅방 id를 pk로 설정하고 작업을 해야겠다.
생각을 해보면 우리의 채팅방은 한번 생성이 되면 수정되지 않는다. 이 말은 새로운 인원이 추가되거나 삭제되지 않는다는 말이다. 우리는 함께 온 여행객들의 만남을 주선해주기 때문에, 같이 여행 온 사람들을 제외하거나 새로운 인물을 추가하지 않는다는 말이다.

그렇다면, 결국 document에서 계속해서 수정되는 값은 메세지이다.

| room_id(PK) | teams | messages | members |

이렇게 설계했다. 여기서 중요한 점은 messages 이다.
다른 teams 혹은 members는 간단하게 배열로 설정하였다.
messages에는 또 다른 값들이 필요하다.

  • sender
  • createdAt
  • content

이 값들이 또 다른 map을 만들어 이 map들로 배열을 형성하는 필드가 바로 messages 이다.

{
  "room_id": {
    "S": "1_5"
  },
  "teams": {
    "L": [
      {
        "S": "sexy"
      },
      {
        "S": "party"
      }
    ]
  },
  "messages": {
    "L": [
      {
        "M": {
          "creates_at": {
            "S": "2109181526"
          },
          "sender": {
            "S": "aaa0@aaa0.com"
          },
          "content": {
            "S": "hi hello"
          }
        }
      },
      {
        "M": {
          "creates_at": {
            "S": "2109181530"
          },
          "sender": {
            "S": "aaa1@aaa1.com"
          },
          "content": {
            "S": "nice to meet you"
          }
        }
      }
    ]
  },
  "members": {
    "L": [
      {
        "S": "aaa0@aaa0.com"
      },
      {
        "S": "aaa1@aaa1.com"
      },
      {
        "S": "aaa2@aaa2.com"
      },
      {
        "S": "woals4@woals4.com"
      },
      {
        "S": "woals5@woals5.com"
      },
      {
        "S": "woals6@woals6.com"
      }
    ]
  }
}

그래서 설계한 dynamodb document 이다.
다른 값들은 저장하는데 어렵지 않았다.
하지만 문제는 messages 이다.
실시간으로 넘겨오는 채팅 내용을 하나하나 저장을 해야하기 때문에, 계속해서 누적해서 저장하는 기능이 필수적인데, 내가 찾아보기로는 dynamodb에 누적하는 방법은 없었다.

그래서 내가 생각해 낸 방법이 모든 값을 filter 함수를 통해 읽어서 새로운 배열에 저장하고, 새로운 대화를 마지막으로 배열에 push 해서 해당 배열을 다시 디비에 저장하는 방식이다.

아무리 생각해도 너무 비효율적이고, 메모리 낭비, 시간 낭비가 예상되지만, 어떻게 더 효율적으로 구현할 수 있을지 한번 알아봐야겠다.

profile
backend developer

0개의 댓글