경매 입찰 시 웹소켓 연결을 ENTER, TALK을 동시에 한다면 bid-message table에 동시에 2개의 데이터가 저장되는 문제였음
—>서버 코드의 오류
b. 입장시 바로 출력되는 ENTER인 메시지인 경우 클라이언트측에서 세션값에 이전 경매게시글에 방문했었던 호가 가격이 ENTER 메시지로 출력되는 오류
—> 서버 코드의 오류
1번문제에 관한 의사결정
1. 1:1채팅 및 전체 채팅과 별도로 해당 경매 가격만을 실시간으로 주고 받을수 있는 매핑주소가 필요함
2. 상세화면으로 들어가자마자 웹소켓을 연결해 해당 유저를 입장시킴
3. 입장한 유저가 호가를 입력
4. 입력한 호가가 경매 테이블의 호가 컬럼에 반영되고 저장됨
5. 입력된 호가를 레디스에도 저장
6. 채팅 메시지를 RedisTemplate를 이용한 convertAndSend 해당 경매 게시글의 호가를 출력함.
- —>입찰 가격을 올릴 때마다 웹소켓에 해당 유저가 입장한다고 설정 요약 하면 해당 경매 게시글의 호가 채팅방을 만듦
클라이언트
methods: {
findRoom: function () {
axios.get('/chat/room/' + this.roomId).then(response => {
this.room = response.data;
});
},
sendMessage: function () {
// 호가 전용 메세지 매핑 주소
ws.send("/app/chat/bid", {}, JSON.stringify({
type: 'TALK',
roomId: this.roomId,
sender: this.sender,
message: this.message
}));
this.message = '';
},
recvMessage: function (recv) {
this.messages.unshift({
"type": recv.type,
"sender": recv.type == 'ENTER' ? '[알림]' : recv.sender,
"message": recv.message
})
}
}
서버
// 호가 주소
@MessageMapping("/chat/bid")
public void enterBid(BidMessageDto message) {
chatService.saveBid(message);
}
@Transactional
public void saveBid(BidMessageDto message) {
if (BidMessage.MessageType.ENTER.equals(message.getType())) {
chatRoomService.enterChatRoom(message.getRoomId());
}
Member member = memberRepository.findByNickName(message.getSender()).orElseThrow(
() -> new IllegalArgumentException("해당 닉네임 없음")
);
String nickName = member.getNickName();
LocalDateTime now = LocalDateTime.now();
String createdAtString = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.KOREA));
BidMessage bidMessage = new BidMessage(message, nickName, createdAtString);
//db에 저장
bidMessageRepository.save(bidMessage);
//redis에 저장
BidMessage bidMessageRedis = chatMessageService.saveBid(bidMessage);
System.out.println("==================redis 시간 :============" + bidMessageRedis.getCreatedAt());
Long nowPrice = Long.parseLong(bidMessage.getMessage());
Auction auction = auctionRepository.findByBidRoomId(bidMessage.getRoomId());
auction.updateJoinPrice(nowPrice);
Participant participant = new Participant(member, auction);
participantRepository.save(participant);
Long participantCnt = participantRepository.countAllByAuctionId(auction.getId());
auction.updateParticipantCnt(participantCnt);
auctionRepository.save(auction);
JoinPrice joinPrice = new JoinPrice(member.getId(), auction.getId(), nowPrice);
joinPriceRepository.save(joinPrice);
redisPublisher.publishBid(ChatRoomService.getTopic(bidMessage.getRoomId()), bidMessage);
}
2번문제에 관한 의사결정
@Transactional
public void saveBid(BidMessageDto message) {
// ENTER메시지인 경우
if (BidMessage.MessageType.ENTER.equals(message.getType())) {
chatRoomService.enterChatRoom(message.getRoomId());
} else { // TALK메시지인 경우 위에서 else문을 추가하지 않아서 ENTER에 가격이
// 본문에 타고 내려와서 저장되었음
Member member = memberRepository.findByNickName(message.getSender()).orElseThrow(
() -> new IllegalArgumentException("해당 닉네임 없음")
);
String nickName = member.getNickName();
System.out.println("닉네임" + nickName);
LocalDateTime now = LocalDateTime.now();
String createdAtString = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.KOREA));
BidMessage bidMessage = new BidMessage(message, nickName, createdAtString);
//db에 저장
bidMessageRepository.save(bidMessage);
//redis에 저장
BidMessage bidMessageRedis = chatMessageService.saveBid(bidMessage);
System.out.println("==================redis 시간 :============" + bidMessageRedis.getCreatedAt());
Long nowPrice = Long.parseLong(bidMessage.getMessage());
Auction auction = auctionRepository.findByBidRoomId(bidMessage.getRoomId());
//Auction auction = auctionRepository.findByMember(member);
auction.updateJoinPrice(nowPrice);
// 해당 경매 게시글에 호가를 입력할때마다 내가 참여한 경매의 숫자가 늘어났던 오류를 해결한 코드.
if (participantRepository.existsByMemberIdAndAuctionId(member.getId(), auction.getId())) {
auctionRepository.save(auction);
JoinPrice joinPrice = new JoinPrice(member.getId(), auction.getId(), nowPrice);
joinPriceRepository.save(joinPrice);
redisPublisher.publishBid(ChatRoomService.getTopic(bidMessage.getRoomId()), bidMessage);
} else {
Participant participant = new Participant(member, auction);
participantRepository.save(participant);
Long participantCnt = participantRepository.countAllByAuctionId(auction.getId());
auction.updateParticipantCnt(participantCnt);
auctionRepository.save(auction);
JoinPrice joinPrice = new JoinPrice(member.getId(), auction.getId(), nowPrice);
joinPriceRepository.save(joinPrice);
System.out.println("===============================================");
System.out.println(bidMessage.getType());
System.out.println(bidMessage.getRoomId());
System.out.println(bidMessage.getSender());
System.out.println(bidMessage.getMessage());
System.out.println(bidMessage.getCreatedAt());
System.out.println(bidMessage.getNickName());
System.out.println("===============================================");
//sendingOperations.convertAndSend("/topic/chat/room/" + bidMessage.getRoomId(), bidMessage);
System.out.println("================================bidMessage roomid :" + bidMessage.getRoomId());
redisPublisher.publishBid(ChatRoomService.getTopic(bidMessage.getRoomId()), bidMessage);
}
}
}