soominkim Study
article thumbnail
Published 2022. 10. 11. 09:48
[SpringBoot] Web Socket Java/Springboot
728x90

1. 웹소켓 탄생배경

기존 HTTP 프로토콜은 요청에 대해서만 응답을 보낼 수 있기 때문에 채팅에서 계속 메시지를 받기만 하는 상황을 구현하기 힘들었고 HTTP 프로토콜은 매 요청과 응답마다 연결을 수립하고 끊는 과정을 반복해야 했기 때문에 유사한 통신을 반복해야 한다는 비효율성에 대한 문제가 있었다. HTTP를 이용한 실시간 통신의 문제를 해결하기 위해 HTML5부터 웹소켓이 등장했습니다. 웹소켓은 실시간 양방향 통신 을 지원하며 한번 연결이 수립되면 클라이언트와 서버 모두 자유롭게 데이터를 보낼 수 있습니다. 이는 채팅과 같은 연속적인 통신에 대해 계속 유사한 통신을 반복하지 않게 해주어 통신의 효율성도 개선하였습니다.

 

2. 웹소켓 프로토콜

웹소켓은 HTTP와 같은 OSI 모델의 7계층에 위치하는 프로토콜이며, 4계층의 TCP에 의존합니다.
HTTP 프로토콜을 이용할 때 http 를 이용하는 것 처럼, 웹소켓을 이용할 때는 ws 를 이용합니다. 또한 보완을 강화한 https를 사용하는 것처럼, ws 에 대해 보완을 강화한 wss 를 사용할 수 있습니다. HTTP를 용해서 연결을 수립하며 연결 된 이후에도 연결을 할 때 사용했던 포트인 80과 443포트를 이용합니다 연결 수립은 핸드쉐이크를 통해 이루어지며 핸드쉐이크시 HTTP를 이용합니다.

 

3. 웹소켓 핸드쉐이크

 

Web Socket HandShake

 

4. 환경설정 application 

// cors 모두 허용
@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**").allowedOrigins("*");
	}
//  
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}

5. WebSocket 사용을 위한 dependency 추가

<!-- web socket -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>

6.  Controller

@Onopen : 클라이언트가 소켓에 연결될 때 이를 해당 메소드를 호출합니다

@Onclose : 클라이언트가 소켓과 연결이 종료될 때 해당 메소드를 호출합니다

@OnMessage : 메시지를 수신할 때 호출

@Component
@ServerEndpoint(value = "/websocket") // 서버가 바인딩된 주소를 뜻함.
public class Socket {
// 소켓에 있는 전체 리스트
	private static ArrayList<Session> sessionList = new ArrayList<Session>();

	@OnOpen // 클라이언트가 소켓에 연결되때 마다 호출
	public void onOpen(Session session) {
//		클라이언트가 소켓에 연결되면 해당 아이디를기록, 해당 아이디를 전체 리스트에 추가
		if (session != null) {
			String sessionId = session.getId();
			System.out.println("client is connected.sessionId == [" + sessionId + "]");
			sessionList.add(session);
//			웹소켓에 연결되어 있는 모든 사용자에게 메시지 전송
			sendMessageToAll("[USER-" + sessionId + "]님이 입장하셨습니다.");
		}
	}

	@OnClose // 클라이언트와 소켓과의 연결이 닫힐때 (끊길떄) 마다 호출
	public void onClose(Session session) {
		if (session != null) {
			String sessionId = session.getId();
			System.out.println("client is disconnected.sessionId == [" + sessionId + "]");
			sendMessageToAll("[USER-" + sessionId + "]님이 나가셨습니다.");
		}
	}

	@OnMessage
	public String onMessage(String message, Session session) {
		if (session != null) {
			String sessionId = session.getId();
			System.out.println("message is arrived.sessionId == [" + sessionId + "]/ message== [" + message + "]");
			sendMessageToAll("[USER-" + sessionId + "]" + message);
		}
		return null;
	}

	@OnError // 의도치 않은 에러 발생
	public void onError(Throwable t) {
		t.printStackTrace();
	}

7. 구현

728x90
profile

soominkim Study

@soominkim

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그