웹소켓

WebSocket

도구

연결을 열어 둔 채 양쪽이 아무 때나 서로에게 데이터를 보낼 수 있게 만든 통신 방식입니다.

등장 배경

웹의 기본 통신은 한 번 묻고 한 번 답하면 끊는 구조입니다. 화면이 서버를 부르고 서버가 답하면 그 연결은 사라집니다. 이 구조에서는 서버가 먼저 말을 걸 방법이 없습니다.

같은 문서를 둘이 편집하는 자리에서 이 한계가 그대로 드러났습니다. 상대가 고친 내용을 보려면 화면이 계속 물어봐야 합니다. 3초마다 물어보면 지연이 3초이고, 문서 하나를 100명이 열어 두고 있으면 아무도 타이핑하지 않는 동안에도 초당 서른 건이 오갑니다. 간격을 0.5초로 줄이면 지연은 나아지고 요청은 여섯 배가 됩니다.

응답을 곧바로 주지 않고 붙잡아 두는 우회책이 한동안 쓰였습니다. 화면이 물어보면 서버가 답을 미뤄 두고 변화가 생길 때 그 응답을 돌려주는 방식입니다. 지연은 줄었지만 연결이 매번 새로 맺어지고 중간의 장비들이 그 연결을 임의로 끊어서 다루기가 까다로웠습니다.

그래서 한 번 연결을 맺고 그 통로를 유지하면서 양쪽이 아무 때나 보내는 규약이 표준으로 자리 잡았습니다. 처음 한 번은 보통의 웹 요청으로 시작하고, 그 요청 안에서 통로를 바꾸자고 합의한 뒤부터 계속 열려 있습니다.

해결하는 문제

세 가지를 한 번에 바꿉니다. 서버가 먼저 말을 걸 수 있게 되고, 주고받는 한 건의 비용이 작아지고, 지연이 밀리초 단위로 내려갑니다. 매 요청에 붙던 머리말과 연결 수립 절차가 첫 한 번으로 끝나기 때문입니다.

이 방식이 값을 하는 자리는 좁고 분명합니다. 같은 문서를 여럿이 동시에 편집하는 화면, 상대의 커서 위치가 실시간으로 보이는 기능, 대화, 숫자가 계속 움직이는 관제 화면입니다. 공통점은 양쪽이 모두 자주 보낸다는 것입니다.

연 채로 두는 대가가 운영 쪽에 생깁니다.

  1. 연결 수가 곧 자원입니다. 서버 한 대가 동시에 유지할 수 있는 연결 수에 상한이 있고, 그 수는 요청을 처리하는 속도와 다른 종류의 한계입니다. 접속자 수가 아니라 열린 연결 수로 용량을 계산하게 됩니다.
  2. 서버가 상태를 들고 있게 됩니다. 어느 사용자가 어느 서버에 붙어 있는지를 알아야 하니, 서버를 두 대로 늘리면 1번에 붙은 사람의 변경을 2번에 붙은 사람에게 전달할 장치가 따로 필요합니다. 서버끼리 사건을 주고받는 중계층을 그 사이에 둡니다.
  3. 끊김을 정상으로 다룹니다. 지하철에서 앱을 쓰면 연결은 계속 끊깁니다. 다시 붙는 처리와, 끊겨 있던 동안 놓친 변경을 메우는 처리를 함께 만들어야 합니다. 메시지마다 순번을 붙여 두고 재연결할 때 마지막으로 받은 번호를 알려 주면 그 뒤부터 이어받습니다.
  4. 중간 장비가 조용한 연결을 끊습니다. 프록시와 방화벽은 한동안 아무것도 오가지 않는 연결을 정리하므로, 몇십 초마다 빈 신호를 주고받아 살아 있음을 알립니다.
  5. 인증을 한 번만 확인하게 됩니다. 연결을 맺을 때 확인하고 그 뒤로는 계속 열려 있으니, 그 사이에 권한이 사라진 사람이 계속 받고 있을 수 있습니다. 주기적으로 다시 확인하거나 권한이 바뀔 때 연결을 끊는 처리를 붙입니다.

대안

같은 필요를 다르게 푸는 방법이 넷 있습니다.

  1. 짧은 간격으로 계속 물어보는 방식입니다. REST 창구를 그대로 쓰면 되니 추가로 만들 것이 없고, 지연과 요청 수를 맞바꿉니다. 초 단위 지연이 괜찮은 자리에서는 이쪽으로 충분합니다.
  2. 서버에서 화면으로 한 방향으로 흘려보내는 방식입니다. 연결을 열어 두되 서버만 말합니다. 끊기면 브라우저가 알아서 다시 붙고 구현이 단순해서, 화면이 서버에 보낼 것이 거의 없는 자리에서는 이쪽이 낫습니다.
  3. 서버끼리 주고받는 방식입니다. 사건이 생긴 쪽이 상대 주소로 알려 주는 웹훅은 연결을 유지하지 않아서 회사 경계를 넘는 통신에 맞습니다.
  4. 필요한 항목만 골라 받는 질의형 창구에 구독 기능을 붙이는 방식입니다. GraphQL에는 값이 바뀔 때 받아 보는 기능이 규격에 들어 있고, 그 아래에서 실제로 쓰이는 통로는 대개 웹소켓입니다.

고르는 기준은 셋입니다. 양쪽이 다 보내는지, 메시지가 얼마나 자주 오가는지, 동시에 열릴 연결이 몇 개인지입니다. 한쪽만 보내면 두 번째로 충분하고, 몇 초 지연이 괜찮으면 첫 번째로 충분합니다.

실무 용례

"알림만 띄우는 거면 웹소켓까지 안 가도 됩니다. 단방향으로 하죠."

필요보다 무거운 방식을 고르지 말자는 제안입니다.

"서버 두 대로 늘렸는데 상대 커서가 안 보입니다. 중계층이 없어서요."

연결이 서버에 묶여 있다는 것을 짚는 보고입니다.

"지하철에서 재연결될 때 그 사이 편집이 사라집니다. 순번을 붙이죠."

끊김을 정상으로 다루자는 요청입니다.

페이지덱이 동시 편집을 붙일 때 이 방식을 썼습니다. 태오가 먼저 3초 간격 조회로 시제품을 만들어 봤는데, 두 사람이 같은 문단을 고칠 때 3초 동안 서로의 변경을 모른 채 쓰다가 충돌이 계속 났습니다.

옮긴 뒤에 운영 쪽 일이 늘었습니다. 문서를 열어 둔 사람 수만큼 연결이 유지되니 서버 용량 계산 기준이 바뀌었고, 배포할 때마다 모든 연결이 한꺼번에 끊겨 재연결이 몰리는 현상이 생겼습니다. 재연결 시각을 조금씩 흩어 주는 처리를 붙이는 데 이틀이 더 들었습니다.

흔한 오해

실시간이면 이 방식을 써야 한다고 보는 경우가 가장 많습니다. 이름과 쓰임새가 그렇게 알려져 있으니 자연스러운 선택입니다. 하지만 실무에서 실시간이라고 부르는 것 대부분은 서버가 화면으로 보내 주기만 하면 됩니다. 알림, 진행률, 새 글 배지가 그렇습니다. 양방향 통로를 여는 순간 연결 관리와 재연결과 중계층이 따라오는데, 한 방향으로 충분한 자리에서는 그 부담만 남습니다.

연결을 열면 일이 끝난다고 보는 것도 흔합니다. 붙는 것까지는 예제 코드로 몇 줄이니 그렇게 보입니다. 하지만 이 방식의 일은 대부분 연결이 열린 뒤에 생깁니다. 끊겼다 붙을 때 놓친 것을 메우고, 조용한 연결이 끊기지 않게 신호를 주고받고, 서버를 늘릴 때 사이를 잇고, 권한이 바뀐 사람의 연결을 끊는 일이 전부 그다음입니다. 붙는 데 이틀이 걸리면 나머지에 2주가 걸립니다.

자주 헷갈리는 용어

용어언제 통신이 일어나는가웹소켓과의 차이
웹훅사건이 생겼을 때 한 번연결을 유지하지 않아서 서버끼리, 특히 회사 경계를 넘는 통신에 맞습니다. 대신 화면에 즉시 반영하려면 그 알림을 받은 서버가 다시 화면으로 밀어 줘야 합니다

같이 보면 좋은 페이지

  • API

    주고받는 방식 다섯 가지와 나머지 갈래를 먼저 봅니다

  • REST

    한 번 묻고 한 번 답하는 기본 방식을 보고 둘을 나란히 놓습니다

마지막 업데이트 2026-09-16