[Project] STOMP로 귓속말 기능 구현

Yumya's record·2024년 11월 25일
0

[회고] Auction Project

목록 보기
6/7
post-thumbnail

🤫 귓속말 기능

이전에 구현한 STOMP는 해당 경로를 구독한 사람 모두가 메시지를 수신하고 전송한다.
하지만 상황에 따라 한 사람에게만 전하고자 하는 말이 있을 것이며, 이를 위해 귓속말 기능을 구현했다.


🤫 구현

Config

@Override
public void configureMessageBroker(MessageBrokerRegistry brokerRegistry) {
        brokerRegistry.enableSimpleBroker("/topic", "/whisper");
        brokerRegistry.setApplicationDestinationPrefixes("/app");
}

귓속말을 위한 경로인 /whisper 경로를 추가한다.

DTO

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class WhisperDto {

    private String roomId; //채팅방 Id
    private String sender; //보내는 사람
    private String receiver; //받는 사람
    private String message; //전송할 메시지

    public void setMessage(String message) {
        this.message = message;
    }
}

전달하고자 하는 정보를 담았다.

Controller

@MessageMapping("/chat/message/whisper")
    public void messageToOne(WhisperDto whisperDto) {
        whisperDto.setMessage("[귓속말] " + whisperDto.getSender() + " : " + whisperDto.getMessage());
        simpMessageSendingOperations.convertAndSend("/whisper/" + whisperDto.getReceiver(), whisperDto);
    }

/app경로로 메시지를 전송시켜 @MessageMapping을 거치도록 한다.
이때 메시지 형태를 [귓속말] {보내는 사람} : {메시지}로 구성해 받는 사람의 귓속말 경로로 전송한다.


🤫 동작

이전에 구현했던 STOMP의 통신 과정에서 사용자 본인만 사용하는 경로를 구현해 메시지를 주고 받을 수 있도록 구현했다.

일단, 채팅방에 사용자 A와 B가 있다고 가정한다.

사용자 A와 B는 채팅방 입장할 때 /whisper/(고유 키)를 구독한다.
이 과정은 클라이언트에서 소켓을 생성한 뒤 이루어져야 한다.

A : /whisper/A 구독

ex) js에서 A의 귓속말 경로 구독
ws.connect({}, function(frame) {
	ws.subscribe("/whisper/" + A, function(message) {
	});
} 
B : /whisper/B 구독

ex) js에서 B의 귓속말 경로 구독
ws.connect({}, function(frame) {
	ws.subscribe("/whisper/" + B, function(message) {
	});
} 

그럼 이제 A는 /whisper/A의 경로로 전송되는 모든 메시지를 전송 받을 수 있다.
동일하게 B도 /whisper/B의 경로로 전송되는 모든 메시지를 전송 받을 수 있다.


이제 사용자 A가 B에게 메시지를 보내고자 한다.
그러면 사용자 A는 B에게 보낼 메시지를 DTO에 담아 /app/chat/message/whisper 경로로 전송한다.

// A -> B : 밥 먹었어?

JSON 형식으로 데이터(DTO) 전송
{
	"roomId" : 1,
    "sender" : A,
    "receiver" : B,
    "message" : "밥 먹었어?"
}

/app 경로로 메시지를 전송했기 때문에 @MessageMapping 메서드에서 메시지 형태를 다음과 같이 변환한다.

// A -> B : 밥 먹었어?

@MessageMapping 메서드에서 메시지 형태 구성
{
	"roomId" : 1,
    "sender" : A,
    "receiver" : B,
    "message" : "[귓속말] A : 밥 먹었어?"
}

@MessageMapping 메서드에서 해당 메시지를 /whisper/B로 보내게 되고, B는 해당 경로를 구독하고 있기 때문에 메시지를 받게 된다.

// B의 화면

[귓속말] A : 밥 먹었어?

이제 B가 A에게 답장하려면 어떻게 될까.
위의 과정에서 보내는 사람과 받는 사람만 달라지게 된다.

// B -> A : 응, 먹었어.

(1) JSON 형태로 데이터 전송
{
	"roomId" : 1,
    "sender" : B,
    "receiver" : A,
    "message" : "응, 먹었어."
}
-> /app/chat/message/whisper 경로로 전송


(2) @MessageMapping 메서드에서 메시지 형태 구성
{
	"roomId" : 1,
    "sender" : B,
    "receiver" : A,
    "message" : "[귓속말] B : 응, 먹었어."
}
-> /whisper/A 경로로 전송

(3) A의 화면

[귓속말] B : 응, 먹었어.

A가 /whisper/A 경로를 구독했기 때문에 해당 메시지를 수신하게 되면서 1대 1로 통신이 가능하게 된다.

따라서 A와 B가 귓속말로 이야기할 수 있게 되었다!


이제 다음에는 채팅방 생성자가 채팅을 못하도록 막을 것이다.
원래는 채팅방에서 채팅방 생성자는 방장이라는 개념으로 존재해 여러 권한을 가진다.
하지만 내가 지금 구현하고 있는 프로젝트에서는 방장이 채팅방 내에 개입해서는 안된다고 생각해 이 기능을 구현하고자 한다. ᐝ҉*_(ˆ. ̫ . ˆ_)

profile
🍀 ٩(ˊᗜˋ*)و 🍀

0개의 댓글