kimyu0218
  • [node] 당신의 socket.io가 동작하지 않는 이유 (Feat. socket.io는 파싱을 해)
    2023년 12월 23일 16시 58분 53초에 업로드 된 글입니다.
    작성자: @kimyu0218
    소켓아이오를 소켓아이고로 부르기로 결심한 이유 😇

    지금부터 말하는 트러블 슈팅은 단일 서버에서 하나의 웹소켓을 이용하는 경우엔 발생하지 않았을 것이다. 하지만 여러 path에 대해 웹소켓을 사용하고 있다면 이 문제에 부딪혔을 수도 있다. 아주 허무하지만, 상상도 못한 이슈 지금부터 시작하겠다.

     

    삽질의 시작, 라우팅

    시작에 앞서 프로젝트 구조를 간단히 설명하겠다. 백엔드는 두 개의 서버를 띄우고 있고, nginx가 가장 앞단에 위치하여 경로에 따라 다른 서버로 프록시한다.

    nginx 라우팅 정보
    - /signal : 시그널링 서버
    - / : WAS 서버

    두 서버 모두 웹소켓을 사용하고 있는데 아이너리하게 오직 시그널링 서버로의 소켓 요청만 동작하지 않았다.

    결론부터 말하자면, socket.io가 url에다 /signal을 붙여도 자동으로 떼어낸다. (우주먼지가 되어버린 소켓 요청)


    이게 무슨 URL이야

    io("https://was.tarotmilktea.com/signal");
    wss://was.tarotmilktea.com/socket.io/?EIO-4&transport...

    원인 파악을 위해 브라우저의 개발자 도구를 열면 상상도 못한 URL이 있다. /signal이라는 path가 사라지고 /socket.io가 그 자리를 대체한 것을 볼 수 있다.

    😦 : 뭐야 내 /signal 돌려줘요
    io : socket.io의 객체로, 클라이언트에서 서버와 통신하기 위해 사용한다.

    socket.io는 호스트를 파싱해

    io 객체는 URL을 파라미터로 전달할 수 있는데, 놀랍게도 socket.io가 파라미터로 넣어준 URL을 자동으로 파싱하여 호스트 주소만 남겨버린다. 즉, 라우팅을 위해 붙여준 /signal이 사라진 상태로 웹소켓 연결을 시도한다.

    그렇다면 내가 붙여준 적도 없는 /socket.io는 뭘까? 바로 socket.io의 기본 path다.

    호스트만 남은 URL에 path를 붙여주기 위해서는 바로 옵션을 활용해야 한다. 다음과 같이 path를 작성하면 /socket.io 대신 /signal이 붙어서 간다.

    io("https://was.tarotmilktea.com", { path: "/signal" });

    위의 경고 문구에도 있듯이 클라이언트, 서버 측 path 처리가 필요하다. 서버 부분은 자신의 프레임워크에 적절하게 수정하도록 하자. (나는 nest를 사용하고 있어서 다음과 같이 수정했다.)

    @WebSocketGateway ({
      ...
      path: '/signal'
    })


    모두들 공식 문서를 잘 읽으시고, 공식 문서에도 오류가 있을 수 있다는 점을 명심하세요.

    댓글