다 된 줄 알았는데
😑(모바일):제가 STOMP Connect가 된 건지 안 된 건지 모르겠어요
🍊: 어, Swift 라이브러리 stompClientDidConnect 등의 메소드로 수신되지 않으시나요?
😑(모바일): 연결이 끊겨도 걔가 이미 연결되어있는 것처럼 응답이 와요.
🍊..... 😱: 헐
😑(모바일): 그래서 재연결할 타이밍을 못 잡아요
🍊: 잠시 기다려주세요, 방법 찾아볼게요.
왜 그랬을까?
위의 글을 참고로 생각해보자.
요약하면 "클라이언트가 일방적으로 네트워크를 끊을 경우, 서버는 클라이언트의 종료 의사를 알지 못한다"
STOMP 모델도 WebSocket을 사용하여 동작하고 있고, 그 WebSocket은 TCP 기반 프로토콜이기 때문에 TCP 3-way handshake가 이루어진다. 이는 연결 종료 시점에도 handshake가 이루어는 게 정상인데, 그 과정이 제대로 이루어지질 않으니 서버는 이미 넌 나와 연결되어있지롱 하는 응답이 가는 거다.
해결방법: hearbeat 체크하기
/***
* @param registry 등록할 브로커 객체
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/{...}", "/{...}", "/{...}")
.setHeartbeatValue(new long[]{0, 10000}) // 서버X, 클라이언트의 10초 주기 Ping 기대
.setTaskScheduler(taskScheduler());
...
}
STOMP는 자체적으로 heart-beating이라는 기능을 지원한다. STOMP 프로토콜의 명세에 따르면, 클라이언트와 서버는 서로 주기적으로 heart-beat 메시지를 교환할 수 있으며 이를 통해 연결이 정상적으로 유지되고 있는지 확인할 수 있다.
위의 설정에 따르면 클라이언트가 일정 시간동안 heart-beat 메시지를 보내지 않는다면 서버는 연결이 끊어진 것으로 판단하고 연결을 정상 종료한다. new long[] 배열의 첫 번째 원소는 0을 주었는데, 이는 서버에서 ping을 날리는 주기로서, 0으로 만들어 안 날리겠다는 의미를 내포한다. 다만 클라이언트는 10초 주기의 통신을 보내기를 기대하는 상황이다.
func openConnection() {
let url = NSURL(string: "ws://{url}/ws")
socketClient = StompClientLib()
let headers = ["heart-beat": "10000, 0"] // heartbeat 설정 (ms 단위)
socketClient.openSocketWithURLRequest(request: NSURLRequest(url: url! as URL), delegate: self, connectionHeaders: headers)
}
그렇다면 그 기대에 맞게 Client도 heartbeat를 일정 주기에 맞게 보내면된다.
만약 통신상태가 걱정된다면, 서버보다는 더 빠른 주기를 맞추어 충족시키는 방법이 있을 것이다.