본문 바로가기
etc

[KOSTA 프로젝트] 01. DB에 JSON형태로 저장해도 될까?

by Zㅣ존수빈zz 2023. 11. 14.

진행하고 있는 프로젝트 기능 중 이전부터 구현해보고 싶었던 채팅 기능이 포함되었다.

요구사항 정의서 같은 문서들을 작성하고, 데이터 모델링을 시작했는데, 왠지 쉽게 머릿속에 그려지지 않았다.

그래서 다른 사례들을 먼저 찾아보게 되었고, 이번 프로젝트 첫번째 의문이 생겼다.

순서대로 채팅방 - 채팅 참여 - 회원 목록이다.

이렇게 채팅 참여 테이블을 따로 빼서 채팅방과 참여자를 연결하는 방식이었는데

이 구조를 처음 봤을 때 테이블 하나를 더 쓰는 것이 불필요해 보였다.

자바에서 엔티티를 만들 때를 생각하며 채팅방 테이블에 참여자 리스트를 넣는다면 테이블이 하나 줄어들고,

코드도 줄어 들 것 같다는 이유에서였다.

이런식으로 참여자 목록 column을 VARCHAR로 저장해서 Java에서 파싱하면 그렇게 어려울 것 같지 않았다.

그런데 찾아본 사례는 왜 그렇게 만들었는지 궁금해졌다.

JSON으로 저장했을 때 불편한 부분이 있어서 그랬을 것이라 추측이 되는데 도무지 알기 어려워서 직접 테이블을 만들기도 해보고, 검색도 해보면서 내 생각 중 어디가 잘못되었는지 알 수 있었다.

자료가 이렇게 많은 걸 보니  나랑 같은 고민을 한 사람이 정말 많았나 보다.

 

stackoverflow에서도 비슷한 문제를 많이 다룬 것 같다.

https://stackoverflow.com/questions/15367696/storing-json-in-database-vs-having-a-new-column-for-each-key

여기에서 제일 위에 있는 답변을 보면 알기 쉽게 정리해줘서 좋았다.

 

Json으로 저장했을 때의 장점은
  • 불필요한 column을 만들지 않아도 된다.
  • schema migration이 필요 없다.

정도인 것 같다. 그런데 두 번째 장점을 말한 댓글은 처음엔 이러한 장점 때문에 'sliced bread'이후로 가장 좋은 것이었다고 칭찬하지만, 시간이 지날 수록 Json은 작은 데이터 조각들을 저장하는 junk drawers가 되었다고 말한다.

결국 Json의 유연성, 즉 유효성 검사가 불가한 것이 가장 큰 단점이 된 셈이다.

이렇게 되면 결국 데이터 유효성 검사를 하는 코드를 다시 생성해야 한다.

 

Json은 빠르고 쉽게 데이터를 전달하고, 찾고, 출력할 수 있지만 일관성, 무결성 면에서는 매우 취약하다.

심지어 DB에서는 하나의 column에 문자열로 저장되기 때문에 검색하기 번거롭다.

그렇기에 댓글 중 Json이 권장되는 경우를 알려준다.

  1. When storing email addresses and phone numbers for a contact, where storing them as values in a JSON array is much easier to manage than multiple separate tables
  2. Saving arbitrary key/value user preferences (where the value can be boolean, textual, or numeric, and you don't want to have separate columns for different data types)
  3. Storing configuration data that has no defined schema (if you're building Zapier, or IFTTT and need to store configuration data for each integration)

 

이 글을 읽고 생각해볼 만한 기준이 생겼는데,

'Json으로 저장될 데이터로 내가 어떤 일을 할 것인지' 이다.

채팅방을 기준으로 했을 때 다른 column으로 일련번호를 부여할 것이기 때문에 특정 채팅방의 참여자 목록은 쉽게 검색할 수 있을 것이다.

ex) SELECT * FROM chat_room WHERE room_id = 1;

 

그러나 나는 채팅 참여자에게 자신이 포함된 채팅방 목록만 보여줄 생각이다.

  • 그러려면 해당 유저가 'USER_01'이라고 했을 때, DB에서 모든 채팅방 데이터를 가져온 뒤, 참여자 목록을 파싱해서 'USER_01'이 있는지 하나하나 검사해야 할 것이다.
  • 혹은 like 구문을 사용하여 'USER_01'이 포함된 채팅방을 찾아야 할텐데, 'USER_011'등 잘못된 정보가 섞여 부가적인 코드를 추가해야 할 수도 있다.

 

결국 나는 Json데이터로 저장하려 했던 참여자 목록에 대해서 조건을 사용한 검색을 해야 했다.

그래서 차라리 'JOIN_CHAT'이라는 연결테이블을 하나 두어서 해당 채팅방에 참여한 참여자 목록을 빠르게 뽑을 수 있도록 하는 것이 낫다는 결론을 내렸다.

 

다음에도 이런 상황이 종종 생길 것 같아 기록을 남긴다.

사실 알아보면서 기준을 잡을 수 있었기 때문에 계속 기억에 남을 것 같긴 하다.

댓글