Socket) Web Socket으로 실시간 채팅 구현하기1

Bak·2024년 2월 1일
0

Socket

목록 보기
3/4

Web Socket

(1) 환경

  • server : local에서 Node.js
  • client : local에서 svelte

(2) 사용 라이브러리

  • socket.io 또는 ws 라이브러리중에서 socket.io 사용
    → 실시간 채팅의 경우 socket.io가 더 적합하다.
  • net

(3) 환경 setting

  • svelte : npx dgit sveltejs/template svelte-app

    • npx : npm패키지 실행 도구, npm이 전역으로 설치되어 있지 않아도 npm이 바로 실행될 수 있게 한다.
      +) npm install -g : npm을 전역으로 설치하는 명령어

    • dgit : github같은 git 저장소에서 프로젝트의 초기템플릿을 복사하는 도구
      → svelte의 공식템플릿인 sveltejs/template를 복사한다.

    • svelte-app : 만들어질 directory 이름

  • svelte 템플릿:
    npm create vite@latest 프로젝트 이름 -- --template 프레임워크 이름
    npm create vite@latest frontend -- --template svelte

  • npm create : 프로젝트 스캐폴딩을 위한 명령어
    +) 프로젝트 스캐폴딩 : 프로젝트를 시작할 때 기본적인 구조와 설정을 자동으로 생성해주는 과정

  • vite@latest : 최신버전의 vite 패키지를 가져온다.
    +) vite : 빌드 도구, 프레임워크의 초기설정과 템플릿을 가져와주는 도구

  • node.js 설치
    https://nodejs.org/en/download
    LTS버전을 설치하며 따로 설정할 것은 없고 전부 기본세팅으로 설치한다.

(4) 라이브러리

  • node.js - express : Web Server 프레임워크 라이브러리
  • node.js - socket.io : Web Socket 라이브러리
    https://socket.io/ - socket.io 공식 사이트로써 기본적인 활용방법이 나와있다.

Web Socket - Server 환경 세팅

(1) 모듈 호출과 서버 socket 생성

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const bodyParser= require('body-parser');
const cors = require('cors');

const app = express();
app.use(bodyParser.json());     // body 부분 처리
app.use(cors());        // cors 부분 에러 해결, 모든 도메인에서의 요청 허용
const server = http.createServer(app);
const io = socketIo(server, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"]
    }
});

라이브러리 설명

  • body-parser : response를 json형태로 변환하기 위한 라이브러리
  • cors : cors 에러를 해결하기 위한 라이브러리

함수 설명

  • require : 다른 파일이나 모듈을 가져오는 함수
  • createServer : 매개변수로 client의 request에 따라 실행되는 함수를 받는다. 즉 request handler이다.
  • socketIO : 매개변수로 http server 객체를 받는다.
    -> Web Socket은 초기 연결을 http로 수립한 후 해당 연결을 업그레이드하여 연결을 유지하며 데이터를 교환한다.

변수 설명

  • app : Application이라는 객체, get, post, put, delete같은 HTTP 요청을 처리하는 메서드를 가지고 있다.
    → get, post, put, delete는 client가 request하는 것이기에 createServer의 매개변수로 사용된다.
  • server : Application 객체를 기반으로 하는 http server
  • io : serverSocket

cors 문제 해결

const io = socketIo(server, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"]
    }
});
  • origin : 모든 ip주소에서의 요청 허용
  • methods : GET, POST 요청만 허용

(2) Connection

io.on('connection',(socket) => {
    console.log('New Client Connected');

    socket.on('disconnect',() =>{
        console.log('Client disconnect');
    });
});

server.listen(8000,() => console.log('Listening on port 8000'));
  • on(이벤트 handler, (resquest) => {내부로직});
    : client에서 io.이벤트메서드를 호출하면 호출할 때 함께 전송되어진 request를 이용해 내부로직을 처리한다.

connection : client에서 io.connection메서드를 통해 socket연결을 요청하면 실행되는 이벤트 handler
(socket) : request, 함수 호출을 통해 생성되는 connectionSocket이다.
→ 화살표함수에서 파라미터의 위치에 따라 request, response가 결정된다. 파라미터가 1개일 경우 request이다.

socket.on('disconnect',() =>{ console.log('Client disconnect');});
→ 위의 response로 들어온 socket을 통해
disconnect요청이 들어온다면
() : 따로 request와 response를 관리하지 않고
console에 log로 'Client disconnect'를 출력하겠다.

  • server.listen(포트번호, () => 내부로직); : 포트번호에서 server가 응답을 대기중이다.

Web Socket - Server 기능 구현

(1) 이전 메시지들 불러오기

let messages = [{text: '어서오세요!', timestamp : new Date().toISOString()}];  
//메세지들을 저장할 배열, 처음에는 어서오세요!와 최초 사용자가 들어온 시간이 출력된다.

app.get('/messages',(req,res)=>{
    console.log("이전 메시지들을 불러옵니다.")
    res.json(messages);
})
  • app.HTTP메서드 ( 'url' , (request, response) => {내부로직});
    : client가 get,post,put,delete의 HTTP메서드를 url을 통해서
    request와 함께 요청을 보낸다면 response를 정의해서 내부로직을 처리한다.

1 → app 은 HTTP요청을 처리하는 객체로써
→ client가 get/messages 요청을 보내면
(req,res) : request를 받고 response를 생성해서
2 → console에 "이전 메시지들을 불러옵니다."라는 메시지를 출력한다.
3 → response로 json(messages),
위의 이전 메시지들을 담아두는 배열(messages)를 json형태로 전송한다.


(2) 메시지 전송 (RestAPI or socket)
: server의 기능구현은 RestAPI 엔드포인트와 같은 HTTP기반응답과
socket.io로만 구현했다.

  • RestAPI

    app.post('/post_messages',(req,res)=>{
      const reqMessage = req.body;
      messages.push(reqMessage);
    
      io.emit('message',reqMessage);
      
      res.status(201).end();
     })

1 → client에서 /post_message라는 요청을 보내면
(req,res) : request를 받고 response를 생성해서
2 → reqest의 body안의 내용을 reqMessage라는 변수에 저장한다.
3 → server가 가지고 있는 이전 메시지들을 담는 배열 messages에 client가 보낸 reqMessage를 저장한다.
4 → client에서 정의된 message메서드를 reqMessage와 함께 호출시킨다.
이는 한 client가 보낸 메시지를 다른 client에게 모두 보내기 위해서이다.
5 → res.status(201).end()

res 메서드

  • res.end() : Express.js에서 응답 process를 종료하는 메서드, client에게 어떤 data도 보내지 않고 단순히 응답 process를 종료한다.
    ex) post메서드에서 data를 보낼 필요 없이 응답을 종료해야 할 때
  • res.status() : 인자안의 값을 status code로 설정한다.
  • res.json() : 인자안의 값을 json형태로 변환 후 client에게 전달한다.
  • res.send() : 인자안에 다양한 타입(문자열, 객체, 배열 ...)을 받을 수 있고 client에게 전달한다.
    res.json()res.send()는 내부적으로 res.end()를 포함하고 있다.
  • socket
socket.on('message',(reqMessage) =>{
    messages.push(reqMessage);
    io.emit('message',reqMessage);  
    // 모든 사용자에게 전송된 메시지들을 보내기 위해 
});
  • socket.on('url', (request) => {내부로직});
    : client가 url을 통해 request를 보내온다면 내부로직을 처리한다.

1 → client가 message url을 reqMessage와 함께 요청한다면
2 → server가 가지고 있는 이전 메시지들을 담는 배열 messages에 client가 보낸 reqMessage를 저장한다.
3 → client에서 정의되어있는 message이벤트를 호출하며 reqMessage를 같이 보낸다.

on은 이벤트를 정의하는 것이고, emit은 이벤트를 호출하는 것

0개의 댓글