개요
위 사진은 현재 개발중인 토이 프로젝트의 User - Friend의 테이블 구조이다.
친구 요청을 수락하여 서로 친구인 사용자 간의 개인 채팅방을 이용 가능하게 할 생각이었으며
친구 요청과 응답에 대한 프로세스를 하나의 테이블로 관리하고, 서로 친구가 된 친구목록을 또다른 테이블에 관리하려고 하였다.
(여기서 말하는 친구 요청에 대한 응답은, 웹소켓으로 구현했음)
현재 요청과 응답에 대한 프로세스
또한 요청과 응답을 관리하는 테이블의 STATUS 컬럼의 도메인값을 NOREAD, READ, REJECT, ACCEPT 의 네 경우를 두고, 요청을 보낸 사용자가 친구 요청을 받은 사용자가 친구 요청을 보지 않았는지, 봤는데 수락도 거절도 아닌지, 거절했는지에 대한 상황을 View할 수 있게 설계했다. 수락한 요청은 바로바로 FriendList에 테이블의 row로 추가할 예정이었다.
예를 들면 IDX가 3인 사용자가 IDX가 1인 사용자에게 요청을 보냈을 때,
위와 같은 row가 insert 될 것이다.
위의 예시처럼, IDX가 3인 사용자 A가 친구 요청 상황에 대한 조회를 원할 경우에, 아래와 같은 테이블의 상황이라고 가정하고, 내가 원하는 비즈니스 로직을 생각해 보았다.
A가 친구 추가를 보낸 것들에 대한 데이터를 요청할 때
1. A의 IDX를 가지고 FriendReqRes 테이블로 Go!!
2. IDX에 대한 요청이 있는지 Select
3. 있다면 어떤 유저에게 보냈는지(TO), 현재 A가 보낸 요청에 대한 상태(STATUS)를 List<Entity>에 담기
4. View 시켜주기
또한 해당 유저가 상대방에게 다시 친구 요청을 할 수 있는 상황은 상대방이 거절했을 때
즉 STATUS = REJECT일 때 라고 정책을 세웠음.
마지막으로 ACCEPT에 대한 row는 FriendList로 insert되며 상대방이 수락하여 서로 친구인 상황이기 때문에
FriendList에 아래와 같이 추가시켜 줄 생각이었다.
여기서 COMMENT 이하 컬럼값들은 생각하지말고, USER_IDX와 FRIEND_IDX만 살펴보자.
서로 친구인 상황이기 때문에, IDX가 3의 친구목록 뿐 아니라, IDX가 4인 친구목록에도 서로가 있어야 한다.
위의 row 하나만 추가할 경우, 서로가 친구인 상황을 DB를 조회하여 얻어내기 힘들기 때문에 친구 요청을 수락한 경우, FriendList 테이블에 두 개의 row를 insert하는 것이 맞다고 판단했다.
의문점
FriendList 테이블 하나에서 관리해도 되지 않을까??? 라는 의문이 들었다.
위와 같이, A라는 유저가 다시 IDX가 4인 사용자에게 친구 요청을 보냈다고 가정하자.
위와 같은 테이블의 row가 insert될 것이다.
4번 유저가 요청을 읽었을 때, 두 테이블의 row 모두 READ로 update해주고
거절했다면 REJECT, 수락했다면 FRIEND로 변경하여 서로 친구임을 나타낼 수 있다.
위와 같이 한 테이블로 관리하면 되지 않을까????? 라는 생각을 했다.
두 경우를 나름 정리해보았다.
1. 도메인 관리를 해야하는가 : NO
- 어짜피 두 경우 다 도메인 관리를 해야함. 하다못해 도메인값이 뭐가 뭔지 내가 알아야함
- 여기서 말하는 도메인이란 create domain을 통한 도메인생성이 아니라, 해당 컬럼에 대한 범위 라고 정의했다.
2. 무결성을 고려해야 하는가 : 하긴 해야함
- 당연히 데이터의 무결성을 고려해야한다고 생각은 하지만 두 경우 모두 대비해야함
- IDX는 User의 PK기 때문에 중복될 일이 없다고 판단
- 트랜잭션으로 누락관리가 가능한 코드를 이미 짰음.
3. 성능 및 기타 issue
- 테이블 분할 시 조인여부 : NO(요청을 수락하면 해당 IDX들을 들고가서 FriendList에 추가만 하면 된다.)
- 유지보수, 확장성 : 아무래도 분할하는 것이 더 낫지 않나... 라는 생각
결국 두 테이블을 사용하는 방법은 데이터의 일관성이나 무결성을 보장하고, 복잡성이 감소할 것이고
FriendList에 STATUS column만 추가하여 사용하면 간단하게 데이터를 관리할 수 있지만, 요청과 응답, 해당 친구의 COMMENT update 혹은 친구 삭제 등 모든 로직을 한 테이블로 수행해야하기 때문에 로직이 추가되고 추가되고 많이 추가되다보면 헷갈리고 꼬일 수 있다고 생각한다.
결론
그래서 어떤 방법을 사용해야 할까?
우선 테이블을 분할하여 관리하기로 했다.
사실 두 방법다 나쁘지 않은 것 같다. 더 좋은 방법도 있는 것 같기도 한데 생각이 나지 않음..
결론 쪽을 쓰면서 하나 더 생각난 것이 있는데,
FriendList에서 친구 요청 하나에 두 row를 생성하는 것을, 컬럼 하나를 추가하여
3번이 4번에게 요청 보냈을 때, 컬럼값을 3→4
수락했을 때, 해당 컬럼에 →3,
거절했다면 →X
이런식으로 관리하여 →로 split하여 요청에 대한 응답 여부들을 파악한다면 row가 두 배로 늘어날 일이 없지 않을까.. 라는 생각도 해보고
row가 엄청 늘어날 경우 일정 기간이 지난 요청과 응답들은 삭제시키거나, 로그화하여 로그테이블을 따로 만드는 것도 방법이 될 것같다.
지적 부탁드립니다!!! 개발 뉴비를 바른 길로 인도해주세요 굽신...
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!