-
Notifications
You must be signed in to change notification settings - Fork 2
RDB Schema
member 엔티티에는 어떠한 외래키 칼럼도 존재해서는 안됩니다. 그 자체로 최상위 엔티티이여야 합니다.
사용자는 공부 시간을 기록하기 위해서 category 정보를 같이 입력해야 합니다. 이때 사용되는 카테고리 정보는 study_category 엔티티에 저장됩니다.
카테고리 데이터는 데이터 정합성을 위해 soft delete 를 사용합니다. 따라서, 카테고리 삭제 시, 카테고리 데이터가 지워지는 것이 아닌 study_type 이 변경됩니다.
해당 카테고리의 소속을 분류해야 하며, 이를 위해 위 두 칼럼이 존재합니다.
study_type 은 해당 카테고리의 소속 및 상태에 대한 ENUM 타입입니다. 올 수 있는 내용으로는 다음과 같습니다.
-
PERSONAL: 개인이 생성한 카테고리입니다. write 는 해당 개인만 가능합니다. -
GROUP: 그룹에서 생성한 카테고리입니다. write 는 해당 그룹의 그룹장 및 메니저만 가능합니다. -
REMOVED: 개인이 생성한 카테고리 중, 삭제된 카테고리입니다. write 권한은 누구에게도 없습니다. -
GROUP_REMOVED: 그룹이 생성한 카테고리입니다. write 권한은 누구에도 없습니다.
type_id 는 study_type 에 의해 정의된 연관관계에서, 해당 엔티티의 id 를 저장합니다. 즉, 가령 study_type 이 PERSONAL 이라면, type_id 는 member#id 를 의미하고, GROUP 이라면, group#id 를 의미합니다.
어플리케이션 단계에서 전략 패턴을 통해 type 에 대한 read/write/validate 로직을 정의합니다.
day_belong 은 해당 카테고리가 포함된 요일에 대한 데이터입니다. 비트마스킹을 통해 0000000(포함되지 않음) ~ 1111111(모든 요일에 포함됨) 의 값을 가집니다. 해당 비트마스킹 연산은 프론트에서 담당하므로, 백엔드에서는 이에 대한 CRUD 로직 정도만 유지하면 됩니다.
공부 시간을 저장하는 엔티티입니다. 어떤 사용자 가 어떤 카테고리 를 언제 얼마나 공부하였는지에 대한 정보를 기록합니다.
기록은 동일한 member_id, study_category_id or name, studied_date 라면, study_time 값을 증가시키며, 아닌 경우 새로운 레코드를 생성합니다.
공부 시간을 저장하기 위해선, 어떤 카테고리에 대한 공부 인지에 대한 정보를 기입해야 합니다. 이때, name 은 study_category 테이블에 저장하지는 않았으나 단 하루 동안만 유효한 "임시 카테고리"에 대한 정의입니다. 임시 카테고리란, 사용자가 정의한 주기적으로 수행해야 되는 카테고리가 아닌, 일시적인 이벤트 등으로 임시로 사용하기 위한 카테고리의 이름입니다.
다른 날짜에, 동일한 임시 카테고리 이름으로 공부를 진행한다면, 새로운 레코드를 생성합니다. (날짜가 다릅니다)
같은 날짜에, 동일한 임시 카테고리 이름으로 공부를 진행한다면, 해당 레코드가 갱신됩니다. (날짜, 이름, 유저가 동일합니다)
같은 날짜에, 동일한 카테고리 아이디로 공부를 진행한다면, 해당 레코드가 갱신됩니다.(날짜, 카테고리, 유저가 동일합니다)
목표 시간은 study_category의 goal 필드와 동일한 역할을 수행합니다. study_time 에 study_category 외래키가 존재함에도 동일한 역할을 하는 필드가 있는 까닭은 다음과 같습니다.
- 사용자가 특정 카테고리에 대해, 목표 시간을 수정하는 경우
- 공부 시간 통계를 통해 불러온 이전 기록의 목표 시간도, 갱신된 목표 시간으로 표시됩니다.
- 그러나 통계의 의도 중 하나는 사용자가 "당시 설정된 목표 시간"을 얼마나 달성했나에 대한 여부입니다.
- 따라서 이전 기록에 대한 목표 시간 정보를 유지할 필요성이 있었고, 공부 시간 자체에 목표 시간 필드(goal)을 두었습니다.
- 새로운
study_time을 저장하는 경우,study_category의goal칼럼 값을 복사해야 합니다. - 임시 카테고리의 경우, 사용자가
goal칼럼 값을 직접 설정할 수 있습니다.
하루 동안의 사용자 공부 시간 요약 데이터입니다. 날짜에 따른 시작 및 종료 시각, 총 공부 시간 등을 기록합니다.
사용자가 해당 날짜에 "최초로" 공부를 시작하는 경우 daily_study_info 레코드가 생성되며, 이때 start_time 에 현재 시각이 입력됩니다. 이후로는 수정할 수 없습니다.
사용자가 공부를 종료할 때마다 최신 값으로 갱신됩니다. 공부를 종료하는 시각이 입력됩니다. 그러나, 공부가 오전 6시 이후로 종료되는 경우 다음과 같은 프로세스를 따릅니다.
- 종료 시점 기준 "어제" 데이터의
end_time을 6:00 으로 입력합니다. - 종료 시점 기준 "오늘" 데이터를 새롭게 생성하고,
start_time을 6:00 으로 입력합니다. -
end_time을 현재 시각으로 입력합니다.
날짜의 기준은 `06:00` 입니다. 즉, 오전 6시 이전이면 "어제" 로 취급하고, 오전 6시 이후가 넘어야 "오늘"이 됩니다.
유저가 모인 집단, group 에 대한 엔티티입니다. 유저와 그룹 간 다대다 매핑을 위한 매핑 테이블 group_member 가 존재합니다.
해당 그룹이 추가적인 멤버를 받을지에 대한 여부입니다. 그룹장 및 메니저가 수정이 가능하며 max_member 와는 관계 없이 false 로 설정되어 있다면 새로운 유저를 추가할 수 없습니다. 단, 현재 해당 기능은 미구현 상태입니다. 다만 다음과 같은 기능이 필요할 것이라 사료됩니다.
- false 인 경우, 가입 문의 비활성화
- false 인 경우, 초대 링크 비활성화
- false 인 경우, 그룹 검색에 나타나지 않음(혹은 비활성화)
해당 그룹에 참가하기 위해, 그룹장 등의 승인을 받아야 되는지에 대한 여부입니다. 만약, 해당 값이 true 인 경우, 사용자는 그룹에 가입 신청을 하고, 해당 신청은 group_register_request 엔티티에 저장됩니다. 기간이 지난 신청 데이터는, 가입 요청 데이터를 읽어올 때 검사하여 삭제합니다.
해당 그룹에 소속된 총 사용자 수입니다. group_member 를 통해 멤버 수를 직접 세는 것 보다, 개별적인 칼럼을 두어 반정규화를 하는 것이 더욱 도움이 될 것이라 판단하였습니다. 이는, 새로운 사용자가 그룹에 참가 시도 시, max_member 와 비교할 때 사용합니다.
group_tag 에서 정의된 값만 사용할 수 있습니다. 직접적인 연관관계는 없으나 어플리케이션 단계에서 구현해야 합니다. tag 는 해당 그룹의 정체성이며, 공통 사항을 다룹니다. 가령, 공시, 9급 공무원 등이 존재합니다.
그룹장 및 메니저는 해당 그룹에서 사용할 카테고리를 생성할 수 있습니다. 이때, 카테고리의 category_type 은 GROUP 이여야 하고, type_id 는 해당 그룹의 ID 이여야 합니다.
또한, 삭제 및 갱신이 가능한데, 삭제의 경우 category_type 이 GROUP_REMOVED 로 변경되며, 해당 데이터를 열람할 수 있지만 사용 및 수정이 불가능합니다. 사용이 불가하다는 의미는, 사용자가 해당 카테고리를 주제로 공부하지 못하는 것을 의미합니다.
채팅방 아이디입니다. 각 그룹은 채팅방을 하나 씩 가지고 있으며, 이는 chat_room 엔티티와 대응됩니다. 모든 그룹 참여자는, 자동으로 해당 채팅방의 멤버로 소속되게 됩니다. (이 역시 어플리케이션 단계에서 수행되어야 합니다)
채팅방에 대한 정보를 관리합니다. 채팅방 이름 및 생성 날짜 등이 있습니다. 유저와 채팅방 간 다대다 매핑을 위한 매핑 테이블 chat_room_member 가 존재합니다.
chat_room_member#last_read_message 는 사용자가 해당 채팅방에서 가장 마지막으로 읽은 채팅의 ID 를 저장합니다. 단, 이는 완전히 실시간이 아니며 비교적 긴 주기로 redis -> mysql 로의 정규화를 시도합니다. 따라서, 최신 데이터를 위해선 redis + mysql 의 데이터를 합쳐야 합니다.
가장 마지막으로 읽은 채팅 ID 를 유지하는 까닭은
- 언리드 유저 카운트(특정 메시지를 읽지 않은 유저 카운트)를 위한 커서 데이터
- 언리드 메시지 카운트(해당 채팅방에서 읽지 않은 메시지 개수)를 위한 커서 데이터
- 로그 불러오기를 위한 시작 지점 채팅 아이디
입니다.
role 등은 아직 구체화된 구현 사항이 없습니다.