본문 바로가기

Spring

WebSocket_2

728x90

채팅 고도화

ChatMessage

  • 채팅 메시지를 주고받기 위한 DTO
@Getter
@Setter
public class ChatMessage {
    // 메시지 타입 : 입장, 채팅
    public enum MessageType {
        ENTER, TALK
    }
    private MessageType type; // 메시지 타입
    private String roomId; // 방번호
    private String sender; // 메시지 보낸사람
    private String message; // 메시지
}

ChatRoom

  • 채팅방을 구현하기 위한 DTO
  • 채팅방은 입장한 클라이언트들의 정보를 가지고 있어야 하므로 WebsocketSession 정보 리스트를 멤버 필드로 갖는다.
  • 채팅방은 입장,대화하기의 기능이 있으므로 handleAction을 통해 처리
  • 입장 시 채팅방의 session정보에 클라이언트의 session리스트에 추가 후 채팅방 메세지가 도착할 경우 채팅방의 모든 session에 메시지를 발송하면 된다.
@Getter
public class ChatRoom {
    private String roomId;
    private String name;
    private Set<WebSocketSession> sessions = new HashSet<>();

    @Builder
    public ChatRoom(String roomId, String name) {
        this.roomId = roomId;
        this.name = name;
    }

    public void handleActions(WebSocketSession session, ChatMessage chatMessage, ChatService chatService) {
        if (chatMessage.getType().equals(ChatMessage.MessageType.ENTER)) {
            sessions.add(session);
            chatMessage.setMessage(chatMessage.getSender() + "님이 입장했습니다.");
        }
        sendMessage(chatMessage, chatService);
    }

    public <T> void sendMessage(T message, ChatService chatService) {
        sessions.parallelStream().forEach(session -> chatService.sendMessage(session, message));
    }
}

ChatService

  • 채팅방을 생성, 조회, 하나의 session에 메시지 발송을 하는 서비스 구현
  • 채팅방 Map은 서버에 생성된 모든 채팅방의 정보를 모아둔다.
  • 채팅방 조회 = 채팅방 Map에 담긴 정보 조회
  • 채팅방 생성 - Random UUID로 구별ID를 가진 채팅방 객체 생성하고 Map에 추가
  • 메시지 발송 - 지정한 websocket session에 메시지 발송
@Slf4j
@RequiredArgsConstructor
@Service
public class ChatService {

    private final ObjectMapper objectMapper;
    private Map<String, ChatRoom> chatRooms;

    @PostConstruct
    private void init() {
        chatRooms = new LinkedHashMap<>();
    }

    public List<ChatRoom> findAllRoom() {
        return new ArrayList<>(chatRooms.values());
    }

    public ChatRoom findRoomById(String roomId) {
        return chatRooms.get(roomId);
    }

    public ChatRoom createRoom(String name) {
        String randomId = UUID.randomUUID().toString();
        ChatRoom chatRoom = ChatRoom.builder()
                .roomId(randomId)
                .name(name)
                .build();
        chatRooms.put(randomId, chatRoom);
        return chatRoom;
    }

    public <T> void sendMessage(WebSocketSession session, T message) {
        try {
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(message)));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }
}

Controller

@RequiredArgsConstructor
@RestController
@RequestMapping("/chat")
public class ChatController {

    private final ChatService chatService;

    @PostMapping
    public ChatRoom createRoom(@RequestParam String name) {
        return chatService.createRoom(name);
    }

    @GetMapping
    public List<ChatRoom> findAllRoom() {
        return chatService.findAllRoom();
    }
}

'Spring' 카테고리의 다른 글

Travis CI 연동 (1)  (0) 2024.04.16
CI/CD  (1) 2024.04.16
S3로 파일 업로드  (0) 2024.04.15
트랜잭션의 ACID란?  (0) 2024.04.15
트랜잭션(Transaction)  (0) 2024.04.15