채팅 정책 정리
1. 채팅방 기준
- 채팅방은
memberId : memberId 기준의 1:1 채팅방이다.
guardianId, sitterId 같은 역할 기준 컬럼은 사용하지 않는다.
- 두 회원 사이 채팅방은 1개만 존재한다.
2. 채팅 가능 대상
ADMIN을 제외한 일반 회원끼리 채팅할 수 있다.
MEMBER ↔ MEMBER, MEMBER ↔ SITTER, SITTER ↔ SITTER 모두 허용한다.
SitterProfile 존재 여부로 채팅 가능 여부를 제한하지 않는다.
- 탈퇴 회원, 정지 회원과는 채팅할 수 없다.
- 본인과는 채팅할 수 없다.
3. 채팅방 생성 및 중복 방지
- 채팅방은 사용자가
채팅 시작하기 버튼을 누르는 시점에 생성한다.
- 채팅 시작 버튼은 우선 시터 프로필 상세 페이지, 공고 상세 페이지 작성자 영역에 둔다.
- 채팅방 생성 요청은 상대 회원 ID인
opponentId만 받는다.
- 현재 로그인한 회원 ID는 JWT 인증 정보에서 가져온다.
- 클라이언트에서 현재 로그인한 회원 ID를 직접 전달받지 않는다.
- 현재 로그인한 회원과
opponentId가 같으면 채팅방을 생성할 수 없다.
- 두 회원 ID 중 작은 값을
memberAId, 큰 값을 memberBId로 저장한다.
roomKey는 "memberAId:memberBId" 형식으로 생성한다.
- 같은
roomKey를 가진 채팅방은 1개만 존재한다.
- 이미 같은
roomKey의 채팅방이 있으면 기존 채팅방을 반환한다.
- 동시에 같은 채팅방 생성 요청이 들어오면 DB
UNIQUE(roomKey)로 중복 생성을 막는다.
UNIQUE(roomKey) 충돌이 발생하면 기존 채팅방을 다시 조회해서 반환한다.
- 채팅방이 처음 생성될 때 두 회원의
ChatRoomParticipant 정보를 함께 생성한다.
4. 메시지 전송
- 메시지는 해당 채팅방의 참여자만 보낼 수 있다.
- 현재 로그인한 회원 ID는 JWT 인증 정보에서 가져온다.
- 메시지 전송 요청에서
senderId를 직접 받지 않는다.
- 메시지는
TEXT, IMAGE 타입을 허용한다.
TEXT 메시지는 앞뒤 공백 제거 후 내용이 비어 있으면 전송할 수 없다.
TEXT 메시지 최대 길이는 1000자로 제한한다.
IMAGE 메시지는 이미지 단독 전송만 허용한다.
- 이미지는 S3에 저장하고, 채팅 메시지에는
imageUrl만 저장한다.
- 허용 이미지 형식은
jpg, jpeg, png로 제한한다.
- 이미지 최대 크기는 10MB로 제한한다.
- 메시지 전송자와 상대방은 탈퇴 또는 정지 상태가 아니어야 한다.
ADMIN은 메시지를 전송할 수 없다.
- 메시지를 저장할 때
senderId, senderNickname을 함께 저장한다.
senderNickname은 메시지 전송 당시 닉네임 스냅샷이다.
- 메시지 전송 성공 시 채팅방의 마지막 메시지 ID와 마지막 메시지 시간을 갱신한다.
5. 채팅방 나가기
- 채팅방 나가기는 실제 채팅방 삭제가 아니다.
- 채팅 메시지는 DB에서 삭제하지 않는다.
- 나간 사람의 화면에서만 기존 채팅 내역을 숨긴다.
- 상대방이 나가지 않았다면 상대방 화면에서는 기존 메시지가 그대로 유지된다.
- 사용자가 채팅방을 나가면
ChatRoomParticipant.isLeft = true로 변경한다.
- 사용자가 채팅방을 나가면
leftAt에 현재 시각을 저장한다.
- 사용자가 채팅방을 나가면
visibleFromAt에도 현재 시각을 저장한다.
- 나간 사용자는
visibleFromAt 이전 메시지를 다시 볼 수 없다.
- 카카오톡처럼 나가도 상대방이 새 메시지를 보내면 다시 연락을 받을 수 있다.
- 상대방이 새 메시지를 보내면 나간 사용자의 채팅방은 다시 목록에 표시된다.
- 이때 나간 사용자는
visibleFromAt 이후 메시지만 볼 수 있다.
- 한 사용자가 채팅방을 나가도 상대방의 상태는 변경하지 않는다.
- 한 사용자가 채팅방을 나가도
ChatRoom, ChatMessage는 삭제하지 않는다.