티스토리 뷰
이 사진 처럼 페이지를 이동할때마다 현재 나에게 도착한 쪽지의 개수를 출력 하는 방법을 알아 보겠습니다.
실시간 채팅, 실시간 알림 기능등에 사용되는 웹 소켓을 사용해서 구현 했습니다.
웹소켓이란
서버와 클라이언트 사이의 양 방향 통신을 지원하기 위한 프로토콜 이라고 생각 하면 됩니다.
기존의 http 프로토콜은 단방향 통신을 지원하기 위한 프로토콜 이었지만 좀더 사용자의 다양한 요구를 수용하기 위해 웹소켓이라는 것이 탄생하게 되었습니다.
웹 소켓의 연결을 설정할때는 http 프로토콜을 사용하기 때문에 기존의 http 포트번호(80)을 그대로 사용해서 웹소켓을 사용할수 있으며
http에 비해서 웹소켓은 헤더가 상대적으로 작기때문에 실시간 통신에 아주 적합합니다.
좀더 자세한 정보는 구글링 하시는게 빠릅니다..
스프링에서 웹소켓을 구현하는 방법을 설명하겠습니다.
우선 맨처음 해야 할 일은 웹소켓 의존설정을 추가해줘야합니다.
<!-- Spring websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
pom.xml 에 위와 같은 의존설정을 추가해줍시다.
<!-- 웹소켓 사용 -->
<websocket:handlers>
<websocket:mapping path="/count" handler="myHandler"/>
</websocket:handlers>
<!-- 웹 소켓 핸들러 -->
<beans:bean id="myHandler" class="com.javalec.ex.handler.WebSocketHandler"/>
그리고나서 위와 같이 서버단에서 실시간 웹 소켓 요청을 처리해줄 핸들러를 생성하고 /count로 들어오는 경로에 대해서 웹 소켓 핸들러가 처리하겠다고 명시해줍니다.(servlet-context.xml)
@Repository
public class WebSocketHandler extends TextWebSocketHandler {
@Autowired
SqlSession sqlsession;
private final Logger logger = LogManager.getLogger(getClass());
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
NoteDao dao = sqlsession.getMapper(NoteDao.class);
this.logger.info(message.getPayload());
session.sendMessage(new TextMessage(dao.count_receive_note(message.getPayload())));
//현재 수신자에게 몇개의 메세지가 와있는지 디비에서 검색함.
}
}
우리가 웹 소켓을 사용하기 위해서 해주어야 할일은 TextWebSocketHandler 을 상속받은 핸들러 클래스를 정의하는것 뿐입니다.
이 클래스를 만들게 되면 자동으로 3개의 메소드가 오버라이드 되는데,
afterConnectionClosed -> 웹 소켓 연결이 종료되고 나서 서버단에서 실행해야할 일들을 정의해주는 메소드
afterConnectionEstablished -> 연결이 성사 되고 나서 해야할 일들.
handleTextMessage-> 웹소켓 서버단으로 메세지가 도착했을때 해주어야할 일들을 정의하는 메소드 입니다.
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
NoteDao dao = sqlsession.getMapper(NoteDao.class);
this.logger.info(message.getPayload());
session.sendMessage(new TextMessage(dao.count_receive_note(message.getPayload())));
//현재 수신자에게 몇개의 메세지가 와있는지 디비에서 검색함.
}
가장 중요한 메소드인 handleTextMessage입니다.
jsp파일에서 클라이언트가 현재 접속중인 닉네임을 웹소켓을 통해서 서버로 보내면 이 메소드가 실행됩니다.
그 현재 접속중인 닉네임은 message.getPayload() 라는 함수를 통해서 메시지에 담긴 텍스트값을 얻을 수 있습니다.
dao.count_receive_note 함수는 수신자의 닉네임을 통해서 수신함에서 현재 수신자에게 몇개의 쪽지가 와있는지를 카운트 하는 기능을 가진 메소드입니다.
즉 클라이언트로부터 현재 접속중인 사용자의 닉네임을 얻고 그것을 통해 디비에 접근해서 현재 몇개의 쪽지가 와있는지 카운트를 하고 다시 클라이언트에게 그 카운트된 숫자를 메세지에 담아서 보내주는 형식으로 웹소켓 핸들러를 구현하였습니다.
이제는 jsp파일을 살펴보겠습니다.
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<security:authorize access="isAuthenticated()">
<security:authentication property="principal.bNick" var="nick"/>
<!-- 웹 소켓 사용해서 현재 몇개의 쪽지가 도착했는지 구해오기. -->
<script type="text/javascript">
var wsUri = "ws://localhost:8181/ex/count";
function send_message() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt);
};
websocket.onmessage = function(evt) {
onMessage(evt);
};
websocket.onerror = function(evt) {
onError(evt);
};
}
function onOpen(evt)
{
websocket.send("${nick}");
}
function onMessage(evt) {
$('#count').append(evt.data);
}
function onError(evt) {
}
$(document).ready(function(){
send_message();
});
</script>
</security:authorize>
위에서 부터 차근히 살펴보겠습니다.
<security:authorize access="isAuthenticated()">
<security:authentication property="principal.bNick" var="nick"/>
스프링 시큐리티 관련 태그입니다. 이 태그를 사용하기 위해선 태그라이브러리를 추가해 줘야 합니다.
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
서버의 과부하를 조금이라도 줄여주기 위해서 로그인된 상태일때만 웹소켓을 활용해서 현재 몇개의 쪽지가 도착했는지 구하도록 구현했습니다.
즉 로그인이 된 상태라면 security:authorize 태그에서 허가가 될것이고, 그렇다면 principal.bNick에서 현재 로그인된 사용자의 닉네임을 nick이라는 변수로 참조 할 수 있게 됩니다.
var wsUri = "ws://localhost:8181/ex/count";
이 부분은 웹 소켓을 요청할 경로입니다. 위의 경로로 메세지를 보내게 될 경우 아까 설정했던
<websocket:handlers>
<websocket:mapping path="/count" handler="myHandler"/>
</websocket:handlers>
맵핑 경로에 걸리게 되므로 웹소켓 핸들러가 요청을 처리할수있게 됩니다.
실행 순서대로 나열 해보면
$(document).ready(function(){
send_message();
});
jsp가 로드 되면 send_message() 라는 함수를 호출합니다.
function send_message() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt);
};
websocket.onmessage = function(evt) {
onMessage(evt);
};
websocket.onerror = function(evt) {
onError(evt);
};
}
send_message() 라는 함수가 실행되면 new WebSocket(wsUri)문을 통해서 웹소켓 객체를 생성하고
websocket.onopen = function(evt) {
onOpen(evt);
};
onOpen이란 함수를 다시 실행하게 됩니다. evt란 이벤트의 약자입니다.
function onOpen(evt)
{
websocket.send("${nick}");
}
onOpen함수에서는 아까 시큐리티에서 설정했던 nick값을 웹소켓 서버로 전송하는 역할을 하게 됩니다. 이런 방식으로 클라이언트에서 서버로 값을 전달 하게 됩니다.
우리가 클라이언트측에서 해주어야 할 일은 웹소켓 객체를 생성하고 그 웹소켓 객체의 메소드3개만 지정해주면 됩니다.
(onopen,onmessage,onerror)
각각 웹소켓 세션이 열렸을때, 서버->클라이언트로 메세지가 도착했을때, 오류가 발생했을때 실행되는 메소드입니다.
이렇게 되면 클라이언트에서 웹소켓객체를 생성할때 지정했던 경로로 현재 로그인된 사용자의 닉네임을 전송하게 되며
서버에서는 그 닉네임을 통해 데이터베이스에서 수신함에서 현재 로그인된 사용자에게 온 쪽지의 개수를 카운팅 하여 다시 클라이언트로 응답을 보내기 때문에 우리는 이제 뷰에서 몇개의 쪽지가 도착했는지를 설정해 줄 수 있게 됩니다.
function onMessage(evt) {
$('#count').append(evt.data);
}
메세지가 도착했을 경우 count라는 아이디를 가진 태그에 도착한 데이터의 값을 넣어주는 제이쿼리 코드입니다.
<span id="count" class="badge bg-theme"></span>
그렇게 되면 이부분에 몇개의 쪽지가 도착했는지 표시 됩니다.
'컴퓨터 공학과 졸업 > 스프링 프로젝트' 카테고리의 다른 글
[스프링/시큐리티] 로그인 실패시 화면에 입력했던 아이디 다시 띄우기 onAuthenticationFailure, AuthenticationFailureHandler (0) | 2017.08.31 |
---|---|
[spring security/스프링 시큐리티] 비밀번호 암호화와 로그인 하기 (0) | 2017.08.28 |
스프링 웹소켓 구현 (0) | 2017.08.22 |
스프링 시큐리티 관련 (0) | 2017.08.11 |
스프링 회원관리 비밀번호 찾기 (2) | 2017.08.08 |
- Total
- Today
- Yesterday
- hydrate
- await
- reflow
- webpack
- Polyfill
- useEffect
- react
- reactdom
- return type
- react hooks
- state
- useRef
- props
- design system
- Action
- Babel
- reducer
- atomic design
- mobx
- async
- Next.js
- server side rendering
- es6
- javascript
- type alias
- rendering scope
- promise
- typescript
- storybook
- computed
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |