TIL

77일차 TIL

ohs020105 2025. 3. 3. 20:30

채팅 웹소켓 관련 트러블 슈팅

 

1. 실시간 연결 인증 문제

// 문제: 웹소켓 연결 시 인증 토큰 검증 실패
// 원인: 클라이언트에서 토큰이 제대로 전달되지 않거나, 서버에서 토큰 검증 로직이 불완전
// 해결:
@WebSocketGateway({
  namespace: 'chatting',
  cors: {
    origin: ['http://localhost:3000', 'http://127.0.0.1:5500'],
    credentials: true,
    allowedHeaders: ['Authorization'],
  },
})

 

2. 채팅 메세지 중복 전송

// 문제: 같은 메시지가 여러 번 전송되는 현상
// 원인: 이벤트 리스너가 중복 등록되거나, 서버에서 메시지를 여러 번 브로드캐스트
// 해결: 메시지 전송 로직 단일화
socket.on('message', (data) => {
  // 중복 체크 로직 추가
  const messageId = `${data.userId}_${Date.now()}`;
  if (processedMessages.has(messageId)) return;
  processedMessages.add(messageId);
});

 

 

3. 실시간 사용자 상태 관리

// 문제: 사용자 연결 해제 시 상태 업데이트 지연
// 해결: 명시적인 연결 해제 처리
@SubscribeMessage('leaveRoom')
async handleLeaveRoom(@MessageBody() data: { userId: number; roomId: number }) {
  // 먼저 퇴장 메시지를 브로드캐스트
  await this.server.to(`room_${data.roomId}`).emit('userLeft');
  // 잠시 대기하여 메시지가 전송될 시간을 확보
  await new Promise(resolve => setTimeout(resolve, 500));
  // 그 후 실제 연결 해제
  await client.leave(`room_${data.roomId}`);
}

 

4. 채팅 이미지 업로드 처리

// 문제: 이미지 업로드 시 진행률 표시와 실시간 업데이트 불가
// 해결: 프로그레스 바 구현과 실시간 상태 업데이트
async function handleFileSelect(event) {
  const progressDiv = document.getElementById('upload-progress');
  progressDiv.style.display = 'block';
  
  const formData = new FormData();
  formData.append('file', file);
  
  const response = await fetch(`/chattingroom/${currentRoomId}/upload`, {
    method: 'POST',
    body: formData,
    onUploadProgress: (progressEvent) => {
      const percentCompleted = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total
      );
      updateProgressBar(percentCompleted);
    },
  });
}