그동안 참 힘든 시간을 보냈다. 이전 프로젝트에서 나때문에 일정이 늦어져서 자괴감과 무력함을 많이 느꼈다. 그래서 이번 프로젝트에서는 이 악물고 하고 있는것 같다. 우린 웹소켓을 이용한 실시간 인디언 포커게임을 구현해 보기로 했다. 일단 백엔드 각자 웹소켓을 공부해보고 오기로 하였다. 공부하던 중 각기 다른 다중 채팅방을 구현했다. 거기서 부터 자신감이 조금 붙었던것 같다. 지금은 나아가서 게임방을 거의 다 구현한 상태인것 같다. 각기 다른 유저가 로그인해도 게임방 참여&나가기 로직과 유저가 다 나가면 그 게임방이 폭파되는 로직이 작동이 잘되는것같다. 이 과정에서도 한번의 고비가 있었다. 처음엔 그냥 스프링 시큐리티와 합쳐서 AuthenticationPrincipal를 써서 로그인한 사용자의 정보를 불러오면 될것이라고 생각했다. 그런데 그게 안됐다. 알아보니 인터셉터를 만들야 한다고 했다. 인터셉터를 만들었는데 역직렬화 문제가 발생했다.
enhandled exception from message handler method
org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Cannot construct instance of `cohttp://m.service.indianfrog.global.security.UserDetailsImpl` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"{}"; line: 1, column: 2]
이걸 SecurityContextHolder.getContext().setAuthentication(authentication);를 사용해서 해결했다.
여기서 또 다른 문제가 발생했다.
@MessageMapping("/game.join/{roomId}")
public void joinGame(@DestinationVariable Long roomId, Principal principal) {
String email = principal.getName();
logger.info("이메일이 뭘까?"+email);
try {
GameRoomDto gameRoom = gameRoomService.addParticipant(roomId, email);
messagingTemplate.convertAndSend("/topic/gameRoom/" + roomId, gameRoom.getParticipants());
} catch (IllegalStateException e) {
// 게임방이 꽉 찼을 때의 예외 처리
}
이렇게 했는데 principal의 값이 null이 되는 문제가 발생했다. 분명 토큰도 발급되는것을 확인했는데도 null값이 들어갔다.
그래서 일단 html에서 유저의 이메일을 저장하고 그냥 string으로 유저의 이메일 값을 불러오는 방식으로 했다.
@MessageMapping("/game.join/{roomId}")
public void joinGame(@DestinationVariable Long roomId, String participant) {
try {
GameRoomDto gameRoom = gameRoomService.addParticipant(roomId, participant);
messagingTemplate.convertAndSend("/topic/gameRoom/" + roomId, gameRoom.getParticipants());
} catch (IllegalStateException e) {
// 게임방이 꽉 찼을 때의 예외 처리
// 적절한 예외 처리 로직 추가 예정
}
}
내일은 이 임시방편을 수정하려고 한다. 항해과정 통틀어서 가장 치열했던 한주였지만 가장 뿌듯했던 한주였기도 하다. 내가 더 열심히 해야 팀원들이 조금 더 편안하게 프로젝트를 진행할수 있다는것을 알기에 더 공부하고 더 나아가고자 한다.