eGovFrame(전자정부프레임워크)으로 1:1 실시간 채팅 구현 중 난관을 겪게 되었다...
💡문제였던 부분
사용자를 선택해 채팅 시작 후 메시지 전송을 해야 하는데
1. MessageService단이 실행되지 않아 messageService.insertOrUpdateMessage(msgVO);를 못 타는 것
2. 웹소켓 연결과 message send는 어찌저찌 타는데 로그에 남지 않고 새로고침해야 그제서야 로그가 뜨면서 메시지 변환 성공 -> 널포인트 익셉션으로 메시지 처리 실패...
3. 새로고침 하니까 당연히 기존 웹소켓 연결은 종료되고 새로운 웹소켓 id에 연결됨
WebSocketConfig
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new ChatWebSocketHandler(), "/user/chat{RoomId}")
.setAllowedOrigins("*");
}
}
ChatWebSocketHandler
public class ChatWebSocketHandler extends TextWebSocketHandler {
private static final Logger logger = LoggerFactory.getLogger(ChatWebSocketHandler.class);
@Autowired
private MessageService messageService;
private final List<WebSocketSession> connectedSessions = new CopyOnWriteArrayList<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
connectedSessions.add(session);
logger.info("웹소켓 연결: " + session.getId());
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
logger.info("수신된 메시지: " + payload);
// 메시지를 MessageVO로 변환
MessageVO msgVO = convertPayloadToMessageVO(payload);
if (msgVO != null) {
logger.info("메시지 변환 성공: " + msgVO);
try {
// 메시지 데이터베이스에 저장
messageService.insertOrUpdateMessage(msgVO);
logger.info("메시지 저장 또는 업데이트: " + msgVO);
} catch (Exception e) {
logger.error("메시지 처리 실패: " + e.getMessage());
}
}
}
private MessageVO convertPayloadToMessageVO(String payload) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.readValue(payload, MessageVO.class);
} catch (Exception e) {
logger.error("메시지 변환 중 오류 발생: " + e.getMessage());
return null;
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
connectedSessions.remove(session);
logger.info("웹소켓 연결 종료: " + session.getId());
}
}
챗지피티한테 물어봐도 이유를 못 찾아서 우리 회사의 천재 개발자 과장님께 도움을 요청했다...
과장님 덕분에 이유를 찾을 수 있었다... ㅠㅠㅠ
WebSocketConfig
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private ChatWebSocketHandler chatWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatWebSocketHandler, "/user/chat/{roomId}")
.setAllowedOrigins("*")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
@Autowired로 ChatWebSocketHandler 의존성 주입을 해 줘야 한다 이전에 regisrty.addHandler부분에 new ChatWebSocketHandler()로 설정해서 새로고침 할 때 그제서야 로그에 기록이 남았던 것(그치만 서비스단을 못 타서 null값이라 메서드 실행되지 않음)
@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {
... // 그외 메서드들
}
@Component로 빈 등록을 해 줘야 한다 이 어노테이션을 사용하면 Bean Configuration 파일에 Bean을 따로 등록하지 않아도 사용할 수 있다
그리고 message_SQL.xml에서
message_SQL.xml
<!-- 특정 채팅방과 발신자 기준의 메시지 확인 -->
<select id="getMessageBySenderIdAndChatRoomId" parameterType="map" resultType="MessageVO">
SELECT * FROM message
WHERE chat_room_id = #{chat_room_id}
AND sender_id = #{sender_id}
ORDER BY regisdate DESC
FETCH FIRST 1 ROW ONLY
</select>
파라미터 타입이 map인 것도 실수였다 ㅋ (왜 그랬을까...?)
그래서 MessageServiceImpl 단도 맵을 적용해 변경해 주었다
MessageServiceImpl
@Override
public int insertOrUpdateMessage(MessageVO msgVO) {
int ret = 0;
try {
logger.info("메시지 삽입 또는 업데이트 시작: ", msgVO);
if (msgVO.getRegisdate() == null) {
msgVO.setRegisdate(new Date(System.currentTimeMillis()));
}
// 기존 메시지 검색(map으로 변경)
Map<String, Object> param = new HashMap<String, Object>();
param.put("sender_id", msgVO.getSender_id());
param.put("chat_room_id", msgVO.getChat_room_id());
MessageVO existingMessage = messageMapper.getMessageBySenderIdAndChatRoomId(param);
if (existingMessage != null) {
logger.info("기존 메시지 발견, 업데이트 진행: ", existingMessage);
ret = updateMessage(msgVO);
} else {
logger.info("새 메시지 삽입 진행: ", msgVO);
ret = insertMessage(msgVO);
}
} catch (Exception e) {
logger.error("메시지 삽입/업데이트 처리 중 오류 발생: ", e);
}
return ret;
}
// map으로 변경
@Override
public MessageVO getMessageBySenderIdAndChatRoomId(int sender_id, int chat_room_id) {
Map<String, Object> param = new HashMap<String, Object>();
param.put("sender_id", sender_id);
param.put("chat_room_id", chat_room_id);
return messageMapper.getMessageBySenderIdAndChatRoomId(param);
}
}
흠 그리고 과장님이 굳이 int타입 말고 그냥 VO로 들고오는 게 편할 거라 하셨다
참고하여 코드 작성해야겠다...
그리고 챗지피티한테도 물어볼 때 생각 좀 하고 어디가 안 타는지 실행되지 않는 부분이 어딘지 분석해서 물어봐야 된다...
그리고 이클립스 설치할 때도 문제가 있었던 것 같은데 잘했는지 확인 후 프로젝트 만들어야겠다
혼날까 봐 안 물어봤다가 시간 많이 날린 것 같다 그냥 혼나고 오류 없이 진행되는 게 더 나은 것 같다 ㅠ_ㅠ
'💡 > MEMO' 카테고리의 다른 글
프로젝트 연습 (0) | 2024.12.30 |
---|---|
[JAVA] WebSocketHandler에서 date값이 안 넘어올 때 (1) | 2024.12.19 |
[JAVA] String equals시 주의할 점 (0) | 2024.11.18 |
VARCHAR와 CHAR의 차이점 (1) | 2024.11.18 |
CSS 우선순위 정리 (1) | 2024.11.14 |