Skip to content
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

Feat #31 채팅 고도화 #31

Merged
merged 37 commits into from
Jan 17, 2025
Merged

Feat #31 채팅 고도화 #31

merged 37 commits into from
Jan 17, 2025

Conversation

hyxklee
Copy link
Member

@hyxklee hyxklee commented Jan 14, 2025

📌 관련 이슈

관련 이슈 번호 #28
Close #

🚀 작업 내용

  • 이전 메시지 조회, 채팅방 나가기 API를 구현했습니다
  • 이전 메시지 조회는 Slice를 이용한 무한 스크롤로 구현을 했고, 마지막 구독 해제 일자를 저장해서 클라이언트로 넘겨줘서 새로운 메시지임을 알 수 있게 구현했습니다
  • 채팅방 재 입장시 새로운 메시지는 전부 조회가 되어야하기 때문에 pageSize에 상관없이 동적으로 새로운 채팅 개수를 파악해서 조회하도록 하였고, pageSize보다 적다면 pageSize 만큼 조회하도록 하였습니다.
  • 채팅방 나가기는 중간 테이블인 채팅 참여자 객체를 삭제시키며 퇴장 메시지를 브로드 캐스팅하게 구현했고, 나간 사람의 채팅도 남아있는게 맞다고 판단해 유지했습니다.
  • 커스텀 예외처리와 연결 해제시 이벤트 리스너를 구현했습니다.
  • 커스텀 예외처리의 경우 /user/queue/errors를 구독하면 에러 메시지를 받을 수 있도록 구현했고, @sendto를 사용해 해당 클라이언트에게만 전달되도록 구현했습니다. 차후 상세한 예외 처리를 추가할 계획입니다
  • 동일한 방에 대한 같은 참여자가 중복 구독을 할 수 없게 막아뒀습니다.

📸 스크린샷

image image image image image image

📢 리뷰 요구사항

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성

@hyxklee hyxklee added 🔨 Refactor 코드 리팩토링 ✨ Feature 기능 개발 및 요구사항 변경 반영 labels Jan 14, 2025
@hyxklee hyxklee self-assigned this Jan 14, 2025
@hyxklee hyxklee changed the title Feat # 채팅 고도화 Feat #31 채팅 고도화 Jan 14, 2025
Copy link
Member

@koreaioi koreaioi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자주 보면서 리뷰 추가하도록 하겠습니다!

Comment on lines +69 to +71
if (chattingParticipantService.checkSubscription(chattingRoom, members)) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복 구독 시 DuplicateSubscribeException 예외를 던지는 대신 return 하는 이유가 궁금합니다!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    private void checkDuplicateSubscription(ChattingParticipant chattingParticipant) {
        if (chattingParticipant.getStatus() == Status.ACTIVE) {
            throw new DuplicateSubscribeException();
        }
    }

중복 구독시 해당 메서드에서 예외를 날려주고 있습니다!

Copy link
Member

@huncozyboy huncozyboy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 !
전체적으로 깔끔해보여요


public interface ChattingMessageRepository extends MongoRepository<ChattingMessage, String> {
Slice<ChattingMessage> findAllByRoomIdAndTimeStampAfterOrderByTimeStampDesc(Long roomId, LocalDateTime joinedAt, Pageable pageable);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

roomId랑 timeStamp 필드를 기준으로 데이터를 검색하고 내림차순으로 정렬 할때 $gt로 greater than이랑 $lt로 less than를 표현해주는 방식은 처음 봤는데 많이 배웠습니다

@@ -1,5 +1,5 @@
package com.gachtaxi.domain.chat.entity.enums;

public enum MessageType {
MESSAGE, ENTER
MESSAGE, ENTER, EXIT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MESSAGE만 존재하는 것이 아닌, MessageType 으로 ENTER와 EXIT를 지정해주신 이유는 채팅방 입장/퇴장 이벤트를 처리해주기 위한 설계로 이해했는데 맞을까요 ??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 입장 메시지와 퇴장 메시지는 최초 입장, 채탕방 완전 퇴장 시에만 별도의 UI로 표시가 되니까 클라이언트 측에서 구분이 될 수 있도록 타입을 지정을 해뒀습니다


// ChattingParticipant chattingParticipant = ChattingParticipant.of(chattingRoom, members);
// chattingParticipantRepository.save(chattingParticipant);
if (chattingParticipantService.checkSubscription(chattingRoom, members)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

방 구독이랑 퇴장과 같은 메서드를 구분해서 구현해준 점은 좋지만, 해당 subscribeChatRoom 메서드에서 checkSubscription을 호출할 때, 메서드 내부적으로 findByChattingRoomAndMembers를 통해 구독 상태를 조회하는 과정에서 중복되는 쿼리 호출이 생겨서 성능에 지장이갈 수도 있다고 판단했습니다.
현재 API가 채팅과 같이 트래픽이 많은 API여서 최적화가 더 필요하다고도 생각되었습니다

Optional<ChattingParticipant> optionalParticipant = chattingParticipantRepository.findByChattingRoomAndMembers(chattingRoom, members);

if문 밖에서 이렇게 미리 구독 상태를 조회한 뒤, 결과를 재사용하는 방식의 설계는 어떻게 생각하시는지 궁금합니다 !

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어떤 부분에서 중복 쿼리가 생기는지 다시 말씀해주실 수 있으실까요??
현재 구현된 상태에서는 멤버, 채팅방, 참여자 이렇게 3개의 select 쿼리가 날라갑니다!
말씀해 주신게 아래 코드라고 이해해서 쿼리를 비교해봤는데, 완전히 동일한 쿼리가 날라 갔습니다!

Optional<ChattingParticipant> optionalParticipant = chattingParticipantRepository.findByChattingRoomAndMembers(chattingRoom, members);

        if (chattingParticipantService.checkSubscription(optionalParticipant)) {
            return;
        }

제가 이해한 부분이 다를 수 있으니 알려주시면 다시 확인해보겠습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아아 확인했습니다 ! subscribeChatRoom 메서드 내부에서 별도로 쿼리를 호출한 후 checkSubscription 내부에서도 동일한 쿼리를 호출할 가능성에 대해서 얘기했었던거였는데, 동일한 쿼리의 형식으로 작동한다면 문제가 없을거같습니다

Copy link
Collaborator

@soyesenna soyesenna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!!
깔끔하게 잘 구현된 것 같아요!!

@@ -24,10 +28,42 @@ public class ChattingParticipant extends BaseEntity {
@JoinColumn(name = "members_id")
private Members members;

@Builder.Default
@Enumerated(EnumType.STRING)
private Status status = Status.ACTIVE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저희 서비스에 Status로 상태 관리를 하는 도메인이 많은데, 명확성을 위해 ChatStatus라는 이름으로 정의하면 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그게 조을 것 같네욥 수정하겠습니당

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 클래스가 채팅, 채팅방, 참여자 모두 사용 중이라 클래스 명만 ChatStatus로 수정하고, 내부 변수명은 status로 수정하는 건 어떠신가요??

# Conflicts:
#	src/main/java/com/gachtaxi/global/common/exception/handler/GlobalExceptionHandler.java
@hyxklee hyxklee merged commit 4f991bf into dev Jan 17, 2025
2 checks passed
@hyxklee hyxklee deleted the feat/#28/채팅-고도화 branch January 17, 2025 08:57
@hyxklee hyxklee linked an issue Jan 17, 2025 that may be closed by this pull request
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ Feature 기능 개발 및 요구사항 변경 반영 🔨 Refactor 코드 리팩토링
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feat]: #28 채팅 비즈니스 예외처리 및 고도화
4 participants