티스토리 뷰
들어가며
이번에 SSAFY에서 프로젝트를 진행하면서 처음으로 웹 기반의 게임을 만들게 되었습니다.
게임을 만들다 보니 클라이언트에서 실시간으로 서버의 데이터 변경을 감지하는 로직을 구현해야 했는데 이 부분을 해결하기 위해 Websocket을 사용했습니다. 당연히 Websocket도 처음 써보았습니다. 뭔가 쉬우면서도 어려운 것 같은 느낌..?
개발하느라 이론을 충분히 공부하지 못한 채로 기술을 사용했던게 아쉬워서 기술에 대한 이해와 의문을 해결하고 실시간 데이터 통신과 그 방법인 Websocket에 대한 이런저런 내용들을 정리하기 위해 글을 씁니다. 가볍게 읽어주시면 좋을듯 합니다.
실시간 데이터 변경 감지
실시간으로 데이터를 통신한다는 것은 어쩌면 개발자에게 당연하게 느껴지는 기술입니다. 실제로 대부분의 API가 그렇게 동작하죠. 그렇다면, 실시간으로 데이터 변경을 감지하는 것은 어떨까요?
HTTP는 요청 -> 응답의 순서로 흘러갑니다. 즉, 요청이 없으면 응답이 없는 것이죠. 그렇다는 것은 서버에서 어떤 데이터의 변경이 일어나도 클라이언트는 API를 호출하기 전까지 이 사실을 모른다는 것입니다.
이 문제점을 해결하기 위해 나온 방식이 Websocket입니다.
기존에는 COMET 기술을 사용한 HTTP기반의 요청, 응답 방식으로 실시간 데이터를 처리했습니다.
이 글에서는 깊게 다루지 않을테니 간단하게 설명하겠습니다.
Polling 방식, Long Polling 방식, Streaming 방식이 있는데
Polling 방식은 쉽게 말하면 인스타나 페이스북에서 화면을 위로 드래그하면 피드가 새로고침되는 것을 알 수 있습니다. 이 자동 새로고침을 주기적으로 계속 하는걸 말합니다. 주기가 짧으면 오버헤드가 큽니다.
Long Polling은 기본적인 원리는 Polling 과 같은데 클라이언트가 한 번 요청을 보내면 요청 자체를 오래 유지시켜 Connectionless인 HTTP를 마치 Connection-Oriented인 것처럼 사용하여 데이터 변경이 있을 때 서버에서 응답을 해주는 방식입니다. 이것은 데이터 변경이 잦을 경우 Polling과 거의 비슷합니다.
Streaming은 클라이언트의 요청을 무한정 대기시키고 chunked 기반의 메시지를 사용해 응답을 하더라도 연결을 유지시키는 방식입니다.
세 방법 모두. HTTP의 특징인 Connectionless를 극복하지 못해 저마다의 단점이 있습니다.
위 문제를 해결하기 위해 나온 방법이 Websocket입니다.
Websocket은 HTTP와 다르게 Connection을 유지하고 Message를 통해 통신한다는 특징이 있습니다.
웹브라우저는 http 프로토콜로 요청/응답으로 동작하는데 TCP/IP socket 처럼 connection이 유지되어 서로 실시간으로 통신을 할수 없습니다. 그래서 등장한것이 websocket 프로토콜입니다. websocket을 사용하면 웹브라우저에서도 socket 통신처럼 실시간으로 데이터를 주고 받을 수 있습니다.
이번에 제가 진행한 프로젝트가 보물찾기 게임이었는데 게임방을 만들고 실시간으로 누군가 보물을 찾았을 경우 해당 보물을 Closed 처리해주어 다른 사람이 해당 보물 위치에 헛걸음하지 않도록 구현하려 했습니다. 이 때, Websocket 기술을 적용했습니다.
Websocket의 강력한 장점, 헤더가 필요 없다.
Websocket은 처음 연결할때만 헤더 데이터를 보내고 이후엔 메시지 바디를 사용해서 통신합니다.
HTTP를 통해 데이터를 주고받을 경우 헤더와 바디를 통해 사용자를 식별하고 응답하게 되는데 매 요청마다 헤더,바디를 보내는 것과 메시지 바디만을 이용해 통신하는 차이에서 성능 상 큰 이점이 있습니다.
Backend Server에서 Websocket 설계 시
Websocket관련 문서들을 찾아보다 Websocket 로직을 처리하는 스레드에서 DB를 처리하는 로직을 함께 수행하는 것은 성능에 안좋은 영향을 끼칠 수 있다는 글을 봤습니다.
누군가 게임방에 입장했다는 메시지를 처리할 때, 메시지를 해당 게임방의 다른 사람들에게 뿌리는 것만 Websocket 스레드에서 처리하고, 게임방에 입장하는 (실제 DB에 데이터를 생성하는) 로직은 따로 API를 만들거나 Websocket 스레드와 별개로 처리해야 한다는 것입니다.
마무리
아직 공부를 진행중이라 틈틈이 내용을 보충해 채워넣도록 하겠습니다...!!!