우리팀은 채팅 서비스의 통신 방식을 [HTTP-Polling, Websocket] 후보로 생각을 했었다.
이 두개의 통신 방식에 대해서는 많은 레퍼런스가 존재하기에 Websocket 이용해 통신을 하는
방법이 성능적으로 우수하다는 것을 알 수 있었다.
서비스의 Scope 를 작게 기획하여 두개의 기술을 모두 접목해 이 둘의 차이점을 알아보려고 한다.
HTTP-Polling
•
클라이언트가 n초 간격으로 request를 서버로 계속 날려서 response를 전달 받는 방식이다.
장점
•
기본 CRUD 개념으로 구현할 수 있기에 구현하기 쉽다.
단점
•
서버측에서 보낼 내용이 없어도 클라이언트는 알 수 없기 때문에 계속 request를 통한 확인이 필요하다.
•
요청 간격을 늘린다면 실시간성이라고 보기 어렵다.
◦
요청 간격을 줄인다면 이에 비례하여 서버 부하 증가
Websocket
•
웹소켓은 HTML5표준 기술로, 사용자의 브라우저와 서버 사이의 동적인 양방향 연결 채널을 구성한다.
•
Websocket API를 통해 서버로 메세지를 보내고, 요청 없이 응답을 받아오는 것이 가능하다.
장점
•
하나의 HTTP 접속으로 양방향 메시지를 자유롭게 주고받을 수 있다.
단점
•
Cross Browser 문제
◦
브라우저 중 버전에 따라 지원을 안 하는 경우도 있다.
•
Stateful
◦
Stateless를 지향하는 일반 HTTP와는 다르게 상태를 유지하는 Stateful 한 성격을 가지고 있다.
◦
연결을 유지해야 하기 때문에 부하가 발생할 수 있다.
◦
비정상적으로 연결이 끊어졌을 때 적절한 대응이 필요하다.
채팅방에 사용자가 들어가면 채팅을 매초 마다 조회하는 방식
@Transactional(readOnly = true)
public ChatRoomDetailGetRes getDetailChatRoom(Long chatRoomId, User user) {
isChatRoomMember(chatRoomId, user.getId()); // 채팅방에 존재하는 사용자 인지 Check
ChatRoom chatRoom = findById(chatRoomId);
List<ChatRes> chatList = chatRepository.findAllByChatRoom_Id(chatRoomId) // 해당 채팅방 내에 있는 채팅을 모두 가져옴
.orElseThrow(() -> new GlobalException(NOT_FOUND_CHAT))
.stream()
.map(ChatRes::to)
.toList();
return ChatRoomDetailGetRes.builder()
.title(chatRoom.getTitle())
.chatResList(chatList)
.build();
}
Java
복사
매초 마다 Query가 나가는 것을 확인
Websocket
WebSocket은 서버와 클라이언트 간에 Socket Connection을 유지해서
언제든 양방향 통신 또는 데이터 전송이 가능하도록 하는 기술이다.
아래 그림은 웹소켓 핸드쉐이크 과정을 그림으로 나타난 것이다.
클라이언트가 ws://localhosy/stomp 로 요청을 보냈을 때 담기는 첫 요청의 헤더
GET /stomp
Host: localhost:8080
Origin: http://localhost:5173
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: eZSHFuOwZzTm8h1B1dpY3g==
Sec-WebSocket-Version: 13
Java
복사
•
Connection : 업그레이를 목적으로 하는 요청
•
Upgrade: client가 업그레이드 되길 원하는 프로토콜
•
Sec-WebSocket-Key : 브라우저에서 생성한 키
•
Sec-WebSocket-Version : 웹소켓 프로토콜 버전