웹 소켓(Web Socket)

yedi·2024년 7월 12일
post-thumbnail

웹 소켓(Web Socket)

| 개념

HTTP 통신을 이용하면 클라이언트에서 서버에 요청을 보내야만 서버에 응답을 할 수 있다.
즉, 서버에서는 요청을 받지 않으면 클라이언트에 통신할 수 없는 것이다.
이러한 문제점을 해결하기 위해서 양방향으로 통신할 수 있는 웹 소켓(Web Socket) 통신을 이용해야 한다.

채팅, 문의, 알림과 같은 ‘실시간’ 이라는 키워드가 필요한 기능들은 HTTP 통신을 사용해서 구현할 수 없다. (계속된 요청 한계)
이러한 기능을 제작할 때 소켓 통신을 이용해야 한다.


종류 설명
폴링(polling) - 단방향
- 클라이언트 -> 서버
- 클라이언트에서 주기적으로 서버에 업데이트 있는 지 확인하는 요청을 보냄
웹 소켓
(web Socket)
- 양방향
- 클라이언트 <-> 서버
- 한 번 웹 소켓을 연결하면 계속 연결된 상태로 있어서 따로 업데이트가 있는지 요청을 보낼 필요가 없음
- node의 모듈 및 라이브러리 : ws, Socket.IO



| 진행 과정

1. 연결 설정 (Connection Establishment)
1-1. 핸드셰이크 요청 (Handshake Request)
1-2. 핸드셰이크 응답 (Handshake Response)
2. 데이터 전송 (Data Transfer)
3. 연결 종료 (Connection Termination)
3-1. 종료 핸드셰이크 (Close Handshake)
3-2. 비정상 종료 (Abnormal Termination)

위 사용 과정에 대해서 자세히 알아보자.

1. 연결 설정 (Connection Establishment)

1-1. 핸드셰이크 요청 (Handshake Request)
: 클라이언트는 HTTP를 사용하여 웹소켓 서버에 연결 요청을 보냅니다.
이 요청은 업그레이드(Upgrade) 헤더를 포함하여 웹소켓 프로토콜로의 전환을 요청합니다.

//예시 요청 헤더
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

1-2. 핸드셰이크 응답 (Handshake Response)
: 서버는 클라이언트의 요청을 검토한 후, 연결을 승인하는 응답을 반환합니다.
이 응답도 업그레이드 헤더를 포함합니다.

//예시 요청 헤더
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

핸드쉐이크(HandShake)

  • 정보기술과 전기통신 및 관련 분야에서 채널에 대한 정상적인 통신이 시작되기 전에 두 개의 실체 간에 확립된 통신 채널의 변수를 동적으로 설정하는 자동화된 협상 과정
  • 정상적인 정보 전송 이전에 이루어짐

2. 데이터 전송 (Data Transfer)

Node.js - Express 설치
https://velog.io/@yedi/Node.js-Express

//index.html -> 클라이언트
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h4>채팅페이지입니다.</h4>
    <button id="send" onclick="socket.send('안녕하세요')">메세지 보내기</button>

    <script>
        //웹소켓 열어달라고 서버에게 부탁하는 코드
        //WebSocket 연결 요청의 경우 http://가 아닌 ws://나 wws:// 작성
        let socket = new WebSocket("ws://localhost:8081");
    </script>

</body>
</html>
//server.js -> 서버
const express = require('express');
const app = express();

app.use("/", function(req, res){
    res.sendFile(__dirname + '/index.html');
});

app.listen(8080);


//웹소켓 열기
const WebSocket = require('ws');

const socket = new WebSocket.Server({
    port: 8081
});

//웹소켓으로 오는 유저 메세지를 받으려면 
socket.on('connection', (ws, req) => {

    ws.on('message', (msg) => {
        console.log('사용자가 보낸 것 : ' + msg);
        //웹소켓으로 서버 -> 유저 메세지 보내기
        ws.send('잘가');
    });

});

3. 연결 종료 (Connection Termination)
3-1. 종료 핸드셰이크 (Close Handshake)
: 클라이언트 또는 서버는 연결을 종료할 수 있습니다.
종료 요청은 종료 프레임(close frame)을 통해 전송되며, 상대방은 이를 수신한 후 응답 프레임을 전송하여 연결을 정상적으로 종료합니다.

//server.js -> 서버
socket.on('connection', (ws, req) => {

    // 연결 종료
    socket.on('close', () => {
        console.log('연결 종료');
    });

});

3-2. 비정상 종료 (Abnormal Termination)
: 네트워크 문제 등으로 인해 비정상적으로 연결이 종료될 수 있습니다.
이 경우, 클라이언트와 서버는 연결이 끊어진 후 재연결을 시도할 수 있습니다.

//server,js -> 서버
socket.on('connection', (ws, req) => {

     // 에러
    socket.on('error', (error) => {
        console.log('에러 발생');
    });
    
});

웹소켓 연결의 예시 전체 흐름

  1. 클라이언트가 서버에 웹소켓 연결을 요청합니다.
  2. 서버가 요청을 수락하고, HTTP 핸드셰이크 응답을 반환합니다.
  3. 클라이언트와 서버는 연결이 설정된 후, 메시지를 주고받습니다.
  4. 클라이언트 또는 서버가 연결을 종료할 때, 종료 프레임을 전송합니다.
  5. 상대방이 종료 프레임을 수신하고, 응답 프레임을 전송하여 연결을 종료합니다.


| 참고

https://www.youtube.com/watch?v=yXPCg5eupGM
https://www.chanstory.dev/blog/post/26
https://velog.io/@delay100/Socket
https://hudi.blog/websocket-with-nodejs/

0개의 댓글