25일차

2024. 8. 30. 18:26FCB2O4

오늘은 어제 구현하려다 실패한 채팅 밴 먹이기 기능을 다시 도전해보았다.

 

곰곰이 생각해본 결과 chatable(채팅 권한 변수)의 변화하는 값을 관리자만 가지고 있으면 안되고 이걸 freezeChat이나 WebCam처럼 WebSocket을 통해 전파해야한다고 보았다.

 

따라서 LiveStreamingPage에도 웹소켓 관련 코드를 추가. 기존에 쓰던 코드를 재활용 했다.

 

useEffect(() => {
    const socket = new SockJS('http://localhost:9000/ws'); // WebSocket 엔드포인트
    const client = new Client({
        webSocketFactory: () => socket,
        connectHeaders: {},
        debug: function (str) {
            console.log('STOMP Debug:', str);
        },
        onConnect: function (frame) {
            console.log('STOMP Connected:', frame);
            setStompClient(client);

            // 채팅 권한 업데이트 구독
            client.subscribe('/topic/chatPermissionUpdate', (response) => {
                const updatedMember = JSON.parse(response.body);
                if (loginMember.memberId === updatedMember.memberId) {
                    const newChatable = updatedMember.chatable === 'Y';
                    setChatable(newChatable);
                }
            });

        },
        onStompError: function (frame) {
            console.error('STOMP Error:', frame);
        },
        onWebSocketError: function (error) {
            console.error('웹소켓 에러:', error);
        }
    });

    client.activate();

    return () => {
        if (client) {
            client.deactivate();
        }
    };
}, [loginMember]);

 

그리고 서버에 요청을 전달하는 함수를 추가한다.

 

// 채팅 금지 / 허용 전환
const toggleChatable = (chatable) => {
    axios.put("/switch/chat", null, {
        params: {
            memberId: searchWord,
            chatable: chatable
        }
    })
        .then(res => {
            stompClient.publish({
                destination: '/app/chat.PermissionUpdate',
                body: JSON.stringify({
                    memberId: searchWord,
                    chatable
                })
            });
        })
        .catch(error => {
            console.error('채팅 상태 업데이트 오류:', error);
        });
};

 

그리고 백엔드의 ChatController

//ChatController.java

@Autowired
private SimpMessagingTemplate messagingTemplate;


//중략


// 채팅 금지 / 허용 전환
@PutMapping("/switch/chat")
public ResponseEntity<String> switchAuthToChat(
        @RequestParam("memberId") String memberId,
        @RequestParam("chatable") char chatable) {

    String res = chatService.switchAuthToChat(memberId, chatable);

    // Member 객체 생성하여 업데이트 내용 전송
    Member member = new Member();
    member.setMemberId(memberId);
    member.setChatable(chatable);

    // 변경된 채팅 권한을 모든 클라이언트에게 전송
    messagingTemplate.convertAndSend("/topic/chatPermissionUpdate", member);

    return ResponseEntity.ok(res);
}

 

어제 작성했던 코드와 비교해보면 다음 부분이 다르다.

 

@Autowired
private SimpMessagingTemplate messagingTemplate;


// Member 객체 생성하여 업데이트 내용 전송
Member member = new Member();
member.setMemberId(memberId);
member.setChatable(chatable);

// 변경된 채팅 권한을 모든 클라이언트에게 전송
messagingTemplate.convertAndSend("/topic/chatPermissionUpdate", member);

 

리액트에서 전달받은 memberIdchatable 값을 Member에 넣는 과정을 추가했다.

 

또한 

 

// 변경된 채팅 권한을 모든 클라이언트에게 전송
messagingTemplate.convertAndSend("/topic/chatPermissionUpdate", member);

 

이 구문 때문에 기존에 쓴 

 

    //채팅창 동결/재개 전환
    @MessageMapping("/chat.freezeChat")
    @SendTo("/topic/freezeChat")
    public boolean chatFreezing() {
        freezeChat = !freezeChat;
        return freezeChat;
    }

    //채팅창 동결/재개 상태 전파
    @GetMapping("/chat/freezeChat")
    public boolean getChatFreezing() {
        return freezeChat;
    }
    
    //스트리밍 시작/종료 전환
    @MessageMapping("/chat.streaming")
    @SendTo("/topic/streaming")
    public boolean streamingBegin() {
    	streamingBegin = !streamingBegin;
        return streamingBegin;
    }
    
    //스트리밍 시작/종료 상태 전파
    @GetMapping("/chat/streaming")
    public boolean getStreamingBegin() {
    	return streamingBegin;
    }

 

이런 구문을 안써도 된다는 것을 깨달았다.

 

그리고 LiveChat.js에서 chatable 값을 받아 그걸 활용해야한다.

 

const LiveChat = ({ chatable }) => {

//중략...
  
  // chatable 상태 변경 알림
  useEffect(() => {
      if (!chatable) {
        alert('채팅이 금지되었습니다.');
      } else {
        alert('채팅이 허용되었습니다.');
      }
  }, [chatable]);

 

그런데 문제가 발생. 페이지에 진입할 때마다 알림창이 여러개 뜬다.

 

그래서 useRef를 사용해 사용자의 상태를 유지 시켜 굳이 접속할 떄마다 알림창이 뜨지 않도록 했다.

 

  const prevChatableRef = useRef(chatable);

//중략...

  // chatable 상태 변경 알림
  useEffect(() => {
    if (prevChatableRef.current !== chatable) {
      if (!chatable) {
        alert('채팅이 금지되었습니다.');
      } else {
        alert('채팅이 허용되었습니다.');
      }
      prevChatableRef.current = chatable;
    }
  }, [chatable]);

 

 

이랬더니 알림창이 계속 뜨는 문제는 해결했는데 가장 큰 문제가 발생. 채팅이 금지된 사용자가 다른 페이지를 갔다오면 채팅 금지가 풀려있는 이슈가 발견됐다.

 

알아보니 로컬 스토리지라는 것을 사용하면 사용자의 정보를 유지할 수 있었다.

 

따라서 LiveStreamingPage에 로컬 스토리지 관련 코드를 삽입

 

const LiveStreamingPage = () => {


//중략....


    useEffect(() => {
        // localStorage에서 chatable 상태를 가져옴
        const savedChatable = localStorage.getItem('chatable');
        if (savedChatable !== null) {
            setChatable(JSON.parse(savedChatable));
        } else {
            // 기본값을 true로 설정
            setChatable(true);
        }
    }, []);


	//중략...


    useEffect(() => {


	//중략....


                // 채팅 권한 업데이트 구독
                client.subscribe('/topic/chatPermissionUpdate', (response) => {
                
                
                //중략..
                
                
                        // 변경된 chatable 값을 로컬 스토리지에 저장
                        localStorage.setItem('chatable', JSON.stringify(newChatable));
                    }
                });
                
    //중략...
    
    
    // 채팅 금지 / 허용 전환
    const toggleChatable = (chatable) => {


	//중략...


                // chatable 값을 로컬 스토리지에 저장
                localStorage.setItem('chatable', JSON.stringify(chatable === "Y"));
            })
            .catch(error => {
                console.error('채팅 상태 업데이트 오류:', error);
            });
    };

 

이걸로 해결. 이제 테스트

 

채팅 금지를 눌렀을 때 화면. 다른 사용자의 채팅을 금지시킨다.

 

다른 페이지를 다녀와도 채팅 금지 상태가 유지됨을 확인

 

이걸로 내가 하려던 모든 기능은 정말로 끝. 이제 팀원들과 통합, 배포하면서 충돌나는 요소들만 고치면 프로젝트가 끝난다.

'FCB2O4' 카테고리의 다른 글

27일차  (1) 2024.09.13
26일차  (0) 2024.09.09
24일차  (0) 2024.08.29
23일차  (0) 2024.08.29
22일차  (2) 2024.08.28