1차 프로젝트에 이어서 2차 때 새로운 프로젝트를 하지 않고 기존 프로젝트를 고도화하는 작업을 하기로 했다.
새로 구현할 기능을 선정했는데, 이번에 유저의 역할을 숙소 등록만 하는 호스트와 예약만 하는 게스트로 분리하게 되었다.
유저의 서비스 이용 편리성을 위하여 게스트 유저가 호스트에게 1:1 실시간 채팅 상담을 할 수 있는 기능을 구현하게 되었다.
이를 구현하기 위해 웹소켓에 대해 공부했다.
웹소켓은 양방향 통신을 위한 네트워크 프로토콜이다.
한번 연결이 성립된 이후에는 클라이언트와 서버 간 지속적인 연결을 유지하고, 이 연결을 통해 양쪽 모두에서 메시지를 자유롭게 주고받을 수 있게 해준다.
이로 인해 실시간 통신이 가능하며 채팅, 실시간 게임 등 구현할 때 사용된다.
연결이 한 번만 이루어지므로 추가적인 연결 설정 오버헤드 없이 빠르고 효율적으로 데이터를 교환할 수 있다.
메시지 프로토콜은 네트워크를 통해 메시지를 교환하기 위한 규칙과 형식을 정의한 것이다.
메시지의 형태, 교환 방법, 처리하는 방법 등을 명시하여 다양한 시스템 간의 통신을 가능하게 한다.
이를 사용함으로써 개발자는 메시지 교환의 구체적인 세부 사항을 신경쓰지 않고 데이터 교환을 위한 일관된 방법을 갖출 수 잇다.
STOMP는 많이 사용되는 메시지 프로토콜 중 하나이다.
텍스트 기반의 간단하고 가독성 높은 형식을 사용하여 클라이언트와 메시지 브로커 간의 비동기 메시지 교환을 지원한다.
여러 언어와 플랫폼에서 사용할 수 있고, 웹소켓을 포함하여 다양한 전송 계층에서 작동할 수 있다.
웹소켓은 단순히 양방향 통신 채털을 제공하는 저수준 프로토콜이기 때문에 실제로 메시지를 주고받기 위한 규약이나 형식을 정의할 필요가 있다.
이를 위해 STOMP 같은 메시지 프로토콜이 웹소켓을 기반으로 사용된다.
(메시지 프로토콜은 웹소켓 없이도 사용될 수 있다. 웹소켓이 아닌 다른 전송 계층 위에서도 사용될 수 있다. 하지만 웹 애플리케이션에서 실시간 양방향 통신을 구현하기 위해 웹소켓과 메시지 프로토콜을 함께 사용하는 경우가 많다.)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
/ws
엔드포인트를 통해 서버에 연결할 수 있게 하고, /app
으로 시작하는 목적지를 가진 메시지가 애플리케이션의 @Controller
로 라우팅되도록 한다.
/topic
으로 시작하는 목적지는 메시지 브로커가 처리해서 구독자에게 메시지를 전달하게 된다.
withSockJS()
는 SockJS 지원을 활성화하기 위해 사용된다.
SockJS는 웹 브라우저 간 호환성 문제를 해결하기 위해 설계된 Javascript 라이브러리이다.
웹소켓이 지원되지 않는 브라우저에서도 유사한 기능을 제공할 수 있게 도와주는 역할을 한다.
ChatRoom은 채팅방 정보를 저장하는 테이블이다.
각 채팅방은 한 명의 호스트와 한 명의 게스트와 연결된다.
Message는 채팅방의 각 메시지 기록을 저장하는 테이블이다.
예시 스키마
CREATE TABLE ChatRoom (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
hostId BIGINT,
userId BIGINT,
FOREIGN KEY (hostId) REFERENCES User(id),
FOREIGN KEY (userId) REFERENCES User(id)
-- 채팅방에 대한 추가 정보 필드(예: 생성 시간 등)가 포함될 수 있음
);
CREATE TABLE Message (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
chatRoomId BIGINT,
senderId BIGINT,
messageText TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (chatRoomId) REFERENCES ChatRoom(id),
FOREIGN KEY (senderId) REFERENCES User(id)
-- 메시지에 대한 추가 정보 필드(예: 읽음 상태 등)가 포함될 수 있음
);
각 Message는 하나의 ChatRoom에 속하며, 각 ChatRoom은 호스트와 게스트 사이의 대화를 나타낸다.