공부 기록/개념정리

Socket ? WebSocket ? Socket.IO ? 봐도 봐도 어려운 소켓 (1)

코딩걈자 2024. 12. 4. 21:34
반응형

미니 프로젝트를 진행하면서 채팅,실시간 화면공유, 화상채팅 기능을 추가하다보니 자연스럽게 소켓에 대해 다루게 됐다.

근데....너무 어렵다 소켓! 프로젝트를 위한 기본 템플릿은 잘 되어있어서 기능 구현 자체는 어렵지 않았는데, 기능을 추가, 리팩토링, 에러 캐치를 하다보니 복사 붙여넣기로는 한계가 생겨버렸다 ,, 😥

계속 공부중이고, 당장 필요한 내용을 위주로 정리한 걸 적어보려한다. 공부하면 모르는게 또 생기고 또 생기고 언제쯤 소켓이 쉬워질까요...?

잘못된 정보가 있으면 언제든 알려주세요!!

 


1. 소켓 (Socket)

1) 등장

  • OSI 7계층의 한계
    • 프로토콜 구현을 위한 구현부 함수가 필요해짐
    • 소켓에서 이러한 함수들의 body를 제공하여 별도의 구현없이 소켓 사용 → 일관된 방식의 네트워크 프로그래밍 환경을 제공
  • 분산 시스템의 등장

2) 개념

  • 컴퓨터 네트워킹에서 프로세스간 통신(IPC)인 양방향 통신을 가능하게 하는 인터페이스
  • 프로토콜, ip주소, 포트넘버로 정의
  • 일반적으로 TCP/IP 프로토콜 사용

3) 소켓 통신 흐름

  • 소켓 상태
    • CLOSED : 초기상태
    • LISTEN : 서버 소켓이 연결 대기 중
    • SYN_SENT : 클라이언트가 서버로 연결 요청을 보냄
    • ESTABLISHED : 연결 성공 상태
    • CLOSE_WAIT : 연결 종료 대기
  • 서버 : 클라이언트 소켓의 연결 요청을 대기하고, 연결 요청이 오면 클라이언트 소켓을 생성하여 통신이 가능하게 함
  • 클라이언트 : 서버와 연결을 요청하고 데이터 송수신.
[server socket]
socket() // 소켓 생성
bind() // ip와 port번호를 설정
listen() // 클라이언트 접근 요청에 수신 대기열을 만들어 몇개의 클라이언트를 대기 시킬지 결정
accept() // 클라이언트와의 연결을 기다림

[client socket]
socket() //소켓 열기, 소켓의 종류를 선택
connect() // 통신을 할 서버의 ip와 서비스port번호에 통신 시도, 요청의 결과가 돌아오면 함수실행 종료
//통신을 시도시, 서버가 accept()함수를 이용하여 클라이언트의 socket descriptor을 반환
send() / recv() // 클라이언트와 서버가 서로 read/write 반복, 요청의 결과가 들어와야 실행이 종료

4) 종류

  • TCP 소켓: 연결지향성(신뢰성 보장), 대량 데이터 처리
  • UDP 소켓: 비연결형, 빠른 데이터 전송, 실시간 멀티미디어 처리

2. 웹소켓 (WebSocket)

  • HTTP 기반의 프로토콜 확장으로 양방향 실시간 통신 제공
    • 원래의 HTTP는 단방향 통신으로 응답 후 바로 연결 종료 -> 실시간 통신이 어려움
    • HTTP 핸드셰이크 이후 TCP 연결 위에서 통신
  • HTML5 이후에 나타난 기술
    • 이전에 구현된 서비스는 Socket.IO / SockJS / STOMP 등 사용
  • 동작 방법 : 핸드셰이킹 -> 프레임 단위 통신

3. Socket.IO

1) 개념

  • 웹소켓과 폴백 기술(Long Polling, JSON Polling, XHR Polling 등)을 조합한 실시간 통신 라이브러리
    • Long Polling : 클라이언트가 서버에 지속적으로 HTTP요청을 보내 실시간 통신을 흉내냄
    • JSON Polling : 주로 CORS 문제가 있는 환경에서 사용 , <script>태그를 동적으로 삽입하여 데이터 요청
    • XHR Polling : XMLHTTPRequest를 이용한 폴백 방식
  • Node.js 환경에서 개발된 클라이언트와 서버간의 저지연, 양방향, 이벤트 기반 통신을 가능하게 하는 라이브러리
  • Engine.IO프로토콜 위에서 동작
    • Socket.IO가 Engine.IO 프레임 안에 애플리케이션 데이터를 담아 전송→ Socket.IO는 Engine.IO의 전송메커니즘을 추상화하여 사용할 수 있음
  • 자동 재연결, 이벤트 기반으로 데이터 전송 처리, 네임스페이스와 룸지원 , 브라우저 호환성의 장점을 가짐

2) 패킷

  • Socket.IO패킷 타입패킷 타입 값 
    CONNECT 0 네임스페이스에 연결하는 동안 사용
    DISCONNECT 1 네임스페이스에서 연결을 끊을 때
    EVENT 2 반대쪽으로 데이터를 전송할 때
    ACK 3 이벤트를 확인할 때
    CONNECT_ERROR 4 연결할 동안
    BINARY_EVENT 5 반대쪽으로 바이너리 데이터를 전송할 때
    BINARY_ACK 6 바이너리 데이터가 포함된 이벤트 확인
  • Engine.IO패킷 타입패킷 타입 값
    OPEN 0 연결 성공
    CLOSE 1 연결 종료
    PING 2 서버 또는 클라이언트가 연결 상태를 확인하기 위해 전송
    PONG 3 PING패킷의 응답
    MESSAGE 4 애플리케이션 데이터가 포함된 일반 메시지, Socket.IO의 패킷을 캡슐화하여 전송
    UPGRADE 5 전송 프로토콜 업그레이드 요청 (웹소켓으로 변경 등)
    NOOP 6 주로 테스트용으로, 아무 동작을 하지 않는 패킷
  • 패킷 인코딩 : Socket.IO 패킷타입+네임스페이스 + 데이터 → (캡슐화) → Engine.IO 프레임 (4) + [ 기존 인코딩 결과 ]
    • { type: EVENT, namespace: "/", data: ["foo"] } → 2["foo"] → 42[”foo”]

3) 연결 과정

  1. 클라이언트가 CONNECT패킷을 보냄
  2. 서버는 연결이 성공하면 CONNECT, 실패하면 CONNECT_ERROR를 보냄
  3. 연결이 성공되면 데이터 교환 시작
  4. DISCONNECT 패킷을 보내 네임스페이스에 대한 연결 종료

4) 주요 메서드

  • on : 이벤트 리스너 등록 / emit : 이벤트 트리거 & 데이터 전송 / removeListener : 이벤트 리스너 제거
  • 서버: io.on(), io.emit(), socket.broadcast.emit().
  • 클라이언트: socket.on(), socket.emit().

4. React에서 Socket.IO 사용하기

  • React의 컴포넌트 라이프 사이클과 함께 사용되어 실시간 통신 상태를 UI에 반영
    • 보통 useEffect를 사용하여 마운트 될 때 소켓을 생성하고, 언마운트 될 때 해제(socket.off)
  • 커스텀 훅을 만들어 관리할 수 있음 (연결, 이벤트 처리, 이벤트 트리거 분리 가능)
  • 클라이언트에서 서버 연결, 서버에서 특정 포트에서 연결 대기 -> 이벤트 리스너 등록 -> 이벤트 트리거 -> 소켓 연결 해제
    useEffect(() => {
        // 소켓 연결
        const newSocket = io('http://localhost:3000');
        setSocket(newSocket); //연결된 소켓 상태 관리

        // 서버에서 메시지 받기 (이벤트 구독)
        newSocket.on('message', (data: string) => {
            setMessages((prevMessages) => [...prevMessages, data]);
        });

        return () => {
            // 컴포넌트 언마운트 시 소켓 연결 해제
            newSocket.disconnect();
        };
    }, []);

    const sendMessage = () => {
        if (socket && message.trim()) {
            // 서버로 메시지 보내기 (이벤트 트리거)
            socket.emit('message', message);
            setMessage('');
        }
    };

개념은 봐도 봐도 어렵다 어려워,, 다음 게시물 부터는 GPT를 괴롭혀서 만든 예제 문제로 실습을 해보며 익혀볼 예정 !