WebSocket 사용하기

Bas·2021년 5월 18일
2

WebSocket이란?

  • 웹소켓 커넥션

웹소켓은 웹 어플리케이션을 위한 양방향 통신기법입니다.
웹소켓 프로토콜은 웹 브라우저와 웹 서버간의 통신을 허용합니다.
HTTP 통신과 차별화된 가장 큰 차이점은 HTTP는 클라이언트가 서버에 요청하는 것이지만, WebSocket은 서버와 클라이언트 간에 '양방향 대화(요청)'가 가능하다는 것입니다.

WebSocket으로 연결이 유지되면 메세지를 앞 뒤로 이동할 수 있으며, 이렇게 이중 통신을 사용하여 웹소켓이 TCP에서 메세지를 스트리밍 할 수있습니다.

WebSocket통신은 요즘 화두가 되고 있는 가상화폐 거래소, 실시간 채팅, 게임, 주식 차트 플랫폼 등에서 사용됩니다.

WebSocket 객체 생성하기

웹소켓을 사용하기 위해  WebSocket객체를 생성해야 합니다. 
WebSocket 생성자는 하나의 필수 파라미터와 하나의 선택 파라미터를 받습니다.

<script>

WebSocket WebSocket(
  in DOMString url,       // 연결할 URL으로, 이것은 WebSocket 서버가 응답할 URL이어야 합니다
  in optional DOMString protocols  // (옵션)
);

</script>

(옵션)
하나의 서버가 여러 개의 WebSocket 서브 프로토콜을 구현할 수 있도록 해줍니다.
예를 들어, 하나의 서버가 처리하는 상호작용이 지정된 protocols에 따라 달라지도록 할 수 있습니다. 만약 프로토콜 문자열을 지정하지 않으면 빈 문자열을 넣은 것으로 간주됩니다.

예제

웹소켓 객체를 생성하여
ws://www.example.com/socketserver 서버에 접속!

<script>

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");

</script>

서버에 Data 전송하기

한 번 연결이 수립되면 서버로 data를 전송할 수 있는데, 그 방법은 간단하다.
단순히 WebSocket오브젝트의 send()호출하여 보내고 싶은 메세지를 지정하면 된다.

<script>

exampleSocket.send("Here's some text that the server is urgently awaiting!");

</script>

보낼 수 있는 data type은 String , Blob, 또는 ArrayBuffer

onopen

그런데 연결을 맺는 것은 비동기적인 작업 + 실패하기 쉽다.
따라서 WebSocket 오브젝트를 생성 하자마자 send()로 데이터 전송하는 것은 실패할 수 있다.

그래서 우리는 연결이 수립 된 이후에만 데이터를 전송하도록 하기 위해 onopen핸들러를 정의하고, 이 위에서 작업합니다.

<script>

exampleSocket.onopen = function (event) {
  exampleSocket.send("Here's some text that the server is urgently awaiting!");
};

</script>

Data 전송에 JSON 사용하기

JSON을 사용하면 복잡한 데이터를 편리하게 보낼 수 있다.
예를 들어 채팅 프로그램이 서버와 JSON으로 캡슐화된 패킷 데이터를 주고받는 프로토콜을 상상해볼 수 있다.

<script>
// 서버를 통해 모든 Users에게 메세지 보내기

function sendText() {
	//  서버가 필요한 데이터를 모은 msg object를 구성한다.
 Construct a msg object containing the data the server needs to process the message from the chat client.
  var msg = {
    type: "message",
    text: document.getElementById("text").value,
    id:   clientID,
    date: Date.now()
  };
  
  // JSON 형식의 메세지 오브젝트를 string으로 전환하여 서버에 보내준다.
   exampleSocket.send(JSON.stringify(msg));
   
  // 유저들에게 보낸 text element를 초기화. (보냈으니까 새거로)
  document.getElementById("text").value = "";

</script>

서버로부터 데이터 수신하기

메세지가 수신되면 message이벤트가 onmessage함수로 부터 전달된다.
아래 코드로 수신되는 data를 받을 수 있다.

<script>

exampleSocket.onmessage = function (event) {
  console.log(event.data);
}

</script>

JSON 오브젝트를 받아서 처리하기

상단의 Data 전송에 JSON 사용하기에서 작업한 코드와 연결지어 생각해보도록 하겠습니다.

클라이언트에서 받을 수 있는 패킥들의 목록은

  • 로그인 핸드쉐이크
  • 메세지 text
  • 유저 목록 업데이트

위의 메세지들을 받아서 처리하는 코드는

<script>
// 서버로부터 데이터 수신하기
exampleSocket.onmessage = function(event) {
  var f = document.getElementById("chatbox").contentDocument;
  var text = "";
  // JSON.parse() : JSON 오브젝트를 자바스크립트 오브젝트로 변환
  var msg = JSON.parse(event.data);
  var time = new Date(msg.date);
  var timeStr = time.toLocaleTimeString();

  switch(msg.type) {
    case "id":
      clientID = msg.id;
      setUsername();
      break;
    case "username":
      text = "<b>User <em>" + msg.name + "</em> signed in at " + timeStr + "</b><br>";
      break;
    case "message":
      text = "(" + timeStr + ") <b>" + msg.name + "</b>: " + msg.text + "<br>";
      break;
    case "rejectusername":
      text = "<b>Your username has been set to <em>" + msg.name + "</em> because the name you chose is in use.</b><br>"
      break;
    case "userlist":
      var ul = "";
      for (i=0; i < msg.users.length; i++) {
        ul += msg.users[i] + "<br>";
      }
      document.getElementById("userlistbox").innerHTML = ul;
      break;
  }

  if (text.length) {
    f.write(text);
    document.getElementById("chatbox").contentWindow.scrollByPages(1);
  }
};

</script>

연결을 종료하기

웹 소켓 사용을 마쳤다면 close()메소드를 호출하여 연결을 종효

exampleSocket.close();

또한 연결을 닫아버리기 전에 bufferedAmount 어트리뷰트를 조사하여 아직 네트워크에 전달되지 않은 데이터가 있는지 검사하는 것도 좋은 방법.


참고 자료

MDN WebSocket을 이용하여 클라이언트 애플리케이션 작성하기

HTPP->AJAX->Websocket

HTML5를 여행하는 비(非) 웹 개발자를 위한 안내서 - 1부 웹소켓.

profile
바스버거

1개의 댓글

comment-user-thumbnail
2023년 12월 7일

안녕하세요. 질문이 있습니다.
웹소켓 연결에서 url 뿐만 아니라 haeder까지 연결하는 방법이 있나요?
백엔드 개발자가 웹소켓 url과 header 정보를 주었는데 header 연결하는 정보를 찾기가 힘들더라구요.
백엔드 개발자가 서버단에서 header 선언도 해야 하는건지 전혀 감이 안오고 있네요;
백엔드 개발자는 웹소켓 url 과 header 정보를 주고 연결하라고 해서요

답글 달기