33import com .back .domain .party .paryChat .dto .ChatMessageDto ;
44import com .back .domain .party .paryChat .entity .ChatMessage ;
55import com .back .domain .party .paryChat .service .ChatMessageService ;
6+ import com .fasterxml .jackson .core .JsonProcessingException ;
67import com .fasterxml .jackson .databind .ObjectMapper ;
78import io .swagger .v3 .oas .annotations .Operation ;
89import lombok .RequiredArgsConstructor ;
1617import org .springframework .messaging .handler .annotation .MessageMapping ;
1718import org .springframework .messaging .handler .annotation .Payload ;
1819import org .springframework .messaging .simp .SimpMessageSendingOperations ;
19- import org .springframework .security .core .annotation .AuthenticationPrincipal ;
20- import org .springframework .security .core .userdetails .User ;
2120import org .springframework .web .bind .annotation .*;
2221
2322@ RestController
@@ -34,53 +33,46 @@ public class WebSocketController {
3433
3534 private static final String CHAT_TOPIC = "chat-messages" ;
3635
37- @ MessageMapping ("/chat.sendMessage" ) // 클라이언트가 메시지를 보내는 경로 (예: /app/chat.sendMessage)
38- public void sendMessage (@ Payload ChatMessageDto chatMessageDto , @ AuthenticationPrincipal User user ) {
39- // 1. 메시지 발신자 설정
40- chatMessageDto .setSenderEmail (user .getUsername ());
36+ @ MessageMapping ("/chat.sendMessage" )
37+ public void sendMessage (@ Payload ChatMessageDto chatMessageDto ) {
38+ // 인증을 사용하지 않으므로, 클라이언트가 DTO에 담아 보낸 senderEmail을 그대로 사용합니다.
39+ String senderEmail = chatMessageDto .getSenderEmail ();
40+ log .info ("Message received from sender: {}" , senderEmail );
4141
42- // 2. 메시지를 해당 파티의 채팅방으로 즉시 전송 (실시간성 확보)
43- messagingTemplate .convertAndSend ("/topic/party/" + chatMessageDto .getPartyId (), chatMessageDto );
44-
45- // 3. 메시지 저장 작업을 Kafka로 오프로드 (비동기 및 안정성 확보)
42+ // 1. 메시지를 Kafka로 발행
4643 try {
47- String messageJson = objectMapper .writeValueAsString (chatMessageDto );
48- // 파티 ID를 키로 사용하여 같은 파티 메시지가 같은 파티션에 저장되도록 보장 (메시지 순서 보장)
49- kafkaTemplate .send (CHAT_TOPIC , chatMessageDto .getPartyId ().toString (), messageJson );
50- } catch (Exception e ) {
51- // Kafka Producer 실패는 (일반적으로 일시적이지만) 심각하므로 ERROR 레벨로 기록합니다.
52- log .error ("Failed to send chat message to Kafka. Message: {}, Exception: {}" , chatMessageDto , e .getMessage (), e );
53- // Kafka 전송 실패는 데이터베이스에 기록을 남기지 못할 위험이 있지만,
54- // 실시간 채팅 자체는 이미 클라이언트에 전달되었으므로 시스템을 중단하지 않고 로그만 남깁니다.
44+ String jsonMessage = objectMapper .writeValueAsString (chatMessageDto );
45+ kafkaTemplate .send ("chat-messages" , jsonMessage );
46+ } catch (JsonProcessingException e ) {
47+ log .error ("Failed to convert ChatMessageDto to JSON for Kafka: {}" , e .getMessage ());
5548 }
49+
50+ // 2. 메시지를 해당 파티의 채팅방으로 즉시 전송 (실시간성 확보)
51+ messagingTemplate .convertAndSend ("/topic/party/" + chatMessageDto .getPartyId (), chatMessageDto );
5652 }
5753
5854 @ MessageMapping ("/chat.updateMessage" )
59- public void updateMessage (@ Payload ChatMessageDto chatMessageDto , @ AuthenticationPrincipal User user ) {
60- // 인증된 사용자의 이메일을 DTO에 설정
61- chatMessageDto .setSenderEmail (user .getUsername ());
55+ public void updateMessage (@ Payload ChatMessageDto chatMessageDto ) {
56+
57+ // DTO의 senderEmail을 사용하여 권한을 확인하고 메시지 수정
58+ ChatMessage updatedMessage = chatMessageService .updateMessage (chatMessageDto );
6259
63- // 메시지를 업데이트하고 반환된 최신 정보를 브로드캐스트합니다.
64- ChatMessage updatedMessage = chatMessageService .updateMessage (chatMessageDto ); // DTO를 직접 넘기도록 수정
6560 ChatMessageDto updatedDto = new ChatMessageDto (updatedMessage );
6661 messagingTemplate .convertAndSend ("/topic/party/" + updatedDto .getPartyId (), updatedDto );
6762 }
6863
6964 @ MessageMapping ("/chat.deleteMessage" )
70- public void deleteMessage (@ Payload ChatMessageDto chatMessageDto , @ AuthenticationPrincipal User user ) {
71- // 인증된 사용자의 이메일을 가져옵니다.
72- String senderEmail = user .getUsername ();
65+ public void deleteMessage (@ Payload ChatMessageDto chatMessageDto ) {
7366
74- // 1. 서비스 메서드를 호출하여 메시지를 삭제합니다. 이 메서드는 이제 반환값이 없습니다.
67+ // DTO의 senderEmail을 사용하여 권한을 확인하고 메시지 삭제
68+ String senderEmail = chatMessageDto .getSenderEmail (); // DTO에서 Email을 가져와 사용
7569 chatMessageService .deleteMessage (chatMessageDto .getId (), senderEmail );
7670
77- // 2. 클라이언트에 삭제 사실을 알리기 위한 DTO를 생성합니다.
7871 ChatMessageDto deletedDto = new ChatMessageDto ();
7972 deletedDto .setId (chatMessageDto .getId ());
8073 deletedDto .setPartyId (chatMessageDto .getPartyId ());
81- deletedDto .setContent (null ); // 삭제되었음을 명확히 하기 위해 content를 null로 설정
74+ deletedDto .setContent (null );
8275
83- // 3. 삭제된 메시지 정보를 브로드캐스트합니다.
8476 messagingTemplate .convertAndSend ("/topic/party/" + deletedDto .getPartyId (), deletedDto );
8577 }
8678
0 commit comments