웹소켓과 폴링
계획
뭔가 오늘 밀도 높게 산건 아니고 평범한 하루였는데 작업들을 잘게 쪼개니까 많이 한 것 처럼 됐다.
오늘 익힌 내용
웹소켓과 폴링
https://www.youtube.com/watch?v=R_agd5qZ26Y
이 영상에 나오는 기능 중 하나에 쓰인다. 우버의 운전수가 탑승객에게 주기적으로 실시간 위치 정보를 쏴준다.
이때 사용자 수도 많고 실시간 데이터도 많다는 걸 고려해야 한다.
2초마다 폴링한다고 하면 1. 탑승객 API측 레이턴시, 2. 탑승객 API측 부하를 가진다고 한다.
- 만약 운전수가 위치 정보를 업데이트했을 때, 탑승객은 재수 없으면 2초 후에 받아보게 된다.
- 계속해서 API 서버에 질의하므로 부하가 발생한다.
이러한 이유로 웹소켓을 선택하는 편이 부하를 줄일 수 있다고 한다.
여기서 드는 생각은, 실시간 서비스중 어느 경우에 웹소켓을 사용하게 되고, 문제가 있다면 어떤 점에서 생길지 궁금했다. 그 전에 서버의 이벤트를 클라이언트로 보내는 방법을 알아보자.
- polling : http 요청을 서버로 계속 날려 이벤트 내용을 전달한다. 요청 빈도가 높으면 부하가 증가하고, 빠른 응답을 기대하기도 어렵다는 단점이 있다.
- 배치 작업 할때나 유용한 듯 싶다
- http를 사용하므로 매번 연결을 맺고 끊는 비용이 발생한다 (connectionless)
- long-polling : 서버 측에서 접속을 열어두는 시간을 길게 하는 방식이다. 그러니까, 클라이언트에서 요청 받은 상태에서 이벤트가 아직 발생 안 했으면 이벤트 발생 후에야 응답하는 것이다.
- 여러 클라이언트에게 동시 이벤트 발생시 서버 부담이 급증한다. (커넥션을 유지하는 비용 때문으로 보임)
- websocket : 양방향 채널을 이용해 양방향 통신을 수행한다. http가 아닌 ws 프로토콜을 사용해 웹소켓 포트에 접속해 있는 모든 클라이언트에게 이벤트 방식으로 응답한다.
- 최초 접속시 http를 사용해 handshking하므로 기존 80, 443 포트를 사용하며, 인증 과정 등을 그대로 유지할 수 있다는 장점이 있다.
- 지속적인 커넥션을 유지해야 하기 때문에 클라이언트 수가 많으면 서버 자원이 급격히 소진되며, 이 특성 때문에 (statefull) 로드 밸런서나 클러스터 환경에서 스케일링이 복잡하다. 테스트도 어렵다.
- 실시간 통신이 필요하지 않은 경우 / 네트워크 및 서버 자원이 제한된 경우 꼭 사용해야 할지 고려해보자
- SSE(Server-Sent Events) : HTML5의 표준이며 웹소켓의 역할을 하면서 더 가볍다. server -> client 단방향 구조이기 때문에 push 작업에 유용하다.
참조에 남겨놓은 실시간 댓글 개발기를 보면, 소켓 + STOMP 테스트하기 어려웠던 문제는 다음과 같았다
- 연결을 유지한 상태에서 테스트가 진행
- 한 번 보내고 끝나는 일반 API들과 달리 단계별로 접근해야 함(CONNECT -> CUBSCRIBE -> SEND 등)
- 소켓 연결, 유지, 끊는 과정에서 사용된 리소스가 제대로 반환되었는지 확인이 어려움(메모리 누수 가능)
- 서버가 죽었을 때, 원인이 커넥션 과부하 때문인지 전송되어야 할 메시지가 빌렸기 때문인지 파악이 어려움
여기서는 이러한 문제들 때문에 STOMP 프로토콜은 무시하고, GoLang으로 소켓만 잘 연결되는지 확인했다고 한다.
GoLang의 경우 Java / Python 프로그램보다 클라이언트 요청에 대해 리소스(heap)를 훨씬 효율적으로 사용한다고 한다.
추가로 저 내용 말고도 여러 내용이 있었는데, 메서드를 까보면서 캐시 사용에 따라 메서드를 바꿔끼우며 튜닝하는 과정이 흥미로웠다.
STOMP
Websocket 위에서 동작하는 간단한 텍스트기반 메시지 프로토콜이며, 클라이언트와 서버 간 전송할 메시지 유형, 형식, 내용을 정의한다. (pub-sub)
- 연결 주소마다 새 핸들러를 구현 / 설정할 필요가 없고, 메시지 브로커를 활용해서 구독을 관리하고 Broadcast할 수 있다.
참조
- https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-Polling-Long-Polling-Server-Sent-Event-WebSocket-%EC%9A%94%EC%95%BD-%EC%A0%95%EB%A6%AC
- https://tech.kakao.com/2020/06/15/websocket-part2/
- https://velog.io/@msung99/%EC%9B%B9%EC%86%8C%EC%BC%93%EA%B3%BC-STOMP%EB%A5%BC-%ED%86%B5%ED%95%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%ED%86%B5%EC%8B%A0-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0
일기
오늘 멘토링을 받았다. 멘토링을 하면서 느낀 점은 뭔가 내가 너무 인턴했던 회사의 피드백에 묶여 모든 걸 거기 기준으로 생각하는 건 아닐까? 하는 생각이 들었다. 예를 들어, 나는 이러이러한 피드백들을 받았으니까 이건 명백한 내 약점이야. 보다는 아 여기는 핏이 이런 측면에서 안 맞았어. 하는 식으로도 생각할 수 있을 것 같다.
또, 내가 교육을 계속해서 받아왔지만 오히려 그것 때문에 내 객관적인 평가를 하기 어려울 수도 있겠다는 피드백을 받았다. 생각해 보니 내가 무언갈 겪어보면서 헤딩하기 보다는, 교육을 듣는 입장이다 보니까... 시도 자체를 안 하면 내 스스로에 대한 평가가 어렵겠다는 생각이 들었다.
앞으로는 해커톤 같은 기회들이 있다면 무지성으로 지원해 보면서 여러 경험, 도메인 지식 등을 쌓아보는 것이 좋을 것 같다. DB 테이블 설계 경험 등에도 도움을 받을 수 있을 것도 같다.