◆ SPRING WEB SOCKET
스프링은 별도의 웹 소켓 서버를 설치하지 않아도 웹 소켓 기능을 사용할 수 있게 지원한다.
웹 소켓 API를 사용하게 되면 서버에서 클라이언트로 먼저 응답을 보내는 것이 가능해진다.
웹 소켓은 채팅기능 구현에 주로 쓰일 수 있는데, 웹 소켓 없이 만들경우 setInterval스크립트 함수를 이용하여 구현할 수 있지만 요청이 많아지기 때문에 과부하가 생길 수 있다.
- setInterval 예 )
위와 같이 계속해서 상태를 요청하여 받아오게 되면 과부하가 발생할 수 있다.
하지만 웹 소켓을 이용하게 되면 다른 클라이언트의 요청 발생시에만 모든 클라이언트의 상태를 갱신할 수 있기 때문에 과부하가 발생할 확률이 적다.
▶ 라이브러리 연동
Spring은 WAS를 가지고도 웹 소켓 서버의 기능을 구현할 수 있게 해두었음.
- -메이븐추가( Spring WebSocket )
▶ 웹 소켓 처리 컨트롤러 작성방법
웹 소켓을 처리할 컨트롤러는 두 가지 방식으로 처리할 수 있다
1. WebSocketHandle를 implements걸어서 목적에 맞게 개조해서 사용.
2. 목적에 맞는 WebSocketHandler를 extends걸어서 사용
- 문자처리 : TextWebSocketHandler
- 파일처리 : BinaryWebSocketHandler
◆ TextWebSocketHandler를 이용한 WebSocket통신
TextWebSocketHandler를 extends하여 생성한 컨트롤러는 afterConnectionEstablished, handleTextMessage, afterConnectiopnClosed 메서드를 Override해야 한다.
▶ 컨트롤러 작성 예제
- 해당 메서드에서의 session은 HTTPSESSION객체와는 전혀 다른 객체이다.
- 자동 등록되는 객체들은 init-method를 설정할 타이밍이 없기 때문에 init()메서드를 만들어서 @PostConstruct 어노테이션을 붙여주면 init메서드로 설정된다.
- session.sendMessage(new TextMessage(“”));메서드로 메시지를 전달할 수 있다.
- session.getRemoteAddress().getAddress().getHostAddress() : 클라이언트 ip반환
▶ 웹 소켓 핸들러 등록
웹 소켓 컨트롤러의 경우 경로를 @RequestMapping을 통해서 지정하는 것이 아니라 스프링 설정파일에서 빈 객체를 등록 할 때 경로를 설정할 수 있다. 단 접근은 Websocket을 통해서만 할 수 있다.
1. 스프링설정파일 -> Namespaces -> websocket 체크
2. 태그를 이용하여 핸들러 등록
- handler옵션으로 컨트롤러의 id를 적어주고(ref), path에 접근(매핑) 경로를 적어준다.
<context:component-scan>으로 등록된 컨트롤러들은 자동으로 클래스이름(또는 앞에만 소문자)를 id로 갖는다.
또는 @Controller(“id”)형식의 어노테이션을 이용 하는것도 가능하다.
▶스크립트를 이용하여 웹 소켓 연결
웹 소켓 컨트롤러와 클라이언트를 연결하기 위해서는 스크립트를 통하여 연결을 시켜야 한다.
-
- 소켓 연결
- new WebSocket("ws:// ip(:port)/수정경로/컨트롤러경로");
=> ${pageContext.request.serverName}은 서버의 ip를 반환해준다.
-
- 연결이 됐을 때( onopen )
-
- 메시지가 들어올 때( onmessage )
obj.data로 서버에서 보낸 메시지를 확인할 수 있다.
( GSON으로 메시지를 보냈을 때 JSON.parse(obj.data)를 이용하여 사용할 수도 있다. )
-
- 연결이 끊길 때 ( 서버가 꺼질 때 )
- 메시지 보내기
위 처럼 스크립트를 통해 메시지를 보낼 수도 있지만, 소켓 컨트롤러의 각 클라이언트의 WebSocketSession객체를 따로 저장하여 서비스객체를 통해 메시지를 보낼 수도 있다.
※ 주의
한 페이지에서 스크립트를 이용해 소켓을 생성할 시 다른 페이지로 넘어갈 때 해당 소켓과의 연결이 해제 된다. 따라서 여러 페이지에서 소켓통신을 사용해야 할 경우 각 페이지마다 소켓을 생성하거나, 소켓을 생성하는 페이지를 include시켜야 한다.
=> 즉 여러 페이지에서 소켓을 생성할 시 연결/해제를 반복하며 통신이 이루어진다. 따라서 연결된 WebSocketSession객체를 컨트롤러에 저장할 때도 연결될 때마다 새로 저장시키게 된다.
▶ 웹 소켓 컨트롤러에서 HttpSession가져오기
웹 소켓을 처리하는 컨트롤러에서는 메서드의인자로 HttpSession객체를 가져 올 수 없다.
따라서 HttpSession객체를 제어할 수 없기 때문에 웹 소켓 컨트롤러에서 HttpSession객체의 데이터가 필요한 경우 설정이 필요하다.
( 단, 실제로 HttpSession객체를 가져오는 것이 아닌 세션이 가지고 있는 데이터만을 불러오는 것이기 때문에 세션객체를 제어할 수는 없다. )
1. 스프링 설정파일 수정
등록한 웹 소켓 컨트롤러에 handshke-interceptiors를 이용하여 HttpSessionHandshakeInterceptor를 등록한다.
( HttpSession 객체를 가로채기 )
2. HttpSession객체 가져오기
위 1번처럼 등록을 하게 되면 session.getAttributes();를 이용하여 Map<String,Object>형태로 HttpSession객체를 가져올 수 있다.
로그인된 사용자의 socket을 저장하는 예)
서비스객체로 WebSocketSession객체를 넘겨주어 따로 저장한다.