본문 바로가기

카테고리 없음

웹소켓을 이용한 게임 개발 공부 1일차

1. HTTP vs TCP

HTTP는 비연결성 구조로 request가 없으면 response도 없다. 연결을 유지하지 않기때문에 많은 트래픽을 빠르게 처리가능합니다. 연결을 유지해야 하는 리소스를 아낄 수 있는 장점이 있다. 또한 stateless(무상태)를 특징으로 가진다. 이전에 일어났던 일(상태)를 저장하고 있지 않아 세션, 쿠키 등으로 해당 요청에 대한 정보를 임의로 저장해서 처리하곤 합니다. HTTP의 메세지 구조는 start-line, header, empty-line, message body로 이루어져 있고 헤더는 메세지에 필요한 모든 부가 정보를 가진다. key-value의 map구조를 가지고 있어 방대한 정보를 추가할 수 있다.

HTTP는 네트워크 7계층 중 application layer에 속하며, 메일을 전송하는 SMTP, 파일을 전송하는 FTP 또한 여기에 포함되는 프로토콜이다. 이 레이어는 결국 transport layer 위에서 동작하게 되고 당연히 HTTP는 TCP나 UDP 둘 중 하나의 연결을 통해 동작하게 된다. 이 TCP는 HTTP와 달리 연결지향성을 지녀 데이터교환을 할 때 무조건 연결을 가집니다. 즉,  HTTP의 Req ↔ Res 가 발생할때 밑에서 TCP 연결이 이뤄지고, 이 연결을 3way-handshake라고 부른다. 

TCP 통신은 양방향 통신(Full-Duplex) 구조로 서버가 접속 요청을 받기위해 소켓을 열고(Listen), 클라이언트는 소켓을 만들어 서버에 접속을 요청합니다.(Connect) 그리고 서버는 이 요청을 받아 클라이언트와 통신할 소켓을 따로 만들고(Accept) 소켓을 통해 서로 정보를 주고 받습니다.(Send/Receive) 그리고 통신을 마치면 소켓을 닫음으로써 통신이 마무리 됩니다.(Close)

 

2. Websoket : HTTP프로토콜 위에서 동작하는 실시간 양방향 통신 (Full-Duplex)

  • 실시간 통신 : 연결이 활성화된 상태에서 빠르고 지속적인 메시지 교환을 허용합니다. 이로 인해 애플리케이션은 사용자에게 지연 없는 인터랙션을 제공할 수 있습니다.
  • 양방향 통신 : 클라이언트와 서버가 동시에 서로에게 메시지를 보낼 수 있습니다. 이는 한 쪽이 다른 쪽의 메시지를 기다리지 않고도 독립적으로 메시지를 송수신할 수 있음을 의미합니다.
  • 지속적 연결 : 웹소켓 연결이 수립되면, 그 연결은 클라이언트나 서버가 명시적으로 종료할 때까지 유지됩니다.
  • 낮은 오버헤드 : 웹소켓은 데이터 패킷의 헤더가 매우 작기 때문에 오버헤드가 낮습니다. 이는 효율적인 네트워크 자원 사용을 가능하게 합니다.
  • HTTP와의 호환성 : 웹소켓은 HTTP 포트(80과 443)를 통해 작동하기 때문에 기존 웹 인프라와 잘 통합됩니다. 웹소켓 연결은 HTTP 연결을 통해 초기화되며, 이후 전이중 통신 채널로 전환됩니다.
웹소켓의 연결방법은 TCP의 연결방법 (3-way-handshake)를 닮아있다.

웹소켓은 기본적으로 TCP 연결 위에서 작동하기 때문에, 웹소켓 연결을 시작하기 전에 TCP의 표준 연결 방법인 3-way handshake가 수행됩니다. 하지만 웹소켓은 이후에 추가적인 핸드셰이크 과정을 진행하여 웹소켓 특유의 연결을 완성합니다.

 

 

3. 웹소켓 프로젝트 세팅

- package.json 파일 생성
npm init -y

 

그리고 es6 이상의 문법을 사용할 수 있도록 그 파일에 “type”: “module” 옵션을 추가해준다.

 

- 설치 명령어
npm i express soket.io
- 데브 디펜던시 설치
npm install -D nodemon prettier

 

- 프리티어 셋팅값 공유

{
  "singleQuote": true,
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 100,
  "arrowParens": "always",
  "orderedImports": true,
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}

 

- app.js 엔트리포인트 파일을 만들고 package.json에 "main" 옵션을 app.js로 수정하고 script에 "dev": "nodemon src/app.js"를 추가한다.

// src/init/socket.js
import { Server as SocketIO } from 'socket.io';

const initSocket = (server) => {
  const io = new SocketIO();
  io.attach(server);
};

export default initSocket;

 

// app.js
import express from 'express';
import { createServer } from 'http';
import initSocket from './init/socket.js';

const app = express();
const server = createServer(app);

const PORT = 3000;

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
initSocket(server); // 소켓 추가

app.get('/', (req, res) => {
  res.send('<h1>Hello World</h1>');
});

server.listen(PORT, async () => {
  console.log(`Server is running on port ${PORT}`);
});

 

서버가 실행될 때 init이라는 폴더 내부에 코드들이 실행되기 때문에 이름을 이렇게 지었다. 그리고 app.js에 코드를 추가해 실행할 때 socket.io가 실행될 수 있게 한다. 이로써 웹소켓을 위한 개발환경 셋팅을 마쳤다.