본문 바로가기
Spring/WebSocket

[Spring WebSocket] SSE vs WebSocket

by 진꿈청 2024. 11. 4.

SSE와 WebSocket, 그들은 왜 실시간 통신 환경에서 자주 비교될까?

우리가 알림과 실시간 채팅 같은 서비스를 구현할 때, 우리는 자연스럽게 두 가지 기술 사이에서 고민한다.

`SSE`와 `WebSocket`은 각기 다른 매력을 가졌다.

 

 

실시간 통신의 필요성

앞서, 언급한 것처럼 알림을 띄우거나 실시간 채팅 서비스에서 실시간 통신은 선택이 아닌 필수이다.

 

그런데 문제는 단방향이냐, 양방향이냐가 된다. 

 

양방향 통신을 택하면 더 복잡하지만 매력적이고, 단방향 통신은 기능은 적지만 그만큼 단순하다.

둘 중 어느 쪽을 고를지를 결정하기 위해서는 기술들의 성격을 좀 더 들여다 봐야 한다.

 

 

SSE (Server-Sent Events)

`SSE`는 마치 인프런 강의처럼 강사가 우리에게 일방적으로 강의를 하는 것과 같다. 

청강생(클라이언트)은 계속해서 강사에게 듣고 받아 적어야 한다.

 

  • 청강생: 강사님, 질문이 있습니다!
  • SSE: 안됩니다. 질문할 수 없어요.

`SSE`는 서버가 클라이언트에게 일방적으로 데이터를 푸시할 때 사용된다.

HTTP 기반이라 프록시나 방화벽이 거부하지 않는다.

 

서버에서 매초마다 데이터를 보낸다고 상상해보자.

 

Server-Side

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;

@RestController
public class SSEController {

    @GetMapping("/sse")
    public void streamEvents(HttpServletResponse response) throws IOException {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");

        PrintWriter writer = response.getWriter();
        for (int i = 1; i <= 5; i++) {
            writer.write("data: SSE 이벤트 #" + i + "\n\n");
            writer.flush();
            try {
                Thread.sleep(1000);  // 1초마다 이벤트 전송
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        writer.close();
    }
}

 

 

Client-Side

const eventSource = new EventSource('/sse');

eventSource.onmessage = function(event) {
    console.log("새 이벤트 수신:", event.data);
};

eventSource.onerror = function() {
    console.error("SSE 연결 오류 발생");
};

 

 

장점:

  • `SSE`는 자동 재연결을 지원한다.
  • 설정이 간단하여 빨리 구현하고 싶은 개발자에게는 최적이다.

단점:

  • 오직 단방향이다. 클라이언트는 서버에게 말을 걸 수 없다.
  • 데이터를 텍스트로만 보내는게 편리하다.(이미지나 비디오 전송은 어렵다)

 

WebSocket

`WebSocket`은 전화를 하는 것과 똑같다.

양방향 통신이 가능하기 때문에 서버와 클라이언트가 자유롭게 대화를 주고 받는다.

 

  • A: "지금 뭐해?"
  • B: "지금 게임중"

 

아래는 서버와 클라이언트가 통신하는 예제이다.

 

Server-Side

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new TextWebSocketHandler() {
            @Override
            protected void handleTextMessage(WebSocketSession session, TextMessage message) 
                    throws Exception {
                session.sendMessage(new TextMessage("에코: " + message.getPayload()));
            }
        }, "/ws");
    }
}

 

Client-Side

const socket = new WebSocket('ws://localhost:8080/ws');

socket.onopen = () => {
    console.log('WebSocket 연결 성공!');
    socket.send('안녕, 서버!');
};

socket.onmessage = (event) => {
    console.log('받은 메시지:', event.data);
};

 

 

장점:

  • 양방향이라 서버와 클라이언트가 마음껏 대화를 할 수 있다.
  • 텍스트뿐만 아니라 바이너리 데이터도 전송할 수 있다. (즉, 그림도 보내는 것이 가능하다)

단점:

  • 설정이 조금 귀찮다. 방화벽에 걸리기도 쉽고, 초기 핸드쉐이크까지 해야 한다.
  • 재연결? 그런건 없다. 알아서 다시 연결할 방법을 마련해야 한다.

 

SSE vs WebSocket

비교 항목 SSE WebSocket
통신 방식 단방향 (서버 → 클라이언트) 양방향 (서버 ↔ 클라이언트)
사용 사례 실시간 알림, 뉴스 피드 채팅, 게임, 협업 도구
프로토콜 HTTP/1.1 TCP
재연결 지원 자동 재연결 지원 별도 구현 필요
설정의 간편함 매우 간편 복잡함
방화벽 친화성 우호적 주의 필요

 

 

정리

SSE:

  • "넌 듣기만 해, 보내는 건 나만 보낼꺼야"에 적합하다.
  • 실시간 뉴스나 알림처럼 서버에서 클라이언트로만 정보가 흐를 때 좋다.

WebSocket:

  • "같이 소통해요~" 스타일이다.
  • 채팅, 게임처럼 상호작용이 필요한 경우 선택하는 것이 좋다.

 

참고

https://ducktopia.tistory.com/137

'Spring > WebSocket' 카테고리의 다른 글

[Spring WebSocket] STOMP  (0) 2024.11.04
[Spring WebSocket] SockJS  (2) 2024.11.04
[Spring WebSocket] WebSocket  (0) 2024.11.04