Skip to content

배포 환경에서 클라이언트‐서버 WS handshake

Yoonseo Han edited this page Dec 3, 2024 · 1 revision

로컬에서는 돌렸을때 문제가 없었는데 도커 환경 위에서 구동을 할때 클라이언트와 서버 사이의 WS 통신에서 에러 메세지가 지속적으로 뜨는 것이 문제가 되었다. 이 때문에 채팅방에 들어와서 채팅을 입력하더라도 보이는 것이 없었기에 해당 문제를 해결해야 했다

우선 알아두면 좋을 브라우저와 도커 환경에서의 WS handshake 순서이다

sequenceDiagram
    participant Browser
    participant Client as Client(React/Vue):5173
    participant Nginx
    participant Backend as Backend:3000

    Browser->>Nginx: 1. HTTP GET /
    Nginx->>Client: 2. 프론트엔드 앱 전달
    Client->>Browser: 3. JS 로드 
    
    Browser->>Nginx: 4. WS 연결 요청 (/socket.io)
    Note right of Browser: ws://domain.com/socket.io
    Nginx->>Backend: 5. WS 연결 프록시
    Backend-->>Nginx: 6. WS Upgrade 응답
    Nginx-->>Browser: 7. WS 연결 수립
    
    Note over Browser,Backend: 8. WebSocket 양방향 통신
Loading

기존의 우리 코드

우선 클라이언트 쪽에서 WS setup을 위해 작성한 코드이다

const URL = 'https://inear.live/rooms';

export const socket = io(URL, {
  autoConnect: false
});

해당코드는 좋은 접근이다. 상기 되어있는 URL을 이용하여 접근을 시도할 경우 클라우드페어에서 알맞게 nginx에다가 http://{public_IP_주소}:80으로 요청을 포워딩할 것이기 때문이다

다만 놓친 몇가지가 있는데

  • 일단 백엔드로 요청을 보내려면 /api prefix를 붙여야 해당 요청이 전송이 된다

  • 로컬 환경이건 배포 환경이건 동일하게 DNS에 영향을 받지 않는 코드를 작성하고 싶으면 URL을 명시하기보다는 상대 경로를 쓰는 것이 더 용이하다

    export const socket = io('/rooms', {
      path: '/api',
      autoConnect: false,
    });

이렇게 설정을 진행하게 되면 다음과 같이 handshake 요청이 들어가게 된다

  • 최초 handshake: /api/?EIO=4&transport=polling
  • WebSocket 연결: /api/?EIO=4&transport=websocket

다만 Socket.IO는 내부적으로 정해진 경로 패턴을 사용한다!!!!!!!!

  • /socket.io/?EIO=4&transport=polling
  • /socket.io/?EIO=4&transport=websocket

그렇기에 사실 보내는 요청은 경로가 /socket.io가 포함이 되어야한다. 그렇다면 수정해야할 사항들

  • 클라이언트는 path에 /api가 아닌 /socket.io를 추가해야한다 (다만 이는 이미 default로 설정이 되어있기 때문에 사실 아무것도 설정을 안해줘도 된다)

    export const socket = io('/rooms', {
      autoConnect: false,
    });
  • 백엔드는 요청을 처리하는게 /api 뿐만 아니라 하나가 더 생긴것이다: /socket.io 그러므로 default.d에서 설정을 또 해줘야한다

upstream backend {
    server server:3000;
}

server {
    listen 80;
    
    # 공통 헤더 설정
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    location / {
        proxy_pass http://client:5173;
    }

    location /api {
        proxy_pass http://backend;
    }

    location /socket.io {
        proxy_pass http://backend;
    }
}

inear

기술 공유

🚀 ffmpeg는 stderr로 디버깅을 하는 이유
🚀 HLS 프로토콜에 관한 정리 및 FFmpeg 사용기
🚀 비트는 tsconfig.json이 세 개?
🚀 NestJS 기본 개념 - Modules
🚀 Socket.io 최(강)적화
🚀 도커와 nginx의 사용기
🚀 부하테스트를 해보자

개발 일지

🚀 FSD 사용기, 근데 이제 나만의 규칙을 곁들인
🚀 CICD 구조 수정
🚀 앨범 단위로 스트리밍 하기 (with HLS)
🚀 HLS로 음악 주고받기
🚀 vite + react + typescript 환경에서 path alias 설정
🚀 React Scan이 뭐죠?
🚀 로컬 환경 개발 모드 배포
🚀 앨범 전체를 스트리밍한다고? (with HLS)
🚀 코드의 안정성을 높이기 위해 테스트코드를 작성해보자

트러블 슈팅

🚀 새로고침 시 HLS ERROR
🚀 input 태그에 한글 입력 후, Enter를 누르면 함수가 두번 호출되는 오류
🚀 nginx proxy pass를 바꿨더니 생긴 에러 - 스웨거 인식 문제
🚀 배포 환경에서 클라이언트-서버 WS handshake
🚀 렌더링 범인은 하나!

협업 규칙

🌈 그라운드 룰
🥔 팀원 소개
🔎 코드 & 깃 컨벤션
🌳 깃 branch 전략
📌 노션 문서 저장소

프로젝트 기획

🎨 피그마
🧑‍💻 기획 공유 발표 자료
🎤 2주차 발표 자료
😎 백로그

데일리 스크럼

📝 1주차
📝 2주차
📝 3주차
📝 4주차
📝 5주차

주간 계획서

🗓️ 1주차
🗓️ 2주차
🗓️ 3주차
🗓️ 4주차
🗓️ 5주차

그룹 회고

✨ 1주차
✨ 2주차
✨ 3주차
✨ 4주차


view

Clone this wiki locally