-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/#29 채팅 관련 로직 구현 #183
Conversation
- WebsocketConfig.java - configureMessageBroker() 메서드 -> 메시지 브로커 설정 및 메시지 발행, 수신 URI 설정 - registerStompEndpoints() 메서드 -> STOMP 엔드포인트 등록 및 API STOMP 기반 웹소켓 연걸 URI 설정
- ChatRoom - 사용자의 채팅방 입장을 위한 관련 레포지토리 구현 - ChatRoomRepository.java - findByGatherArticleId(), findById(), existsById() 메서드 명시적으로 선언 - ChatRoomRepositoryCustom.java - findValidateDTOByGatherArticleId(), findChatRoomDetailsListByUsername() 커스텀 메서드 선언 - ChatRoomRepositoryCustomImpl.java - findValidateDTOByGatherArticleId(), findChatRoomDetailsListByUsername() 구현 - 사용자의 채팅방 입장을 위한 ChatRoomResponse DTO 구현 - ChatRoomResponse.InfoDTO.java - 채팅방 정보를 조회하기 위한 DTO - 필드: id, joinedAt, memberChatRoomRole - ChatRoomResponse.ValidateDTO.java - 채팅방이 존재하는지를 조회하기 위한 DTO - 필드: id - ChatRoomResponse.ChatRoomDetailsDTO.java - 참여 채팅방 목록 및 관련 정보를 조회하기 위한 DTO - 필드: chatRoomId, gatherArticleSimpleInfo(해당 채팅방과 관련된 모집글 간단 정보), lastChatMessageInfo(해당 채팅방에서 마지막으로 전송된 메시지 정보) -
- MemberChatRoom - 채팅방에 참여한 사용자의 정보 관리 로직을 구현하기 위한 관련 레포지토리 구현 - MemberChatRoomRepository.java - existsByChatRoomIdAndMemberUsername(), existsByChatRoomIdAndMemberNickname() 메서드 명시적으로 선언 - MemberChatRoomRepositoryCustom.java - existsByGatherArticleIdAndNickname(), findByGatherArticleIdAndUsername() 커스텀 메서드 선언 - MemberChatRoomRepositoryCustomImpl.java - existsByGatherArticleIdAndNickname(), findByGatherArticleIdAndUsername() 구현 - 사용자의 채팅방 입장을 위한 MemberChatRoomResponse DTO 구현 - MemberChatRoomResponse.ValidateDTO.java - 채팅방에 참여한 사용자의 정보를 조회하기 위한 DTO - 필드: id, memberChatRoomRole
- ChatMessage - 채팅 메세지 발행 및 전송, 메세지 수신 구현을 위한 관련 레포지토리 구현 - ChatMessageRepository.java - Spring Data JPA 제공 메서드를 활용하기 위한 레포지토리 구현 - ChatMessageRepositoryCustom.java - findMessagesAfterMemberJoinedByChatRoomIdAndUsername(), findTalkMessageById(), findEnterOrExitMessageById() 커스텀 메서드 선언 - ChatMessageRepositoryCustomImpl.java - findMessagesAfterMemberJoinedByChatRoomIdAndUsername(), findTalkMessageById(), findEnterOrExitMessageById() 메서드 구현 - 채팅 메세지 발행 및 전송 구현을 위한 ChatMessageRequest DTO 구현 - ChatMessageRequest.PublishDTO.java - 채팅방에 참여한 사용자들에게 발행할 메세지 내용을 클라이언트로부터 전달받기 위한 DTO - 필드: content - 채팅 메세지 수신 구현을 위한 ChatMessageResponse DTO 구현 - ChatMessageResponse.ChatMessageInfoDTO.java - 입장, 퇴장 메세지를 제외한 일반적인 메세지의 정보를 조회하기 위한 DTO - 필드: content, nickname, profileImageS3SavedURL, rank, messageType, sentAt - ChatMessageResponse.EnterOrExitMessageInfoDTO.java - 입장, 퇴장 메세지의 정보를 조회하기 위한 DTO - 필드: content, messageType - ChatMessageResponse.LatestChatMessageInfoDTO.java - 채팅방에서 가장 최근에 전송된 메시지 내용과 시간을 조회하기 위한 DTO - 필드: content, sentAt
- ChatRoom - 채팅방 입장, 퇴장 관련 로직을 구현하기 위한 ChatRoomService.java 구현 - ChatRoomService.java - 필드: chatRoomRepository, memberChatRoomRepository, memberRepository - enterChatRoom() 메서드: 사용자가 특정 모집글과 관련된 채팅방에 입장 - leaveChatRoom() 메서드: 사용자가 특정 모집글과 관련된 채팅방에서 퇴장 - getChatRoomDetailsListByUsername() 메서드: 특정 사용자가 참여하고 있는 채팅방 상세 정보 목록 조회
- ChatMessage - 메세지 발행 및 전송, 수신 관련 로직을 구현하기 위한 ChatMessageService.java 구현 - ChatMessageService.java - 필드: chatMessageRepository, chatRoomRepository, memberRepository, memberChatRoomRepository, messagingTemplate - publishMessage() 메서드: 메세지 발행 및 채팅방에 메세지 전송 - publishEnterChatMessage() 메서드: 채팅방 입장 메세지 발행 및 채팅방에 사용자 입장 메세지 전송 - publishExitChatMessage() 메서드: 채팅방 퇴장 메세지 발행 및 채팅방에 사용자 퇴장 메세지 전송 - publishEnterOrExitChatMessage() 메서드: 채팅방 입장/퇴장 메세지 발행 및 채팅방에 사용자 입장/퇴장 메세지 전송 - findMessagesAfterMemberJoinedByChatRoomIdAndUsername() 메서드: 사용자가 채팅방에 입장한 이후의 메세지 조회 - 채팅방 입장/퇴장 메세지를 생성하기 위한 유틸 클래스 구현 - ChatMessageUtil.java - buildChatMessageContent() 메서드: 채팅 메시지 내용을 생성
- ChatRoom - 채팅방 입장/퇴장 요청을 캐치하기 위한 ChatRoomController.java 구현 - ChatRoomController.java - 필드: chatRoomService, gatherArticleService - getChatRoomGatherArticleInfo() 메서드: 채팅방 정보와 연관된 모집글 정보 조회 요청 캐치 - 요청 URI: '/api/chat/rooms/{chatRoomId}/gather-articles/{gatherArticleId}' - getChatRoomDetailsByUsername() 메서드: 특정 사용자가 참여한 채팅방 목록 조회 요청 캐치 - 요청 URI: '/api/chat/rooms'
- ChatMessage - 채팅방 입장/퇴장 요청을 캐치하기 위한 ChatMessageController.java 구현 - ChatMessageController.java - 필드: chatMessageService - publishMessage() 메서드: 특정 채팅방에 메세지 발행 및 전송 요청 캐치 - 요청 URI: '/api/chat/publication/{chatRoomId}' - getChatMessages() 메서드: 채팅방 메세지 내역 조회 요청 캐치 - 요청 URI: '/api/chat/rooms/{chatRoomId}/messages'
- GatherArticleResponse.SummaryInfoDTO.java - 채팅방 정보와 연관된 모집글 요약 정보를 조회하기 위한 DTO - 필드: title, meetingLocation, maxParticipants, currentParticipants, startDateTime, endDateTime - GatherArticleResponse.SimpleInfoDTO.java - 채팅방 정보와 연관된 모집글 간단 정보를 조회하기 위한 DTO - 필드: gatherArticleId, title, maxParticipants, meetingLocation, currentParticipants - GatherArticleRepository.java - existsByChatRoomIdAndId() 메서드 명시적으로 추가 선언 - GatherArticleRepositoryCustom.java - findSimpleInfoByGatherArticleId() 커스텀 메서드 추가 선언 - GatherArticleRepositoryCustomImpl.java - findSimpleInfoByGatherArticleId() 추가된 메서드 구현 - GatherArticleService.java - 채팅방 정보와 연관된 모집글 요약 정보 조희를 위한 메서드 추가 - getChatRoomGatherArticleSimpleInfo() 메서드: 채팅방 정보와 연관된 모집글 간단 정보 조회
- AlreadyEnteredChatRoomException.java - 이미 입장한 채팅방에 입장하려는 경우 - ChatRoomHostCannotLeaveException.java - 채팅방 방장이 채팅방을 나가려는 경우 - ChatRoomNotFoundException.java - 정보를 찾을수 없는 채팅방 정보를 조회하려는 경우 - ChatRoomRetrievalException.java - 서버 문제로 채팅방 정보를 찾을 수 없는 경우 - ChatRoomAccessDeniedException.java - 채팅방에 접근 권한이 없는 사용자인 경우 - ChatRoomExceptionHandler.java - handleChatRoomNotFoundException() 메서드: ChatRoomNotFoundException 등록 - handleChatRoomHostCannotLeaveException() 메서드: ChatRoomHostCannotLeaveException 등록 - handleChatRoomRetrievalException() 메서드: ChatRoomRetrievalException 등록 - handleAlreadyEnteredChatRoomException() 메서드: AlreadyEnteredChatRoomException 등록 - handleChatRoomAccessDeniedException() 메서드: ChatRoomAccessDeniedException 등록
- MemberChatRoomNotFoundException.java - 찾을 수 없는, 채팅방에 입장한 사용자의 정보를 요청한 경우 - MemberChatRoomRetrievalException.java - 서버 문제로 채팅방에 입장한 사용자의 정보를 찾을 수 없는 경우 - MemberChatRoomSaveException.java - 서버 문제로 채팅방에 입장한 사용자의 정보를 저장하지 못한 경우 - MemberChatRoomExceptionHandler.java - handleMemberChatRoomNotFoundException() 메서드: MemberChatRoomNotFoundException 등록 - handleMemberChatRoomRetrievalException() 메서드: MemberChatRoomRetrievalException 등록 - handleMemberChatRoomSaveException() 메서드: MemberChatRoomSaveException 등록
- ChatMessageRetrievalException.java - 서버 문제로 채팅 메세지 정보를 찾을 수 없는 경우 - ChatMessageSaveException.java - 서버 문제로 발행한 채팅 메세지 정보를 저장하지 못하는 경우 - ChatMessageExceptionHandler.java - handleChatMessageRetrievalException() 메서드: ChatMessageRetrievalException 등록 - handleChatMessageSaveException() 메서드: ChatMessageSaveException 등록
- 필드 이름 수정 - MemberChatRoom.java - chatRoomRole -> memberChatRoomRole 로 수정 - ChatRoomRole.java - AUTHOR("author") -> HOST("host") 로 수정 - 클래스 이름 수정으로 인한 리팩토링 - ChatMessageResponse.LastChatMessageInfoDTO -> ChatMessageResponse.LatestChatMessageInfoDTO 로 수정 - ChatRoomRepositoryCustomImpl.java - findChatRoomDetailsListByUsername() 메서드내에 ChatMessageResponse.LastChatMessageInfoDTO -> ChatMessageResponse.LatestChatMessageInfoDTO 로 수정
- ParticipationApplicationService.java - cancelParticipationApplication() 메서드 - 기존에는 해당 메서드 내에 참가 취소시 이미 참가 승인된 사용자와 참가 신청만 했던 사용자를 구분하여 채팅방 퇴장 메서드를 호출하였으나 스프링의 단일 책임 원칙을 위하여, 채팅방 퇴장 메서드를 분리하여 실행시키기 위한 로직 및 리턴값 수정 - ParticipationApplicationController.java - approveParticipationApplication() 메서드 리팩토링 - 기존의 참가승인 매서드내에서 채팅방 입장 메서드도 함께 호출하였으나 스프링의 단일 책임 원칙을 위하여 컨트롤러 레이어에서 참가신청 승인 메서드와 채팅방 입장/퇴장 메서드를 각각 호출하도록 리팩토링 - cancelParticipationApplication() - 기존의 참가취소 메서드내에서 채팅방 퇴장 메서드도 함께 호출하였으나 스프링의 단일 책임 원칙을 위하여 컨트롤러 레이어에서 참가신청 취소 메서드와 채팅방 퇴장 메서드 호출을 구분하도록 리팩토링 - 채팅방 퇴장 로직은 이미 참가 승인되어 채팅방에 입장한 사람만 채팅방에서 퇴장해야하므로 참가 승인되어 채팅방에 입장한 사용자와 참가 신청만한 사용자를 구분하기 위해 참가 취소 메서드의 리턴값을 리팩토링하여 값을 받은후 해당 값을 바탕으로 참가 승인된 사용자만 채팅방 퇴장 메서드를 호출하도록 리팩토링
@geunhokinn @serahissomi @meanzi3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
채팅 로직 구현하시느라 고생하셨습니다!
Projections.constructor(GatherArticleResponse.SimpleInfoDTO.class, | ||
gatherArticle.id, | ||
gatherArticle.title, | ||
gatherArticle.meetingLocation, | ||
gatherArticle.currentParticipants | ||
).as("gatherArticleSimpleInfo"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
필드 직접 접근 방식으로 컨벤션을 유지하면 좋을 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
확인했습니다.
.where(member.username.eq(username) | ||
.and(chatMessage.createdAt.eq( | ||
JPAExpressions | ||
.select(chatMessage.createdAt.max()) | ||
.from(chatMessage) | ||
.where(chatMessage.chatRoom.id.eq(chatRoom.id)) | ||
)) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
서브 쿼리를 이렇게 활용하는군요!
if (joinedAt == null) { | ||
throw new MemberChatRoomRetrievalException("서버 문제로 사용자가 해당 채팅방에 입장한 시간을 찾을 수 없습니다. 관리자에게 문의하세요."); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
예외 처리 부분은 서비스 로직으로 분리해도 괜찮을 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메서드로 구현하도록 하겠습니다.
ChatRoom chatRoom = chatRoomRepository.findByGatherArticleId(gatherArticleId) | ||
.orElseThrow(() -> new ChatRoomNotFoundException("해당 모집글에 대한 채팅방이 존재하지 않습니다.")); | ||
|
||
Long chatRoomId = chatRoom.getId(); | ||
|
||
if (chatRoomId == null) { | ||
throw new ChatRoomRetrievalException("서버 문제로 해당 채팅방의 정보를 찾을 수 없습니다. 관리자에게 문의하세요."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChatRoom을 조회하는 시점에 ChatRoom 엔티티가 있는지 확인하고 있으므로 밑에 있는 chatRommId == null 을 검증하는 이미 앞선 로직에서 확인이 된다고 생각이 됩니다. 리팩토링 때 고려해주시면 감사하겠습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
확인했습니다.
return messages.stream() | ||
.map(message -> { | ||
ChatMessageResponse.ChatMessageInfoDTO.ChatMessageInfoDTOBuilder builder = | ||
ChatMessageResponse.ChatMessageInfoDTO.builder() | ||
.content(message.getContent()) | ||
.messageType(message.getMessageType()); | ||
|
||
if (message.getMessageType() == MessageType.TALK) { | ||
builder.nickname(message.getNickname()) | ||
.profileImageS3SavedURL(message.getProfileImageS3SavedURL()) | ||
.rank(message.getRank()) | ||
.sentAt(message.getSentAt()); | ||
} | ||
|
||
return builder.build(); | ||
}) | ||
.collect(Collectors.toList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
빌더 패턴 안에 if 문을 넣어서 동적으로 응답 DTO를 만들 수 있군요!
#️⃣연관된 이슈
📝작업 내용
채팅방 및 관련 기능, 채팅 메세지 전송을 위한 웹소켓 설정
채팅방 관련 로직을 구현하기 위한 레포지토리 및 DTO 구현
ChatRoom
ChatRoomRepository.java
ChatRoomRepositoryCustom.java
ChatRoomRepositoryCustomImpl.java
사용자의 채팅방 입장을 위한 ChatRoomResponse DTO 구현
ChatRoomResponse.InfoDTO.java
ChatRoomResponse.ValidateDTO.java
ChatRoomResponse.ChatRoomDetailsDTO.java
채팅방에 참여한 사용자 정보 관리 로직 구현을 위한 레포지토리 및 DTO 구현
MemberChatRoom
MemberChatRoomRepository.java
MemberChatRoomRepositoryCustom.java
MemberChatRoomRepositoryCustomImpl.java
사용자의 채팅방 입장을 위한 MemberChatRoomResponse DTO 구현
MemberChatRoomResponse.ValidateDTO.java
채팅 메세지 발행 및 전송, 메세지 수신 구현을 위한 레포지토리 및 DTO 구현
ChatMessage
ChatMessageRepository.java
ChatMessageRepositoryCustom.java
ChatMessageRepositoryCustomImpl.java
채팅 메세지 발행 및 전송 구현을 위한 ChatMessageRequest DTO 구현
ChatMessageRequest.PublishDTO.java
채팅 메세지 수신 구현을 위한 ChatMessageResponse DTO 구현
ChatMessageResponse.ChatMessageInfoDTO.java
ChatMessageResponse.EnterOrExitMessageInfoDTO.java
ChatMessageResponse.LatestChatMessageInfoDTO.java
채팅방 입장, 퇴장 관련 로직을 구현하기 위한 비즈니스 로직 구현
ChatRoom
ChatRoomService.java
메세지 발행 및 전송, 수신 관련 로직을 구현하기 위한 비즈니스 로직 및 유틸 클래스 구현
ChatMessage
메세지 발행 및 전송, 수신 관련 로직을 구현하기 위한 ChatMessageService.java 구현
ChatMessageService.java
채팅방 입장/퇴장 메세지를 생성하기 위한 유틸 클래스 구현
채팅방 입장/퇴장 요청을 캐치하기 위한 컨트롤러 구현
ChatRoom
ChatRoomController.java
필드: chatRoomService, gatherArticleService
getChatRoomGatherArticleInfo() 메서드: 채팅방 정보와 연관된 모집글 정보 조회 요청 캐치
요청 URI: '/api/chat/rooms/{chatRoomId}/gather-articles/{gatherArticleId}'
getChatRoomDetailsByUsername() 메서드: 특정 사용자가 참여한 채팅방 목록 조회 요청 캐치
요청 URI: '/api/chat/rooms'
채팅 메세지 발행 및 전송, 채팅방 메세지 조회 요청을 캐치하기 위한 컨트롤러 구현
ChatMessage
ChatMessageController.java
필드: chatMessageService
publishMessage() 메서드: 특정 채팅방에 메세지 발행 및 전송 요청 캐치
요청 URI: '/api/chat/publication/{chatRoomId}'
getChatMessages() 메서드: 채팅방 메세지 내역 조회 요청 캐치
요청 URI: '/api/chat/rooms/{chatRoomId}/messages'
채팅방 정보와 연관된 모집글 요약 정보 조회를 위한 로직 및 DTO 구현
GatherArticleResponse.SummaryInfoDTO.java
GatherArticleResponse.SimpleInfoDTO.java
GatherArticleRepository.java
GatherArticleRepositoryCustom.java
GatherArticleRepositoryCustomImpl.java
GatherArticleService.java
채팅방 입장/퇴장시 발생할 수 있는 예외 클래스 및 예외 핸들러 구현
AlreadyEnteredChatRoomException.java
ChatRoomHostCannotLeaveException.java
ChatRoomNotFoundException.java
정보를 찾을수 없는 채팅방 정보를 조회하려는 경우
ChatRoomRetrievalException.java
ChatRoomAccessDeniedException.java
ChatRoomExceptionHandler.java
채팅방에 입장한 사용자 관련 정보 관리시 발생할 수 있는 예외 클래스 및 예외 핸들러 구현
MemberChatRoomNotFoundException.java
MemberChatRoomRetrievalException.java
MemberChatRoomSaveException.java
MemberChatRoomExceptionHandler.java
채팅 메세지 발행 및 전송시 발생할 수 있는 예외 클래스 및 예외 핸들러 구현
ChatMessageRetrievalException.java
ChatMessageSaveException.java
ChatMessageExceptionHandler.java
클래스 이름 변경으로 인한 리팩토링 및 필드 이름 수정
필드 이름 수정
MemberChatRoom.java
ChatRoomRole.java
클래스 이름 수정으로 인한 리팩토링
ChatRoomRepositoryCustomImpl.java
스프링의 단일 책임 원칙을 위한 리팩토링
ParticipationApplicationService.java
ParticipationApplicationController.java
approveParticipationApplication() 메서드 리팩토링
cancelParticipationApplication()
💬리뷰 요구사항