[포스코x코딩온] KDT-Web-8 9주차 회고2 WebSocket

Yunes·2023년 8월 28일
0

[포스코x코딩온]

목록 보기
26/47
post-thumbnail

웹의 동작 방식

웹에 연결된 컴퓨터를 클라이언트와 서버라고 하자.

  • 클라이언트 : 웹 사용자의 인터넷이 연결된 장치, 이 장치들에서 이용가능한 웹에 접근하는 소프트웨어
  • 서버 : 웹페이지, 사이트, 앱을 저장하는 컴퓨터. 클라이언트가 웹페이지에 접근하려할 때 서버로부터 클라이언트의 장치로 사용자의 브라우저에서 보여지기 위한 웹페이지의 사본이 다운로드된다.

mdn - 웹의 동작 방식 에 매우 적절한 비유를 들어 설명해주고 있다.

비유

- 도로

클라이언트 - 도로 한쪽 끝의 집

서버 - 도로 한쪽 끝의 상점

인터넷 연결 - 집과 상점 사이의 거리

TCP/IP - 주문을 하고 상점에 가고, 상품을 살 수 있게 해주는 운송장치와 같다. 또한 차 또는 자전거와 같다.

DNS - 상점에 접근하기 위해 상점의 주소를 찾는것. 웹사이트를 위한 주소록과 같다.

HTTP - 상품을 주문하기 위해 사용하는 언어와 같다.

용어 설명

인터넷 연결 - 웹에서 데이터를 보내고 받을 수 있게 해준다.

TCP/IP - Transport Control Protocol 전송 제어 규약과 Internet Protocol 인터넷 규약은 어떻게 웹을 건너 여행해야 하는지 정의하는 통신 규약이다.

DNS - Domain Name System Servers 도메인 이름 시스템 서버는 IP 주소에 이름을 붙여 사용할 수 있게해줘서 브라우저에 입력하는 웹주소 www.naver.com 를 웹사이트의 실제 IP 주소에 맞춰주는 서버이다.

HTTP - Hypertext Transfer Protocol 하이퍼텍스트 전송 규약은 클라이언트와 서버가 서로 통신할 수 있게 하기 위한 언어를 정의하는 어플리케이션 규약이다.

웹이 동작할 때 발생하는 일

브라우저에 웹 주소를 입력할 때 - 비유 - 상점으로 걸어가는 것

  1. 브라우저는 DNS 서버로 가 웹 사이트가 있는 서버의 진짜 주소를 찾는다. - 비유 - 상점의 주소 조회

  2. 브라우저는 웹사이트의 사본을 클라이언트에게 보내달라는 HTTP 요청 메시지를 서버로 전송 - 비유 - 상점으로 가서 상품 주문

  • 클라이언트와 서버 사이 전송된 모든 데이터는 TCP/IP 연결을 통해 전송
  1. 해당 메시지를 받은 서버는 클라이언트 요청을 승낙하고 200 OK 메시지 반환. 서버는 웹사이트의 파일을 데이터 패킷이라 불리는 작은 덩어리들로 브라우저에 전송 - 상점이 주문된 상품을 전달하고 우리는 그것을 집으로 가져간다.

  2. 브라우저는 이 작은 덩어리들을 완전한 웹사이트로 조립하고 보여준다. - 비유 - 상품이 집에 도착했다.

WebSocket

이미지 출처 - wallarm WebSocekt Connection vs HTTP Connection

TCP 연결을 통해 실시간 양방향 통신을 하기 위한 기술. 서버와 클라이언트 사이에 소켓 커넥션을 유지하면서 양방향 통신이 가능하게 한다.

한 서버와 클라이언트들 사이에 connection 이 수립되면 그 이후에 클라이언트와 서버는 양방향으로 메시지를 주고받을 수 있게 된다.

Socket : 프로세스가 네트워크로 데이터를 내보내거나 데이터를 받기 위한 실제적인 창구 역할을 하는 것

서버소켓 : 연결 요청을 받아들이는 역할, 클라이언트의 요청을 받아들여 실제 통신을 위한 소켓을 생성한다.

클라이언트 소켓 : 서버에 연결을 요청하고 연결이 수락되면 서버와 데이터를 주고받을 수 있는 소켓

handshake : 클라이언트가 서버로 웹소켓 연결을 요청시 서버와 클라이언트 간에 초기 핸드셰이크가 이루어지며 이 과정을 통해 웹소켓을 연결한다.

웹소켓은 HTTP 프로토콜로 Handshake 요청, 초기 통신 시작한 후 웹소켓 프로토콜로 변환해 데이터를 전송한다.

웹소켓은 일반적인 HTTP 통신과 달리 양방향 데이터를 실시간으로 전송할 수 있다. 그러기 위해 클라이언트는 서버에 소켓 연결을 한 상태로 유지된다.

HTTP 의 실시간 통신 방식

이미지 출처 : WebSockets and HTTP streaming in .NET

polling 폴링

이미지 출처 : PubNub - What is HTTP Long Polling?

HTTP 는 비연결성의 특성을 갖고 있어 실시간 통신에 적합하지 않다. 한번 요청을 보내고 응답을 받으면 연결을 종료한다.

그런데 언제 이벤트가 발생하지 모르니 적절한 간격으로 계속 요청 - 응답을 반복하는 것을 폴링 이라고 한다.

업데이트 간격이 너무 길면 업데이트가 지연되고 간격이 너무 짧으면 리소스가 낭비되고 비효율성이 발생한다.

long polling 롱 폴링

이미지 출처 : PubNub - What is HTTP Long Polling?

폴링과 같이 브라우저에서 서버로 요청을 보낼때 서버는 연결을 닫지 않고 이벤트가 발생할 때까지 연결을 유지한다.

클라이언트는 서버의 응답을 기다리고 이벤트 발생시 클라이언트에 응답을 보낸다.

클라이언트는 즉시 서버에 다른 HTTP Long polling 요청을 보낸다.

  • 일반 폴링보다 효율적이다.
  • 브라우저는 사용 가능한 업데이트를 항상 수신한다.
  • 단, 이벤트가 발생할 때까지 기다리기 때문에 요청과 응답 사이에 오랜 시간이 소요된다.
  • 실시간성이 필요한 적은 수의 클라이언트와 연결되어 있는 경우에 사용한다.

Streaming 스트리밍

이미지 출처 : PubNub - What is HTTP Long Polling?

Streaming 은 서버가 지시하기 전까지 응답이 유지되는 HTTP 요청을 말한다. 한번 HTTP 요청을 보내면 끝없이 응답을 받는다.

주로 서버에서 클라이언트로 단방향 통신이 이루어진다. ( 클라이언트에서 서버로 데이터를 보내는게 어렵다. )

polling : 일정 주기마다 서버에 계속 요청
long polling : 서버에 요청을 보내고 서버는 이벤트가 발생시 응답, 다시 연결
streaming : 서버에 연결 요청을 보내고 계속 응답 데이터를 받는다. 서버는 이벤트 발생시 응답을 보낸다.

Web Socket

이미지 출처 : wallarm - WebSocket

웹에서 하나의 TCP 연결을 통해 양방향 통신을 제공하는 컴퓨터 통신 프로토콜

  • 실시간 서비스 구현하기에 적합

  • 최초 접속이 일반 HTTP 요청을 통한 handshaking 으로 이루어짐

  • handshake 가 성공적으로 이루어지면 HTTP -> 웹 소켓 프로토콜로 변경하는 프로토콜 스위칭 이 이뤄진다.

  • HTTP 와 HTTPS 가 있듯이 웹소켓에는 ws 와 wss 가 있다.

  • WebSocekt 을 사용시 기존 API 프로토콜보다 더 빠르고 오버헤드가 덜 필요한 실시간 애플리케이션을 만들 수 있다.

구현

// index.js

const ws = require("ws");
const PORT = 8000;
const express = require("express");
const app = express();

app.set("view engine", "ejs");

app.get("/", (req, res) => {
  res.render("client");
});

const server = app.listen(PORT, () => {
  console.log(`http://localhost:${PORT}`);
});

// 웹소켓 서버 접속
const wss = new ws.Server({ server });
// 브라우저(클라이언트)들을 담을 변수선언
const sockets = [];
// socket 변수는 접속한 브라우저
wss.on("connection", (socket) => {
  console.log("클라이언트가 연결되었습니다.");
  // sockets 배열에 브라우저 추가
  sockets.push(socket);

  socket.on("message", (message) => {
    console.log(`클라이언트로부터 받은 메시지: ${message}`);
    console.log("message : ", message);
    console.log(`message : ${message}`);

    // 클라이언트로 응답 메시지 전송
    const { name, msg } = JSON.parse(message);
    console.log("name, msg : ", name, msg);
    sockets.forEach((socket) => {
      socket.send(`${message}`);
    });
  });

  // 오류
  socket.on("error", (err) => {
    console.log("에러가 발생했습니다.", err);
  });
  //접속종료
  socket.on("close", () => {
    console.log("클라이언트와 연결이 종료됨");
  });
});
<!-- client.ejs --> 
  <body>
    <ul></ul>
    <form id="chat">
      <label for="name">이름</label>
      <input type="text" id="name" /> <br />
      <label for="message">메세지</label>
      <input type="text" id="message" /> <br />
      <button>채팅</button>
    </form>
    <script>
      const socket = new WebSocket("ws://localhost:8000");
      // form 가져오기
      const chatForm = document.querySelector("#chat");
      // ul 가져오기
      const ul = document.querySelector("ul");
      // 서버에 연결
      socket.addEventListener("open", (event) => {
        console.log("서버에 연결되었습니다.");
      });
      // 메시지 주고 받음
      socket.addEventListener("message", (event) => {
        const li = document.createElement("li");
        const { name, msg } = JSON.parse(event.data);
        li.textContent = `${name}: ${msg}`;
        ul.appendChild(li);
      });
      // 오류 발생
      socket.addEventListener("error", (event) => {
        console.log("오류가 발생하였습니다.", event.error);
      });
      // 종료
      socket.addEventListener("close", (event) => {
        console.log("서버와 연결이 종료되었습니다.");
      });

      //// form 이벤트 ///
      chatForm.addEventListener("submit", (event) => {
        event.preventDefault();
        const msg = chatForm.querySelector("#message");
        const name = chatForm.querySelector("#name");
        socket.send(JSON.stringify({ name: name.value, msg: msg.value }));
        msg.value = "";
      });
    </script>
  </body>

POSTMAN 으로 실습

먼저 서버를 돌려준다.

그리고 client1, client2 를 connect 하여 서버에 소켓으로 연결해준다.

Message 는 client 에서 다음과 같은 형태로 socket 에 메시지를 전송해서 JSON 으로 구성했다.

socket.send(JSON.stringify({ name: name.value, msg: msg.value }));

postman 으로 websocket 통신하기

웹에서 볼때 websocket 통신시 보이는 화면

레퍼런스

docs
mdn - 웹의 동작 방식
blog
eddy - Spring Websocket & STOMP
벼리구름 - HTTP vs WebSocket
reference
PubNub - What is HTTP Long Polling?
WebSockets and HTTP streaming in .NET

profile
미래의 나를 만들어나가는 한 개발자의 블로그입니다.

0개의 댓글