벌써 쓴지 1년이 넘은 (시간 진짜 빠르네...) [업비트 웹소켓 요청제한 우회하기](https://blog.coinsect.io/posts/bypass-upbit-websocket-rate-limit) 글의 후속작업을 오늘 다시 진행했다.
[Cloudflare 터널로 돌려보기도](https://blog.coinsect.io/posts/upbit-websocket-aws-data-transfer-cost-reduction) 했지만 어차피 AWS Data Transfer는 Cloudflare로의 Outbound 트래픽으로 간주되어 과금은 줄어들지 않았었다.
결국 내린 결론은, 어쨌든 사용자들이 내 사이트에서 직접 업비트 웹소켓에 붙으면 나에게 있어 비용적으론 제일 좋지만 [코인충](https://coinsect.io) 도메인에 대해서 rate limit이 걸리기 때문에, 내가 업비트 웹소켓에 붙는 프록시 서버를 하나 만들고, 유저들이 여기를 보도록 하자는 것이었다.
작년에 시도한 첫째 방법과는 약간의 차이가 있는게, 그때는 특별히 프록시 서버 코드를 짠게 아니라 아래처럼 그냥 Nginx단에서 그대로 "우회"(Proxy)만 시켰었다.

그런데 이번에는 업비트 웹소켓 서버에 연결될 프록시 서버를 Go로 짜고, Nginx가 이걸 바라보게 처리해뒀다. 물론 Nginx는 뭐 꼭 필요하진 않은데 기존에 적어둔 위 세팅을 Go 서버가 뜬 localhost로 바꾸는 등 조금만 건드리면 됐어서 이 세팅을 가져갔다.
굳이 Go로 짠 이유는? 이미 서버에서 systemctl을 돌리고 있어서 세팅이 편하기도 하고, 무엇보다 **Nodejs보다 훨씬 빠르니까**.
[코드](https://github.com/kispi/coinsect_api/blob/main/proxy_upbit/main.go) 내용을 간략히 설명하자면,
- **[비용을 줄이는 핵심]** 스로틀링. 업비트에서 데이터가 내 서버로 왔다고 바로 연결된 클라이언트들에 브로드캐스팅하는게 아니라, 일정 시간마다 보내서 트래픽을 대폭 줄임.
- 업비트 서버와 **단 하나의 웹소켓 연결**만 유지.
- 연결이 끊어지면 자동으로 재연결 시도.
- 클라이언트들의 구독을 관리하고 각 클라이언트가 요청하는 티커들의 구독의 합집합을 구해서 업비트에 새로 요청.
- 클라이언트에 브로드캐스팅할때도, 매 클라이언트가 구독한 n개의 티커 중 업데이트된 m개를 보내기 위해 서버가 m번의 `writeMessage`를 하는게 아니라, 업데이트된 m개를 합쳐서 한 번만 `writeMessage`를 함.
- 업비트 웹소켓 데이터는 바이너리로 오기 때문에 이걸 JSON으로 파싱해야하는데, 이 로직을 클라이언트에서 서버로 옮김. (서버가 구조를 알아야 필요한 정보만 최신으로 갱신하며 최신 상태를 유지할 수 있으므로)
이처럼 위 Go 서버는 꽤나 복잡한 일들을 하는데, 이렇게 처리를 해도 어쨌든 비용은 늘어날 수 밖에 없다. 그렇지만 업비트 <=> n대의 클라이언트의 모든 트래픽을 무식하게 중개하던 먼저번의 방법처럼 거의 1TB에 달하는 outbound 요금이 부과되는 일은 없을거라고 기대해본다.
이 문제로 고통을 겪는 업비트 코인시세 중개 서비스 개발자분들이라면, 저 소스코드를 hostname 체크하는 부분 정도만 변경해서 거의 그냥 그대로 써도 될 것 같다.