채팅 서버의 경우 socket 통신을 하는 서버가 필요하다.
일반적으로 http 통신의 경우 클라이언트(Client) 요청이 있을 때 서버(Server)가 응답하고 연결을 종료하는 단방향 통신(비연결 통신)
지속적으로 데이터를 주고 받을 수 없다.
클라이언트가 서버에 접속해 콘텐츠를 요청하고 결과를 받아 사용한다.
Server와 Client가 지속적으로 연결을 유지하고 양방향으로 통신
채팅과 같은 실시간 서비스에서 많이 사용된다.
기존의 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜 RFC 6455
일반적인 socket 통신과 달리 HTTP 80 및 433 포트를 이용하여 기존 방화벽 규칙을 재사용할 수 있도록 설계되었다.
접속은 HTTO 프로토콜을 이용하고 이후 통신은 자체적인 Websocket 프로토콜로 통신하게 된다.
Websocket은 HTTP와 호환 가능하도록 설계되었으며 HTTP 요청을 시작하지만 두 프로토콜의 아키텍쳐와 프로그래밍 모델은 매우 다름
HTTP와 REST의 경우 여러 URL로 모델링된다. 어플리케이션과 상호작용하기 위해 클라이어트는 해당 URL에 접속(request-reponse-style)한다. 서버는 HTTP URL, 메소드(Method), 헤더(Hadder)를 기반으로 요청을 적절한 핸드로(Handler)로 라우팅(Routing)
일반적으로 초기 연결을 위한 URL 하나 존재
어플리케이션 내 메시지는 동일한 TCP 연결을 통해 흐른다.
비동기식 이벤트 중심의 메시지 전달 아키텍쳐를 나타낸다.
메시지 내용에 의미를 규정하지 않는 저수준 전송 프로토콜로 클라이언트와 서버가 메시지 시맨틱(Message Semantic)에 동의하지 않으면 메시지를 라우팅하거나 처리할 수 없다.
Websocket 클라이언트와 서버는 HTTP 핸드세이크(Handshake) 요청의 Sec-Websocket-Protocol
헤더를 통해 높은 수준의 메시징 프로토콜(ex. stmop)의 사용이 가능하며 없다면 독자적인 규약 마련이 필요
Websocket은 웹 페이지를 동적이고 대화식으로 구성 가능
하지만 많은 경우에서 Ajax, HTTP 스트리밍, long polliing의 조합으로 간단하고 효과적인 솔루션 제공가능
뉴스, 메일, sns피드와 같이 동적인 업데이트를 필요로 하지만 실시간으로 업데이트가 이루어질 필요가 없다.
메세지 크기가 상대적으로 작은 경우 역시 HTTP 스트리밍, polling이 효과적일 수 있다.
Websocket을 사용하는데 적합한 사례로는 짧은 대기 시간, 고주파수, 대용량의 조합의 경우를 고려해야 한다.
Spring boot gradle프로젝트 생성
기본 설정
id 'org.springframework.boot' version '2.6.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
...
sourceCompatibility = '11'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
socket 통신은 서버와 클라이언트가 1:N 관계를 가진다. 따라서 한 서버에 여러 클라이언트가 접속 가능하다.
서버에는 다수의 클라이언트가 발송한 메시지를 받아 처리할 Handler가 필요
TextWebsocketHandler
상속을 받아 Handler 작성
클라이언트에게 받은 메시지를 Console Log에 출력, 클라이언트로 환영 메시지 전송
// import 생략....
@Slf4j
@Component
public class WebSockChatHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
log.info("payload {}", payload);
TextMessage textMessage = new TextMessage("Welcome chatting sever~^^");
session.sendMessage(textMessage);
}
}
Handler를 이용하여 websocket을 활성화하기 위한 Config 파일 작성
@EnablewebSocket
선언하여 websocket 활성화
Websocket에 접속하기 위한 endpoint 설정