웹 소캣을 활용한 채팅을 구현 할려고한다. 전반적인 작업이 처음 하는 작업이다 보니깐 실수가 많았다. stemp를 사용하는데 특정 컴퍼넌트 안에서 구독해야만 사용할수 있다는 걸 모르고 js파일를 따로 만들어서 axios로 인스턴스로 만들어서 api를 각 함수로 만들어 관리하는것 처럼 관리해서 import해서 리덕스스토어 안에 미들웨이로 컴퍼넌트에서 구독해서 사용하게 로직을 만들었는데 서버와 연결이 안되는거다 한참을 찾다가 stomp를 구독방식으로 컴퍼넌트 안에서만 선언 해야 한다는걸 알았고 다시는 초보적인 실수를 하지 않을러고 한다.
웹소캣이란?
Transport protocol의 일종으로 쉽게 이야기하면 웹버전의 TCP 또는 Socket이라고 이해하면 된다.
WebSocket은 서버와 클라이언트 간에 Socket Connection을 유지해서 언제든 양방향 통신 또는 데이터 전송이 가능하도록 하는 기술이다.
사용이유
서버와 클라이언트 간의 Socket connection같은 영구적인 연결이 되어있지 않고 클라이언트 쪽에서 필요할때 Request를 할때만 서버가 Response를 하는 방식으로 통신이 진행되는 한방향 통신이다. 이럴경우 서버쪽 데이터가 업데이트 되더라도 클라이언트 쪽에는 화면은 Refresh하지 않는한 변경된 데이터가 업데이트 되지 않는 문제가 발생한다. 이런 문제는 일반적은 웹어플리케이션에서는 기존의 있던 임시방편인 Long polling이라던가 Ajax를 사용해도 어느정도 해결이 가능하지만 데이터의 빠른 업데이트가 아주 중요한 요소 중에 하나인 어플리케이션에서는 실시간 업데이트가 아주 중요하기 때문에 Web Socket이 아주 중요한 기술로 사용되고 있다.
Web Socket은 Stateful protocol이기 때문에 클라이언트와 한 번 연결이 되면 계속 같은 라인을 사용해서 통신하기 때문에 HTTP 사용시 필요없이 발생되는 HTTP와 TCP연결 트래픽을 피할 수 있다. 마지막으로 Web Socket은 HTTP와 같은 포트(80)을 사용하기에 기업용 어플리케이션에 적용할 때 방화벽은 재설정 하지 않아도 되는 장점이 있다.
실시간 네트워킹 (Real Time-Networking)
웹 환경에서 연속된 데이터를 빠르게 노출ex) 채팅, 주식, 비디오 데이터(youtube)
여러 단말기에 빠르게 데이터를 교환
작동원리
서버와 클라이언트 간의 WebSocket연결은 HTTP프로토콜을 통해 이루어집니다. 만약 연결이 정상적으로 이루어 진다면 서버와 클라이언트 간에 WebSocket연결이 이루어지고 일정 시간이 지나면 HTTP연결은 자동으로 끊어집니다.
HTTP통신방법과 WebSocket의 차이점
결정적인 차이는 프로토콜이다.
WebSocket 프로토콜은 접속 확립에 HTTP를 사용하지만, 그 후 통신은 WebSocket 독자의 프로토콜로 이루어진다.
또한, header가 상당히 작아 overhead가 적은 특징이 있다. 장시간 접속을 전제로 하기 때문에, 접속한 상태라면 클라이언트나 서버로부터 데이터 송신이 가능하다. 더불어 데이터의 송신과 수신에 각각 커넥션을 맺을 필요가 없어 하나의 커넥션으로 데이터를 송수신 할 수 있다.
import Stomp from 'stompjs';
import SockJS from 'sockjs-client';
import { getCookie } from '../../shared/Cookie';
const Component = () =>{
const devTarget = `${서버URL}/ws-stomp`;
const TOKEN = getCookie('-');
const sock = new SockJS(devTarget);
const ws = Stomp.over(sock);
// 서버 연결과 서버에서 바로 통신해서 들어오는 데이터 값을 리덕스 스토어에 저장한다.
const wsConnectSubscribe = Id => {
try {
ws.debug = null;
// 서버 연결 요청
ws.connect({ token: TOKEN }, () => {
// 서버 연결 확인 하고 데이터가 내려오는 위치
ws.subscribe(`/sub/chatting/roomList/${Id}`, data => {
let recv = JSON.parse(data.body);
// 데이터를 리덕스에 저장해서 구독해야할 컴퍼넌트에 사용한다.
dispatch(ChatAction.PostChatting(recv));
scrollTomBottom();
});
});
} catch (err) {
console.log(err);
}
};
// 웹소켓이 연결될 때 까지 0.1초마다 실행하는 함수
const waitForConnection = (ws, callback) => {
setTimeout(() => {
if (ws.ws.readyState === 1) {
callback();
} else {
waitForConnection(ws, callback);
}
}, 0.1);
};
// 다른 방을 클릭하거나 뒤로가기 버튼 클릭시 연결해제 및 구독해제
const wsDisConnectUnsubscribe = () => {
try {
ws.debug = null;
// 서버 연결 취소 요청
ws.disconnect(
() => {
// 서버 연결 취소 요청 확인
ws.unsubscribe('sub-0');
clearTimeout(waitForConnection);
},
{ token: TOKEN },
);
} catch (e) {
console.log('연결 구독 해체 에러', e);
}
};
// 채팅 보내기
const sendMessage = ms => {
try {
waitForConnection(ws, () => {
ws.debug = null;
ws.send('/pub/chatting/ms', { token: TOKEN }, JSON.stringify(ms));
});
} catch (e) {
console.log(e);
}
};
.
.
.
.
.
.
}
소켓을 적용하고 더 공부를 하다보니깐 REDEX SAGA로 SOCKET.IO를 미들웨어로 관리하는 방법있다는걸 알았다. 약간 처음 하는거라 STOMP에만 억매여서 다른 생각은 생각은 하지 못한거 같다. 개발자로써 시야를 넓히고 폭 넓은 기술 스팩트럼 가질려고 노력해야겠다.
'프론트엔드 > Javascript' 카테고리의 다른 글
git 새로운 시작 (0) | 2022.01.13 |
---|---|
JavaScript란? (0) | 2021.12.25 |
자바스크립트 패키지 매니저 (0) | 2021.11.29 |
17번 문제 문자열 다루기 기본 (0) | 2021.11.08 |
jquery ajax 통신 (0) | 2021.11.06 |