T_era
실시간 데이터 전송 방식 정리 본문
1. 데이터 전송 방식의 종류
- 브로드캐스트(Broadcast)
네트워크에 연결된 모든 디바이스(클라이언트)에게 데이터를 전송하는 방식 - 유니캐스트(Unicast)
한 명의 특정 클라이언트에게만 데이터를 전송 - 멀티캐스트(Multicast)
여러 명의 특정 그룹(여러 클라이언트)에게만 데이터를 전송
2. 옛날 방식: Polling
- Polling
클라이언트가 주기적으로 서버에 데이터를 요청하는 방식 - Short-Polling
- 일정 주기마다 서버에 요청
- 구현이 쉽지만, 불필요한 네트워크 트래픽 발생
- Long-Polling
- 클라이언트가 요청 후, 서버에서 데이터가 준비될 때까지 대기
- 데이터가 준비되면 응답, 아니면 타임아웃
- Short-Polling보다 오버헤드가 적음
3. Server-Sent Events (SSE)
- 특징
- 서버 → 클라이언트 단방향 실시간 데이터 전송
- HTTP 기반 (Content-Type:
text/event-stream) - 브라우저가 자동으로 재연결 시도
- 단점
- 단방향(서버→클라이언트)만 지원
- 브라우저 호환성 이슈(IE 미지원)
- 클라이언트 연결 종료 감지 어려움
간단 예시 (Kotlin/Spring):
@RestController
class SseController {
@GetMapping("/sse", produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun sseEmitter(): SseEmitter {
return SseEmitter().apply {
send("안녕하세요! 현재 시간: ${LocalDateTime.now()}")
complete()
}
}
}
4. WebSocket
- 특징
- 서버 ↔ 클라이언트 양방향 실시간 통신(Full-Duplex)
- 저지연, 낮은 오버헤드
- 단점
- 세션 관리 및 Scale-Out이 어려움
- 재연결 로직 직접 구현 필요
핵심 코드 예시 (Kotlin/Spring):
@Configuration
@EnableWebSocket
class WebSocketConfig : WebSocketConfigurer {
override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
registry.addHandler(ChatWebSocketHandler(), "/chat").setAllowedOrigins("*")
}
}
@Component
class ChatWebSocketHandler : TextWebSocketHandler() {
private val sessions = mutableSetOf<WebSocketSession>()
override fun afterConnectionEstablished(session: WebSocketSession) { sessions.add(session) }
override fun handleTextMessage(session: WebSocketSession, message: TextMessage) {
sessions.forEach { it.sendMessage(TextMessage("에코: ${message.payload}")) }
}
override fun afterConnectionClosed(session: WebSocketSession, status: CloseStatus) { sessions.remove(session) }
}
동작 과정
- 클라이언트가 HTTP 요청에
Upgrade: websocket헤더를 추가해 프로토콜 업그레이드 요청 - 서버가 101 Switching Protocols로 응답, WebSocket 연결 성립
- 이후 데이터는 Frame 단위로 양방향 송수신
5. STOMP (Simple Text Oriented Messaging Protocol)
- 특징
- WebSocket 위에서 동작하는 메시징 프로토콜
- 목적지(토픽) 기반 메시지 송수신
- 외부 브로커(RabbitMQ, ActiveMQ 등) 연동 가능
핵심 코드 예시 (Kotlin/Spring):
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/ws")
}
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.setApplicationDestinationPrefixes("/app")
registry.enableSimpleBroker("/topic")
}
}
@Controller
class GreetingController {
@MessageMapping("/greeting")
fun handle(greeting: String): String = "[${getTimestamp()}] $greeting"
private fun getTimestamp() = SimpleDateFormat("MM/dd/yyyy h:mm:ss a").format(Date())
}
- 클라이언트가
/topic/greeting을 구독하면,/app/greeting으로 메시지 전송 시 브로커가 구독자에게 전달
6. 요약
| 방식 | 특징 | 장점 | 단점 |
|---|---|---|---|
| Polling | 주기적 요청 | 구현 쉬움 | 불필요 트래픽 |
| Long-Polling | 서버에서 대기 후 응답 | 오버헤드 적음 | 구현 복잡 |
| SSE | 서버→클라이언트 단방향 | 표준, 간단 | 단방향, IE 미지원 |
| WebSocket | 양방향, Full-Duplex | 실시간, 저지연 | 세션/스케일 관리 어려움 |
| STOMP | 토픽 기반 메시징(WebSocket) | 브로커 연동 쉬움 | 브로커 필요 |
'Programing > Spring' 카테고리의 다른 글
| Spring WebSocket 알림 기능 구현 및 테스트 경험 정리 (1) | 2025.07.09 |
|---|---|
| RestTemplate 직접 생성 vs 빌더 생성 차이와 동작 원리 (0) | 2025.07.08 |
| Spring Boot + AWS S3 프로필 이미지 API 구현 (1) | 2025.07.01 |
| Spring Boot EC2 배포 & 테스트 과정에서 문제 해결 (0) | 2025.06.30 |
| 헬퍼(Helper)와 유틸(Utility)의 차이, 그리고 실전 코드 예시 (0) | 2025.06.25 |