채팅 시스템은 거의 WebSocket으로 구현한다. 오늘은 Unix프로그래밍 수업에서 배웠던 소켓과 같은 부류인 웹소켓에 대하 알아보자!
ㅁWebSocket: 하나의 TCP 연결을 통해 클라이언트와 서버 간에 실시간, 양방향 통신을 가능하게 해주는 프로토콜
2011년 IETF에 의해 RFC 6455로 표준화되었으며, HTML5의 일부로 웹 브라우저에서 기본적으로 지원된다
1. WebSocket 특징
- Full-duplex 통신
HTTP는 요청-응답 기반의 Half-duplex 구조이나, WebSocket은 요청 없이도 서버가 클라이언트에게 자유롭게 데이터를 보낼 수 있는 구조이다. 이를 통해 실시간 알림, 채팅, 게임 등에서 즉각적인 반응을 구현할 수 있다. - 연결 유지(Persistent Connection)
WebSocket은 최초 연결 시 HTTP 프로토콜을 사용해 핸드셰이크를 진행한 후, TCP 기반의 연결을 유지한다. 따라서 매번 새로 연결을 생성하지 않아도 되어 오버헤드가 줄어든다. - 헤더 오버헤드 감소
HTTP 요청과 응답은 많은 양의 헤더 정보를 포함하고 있지만, WebSocket은 최초 핸드셰이크 이후에는 최소한의 헤더만을 사용하여 네트워크 사용량이 적다.
2. WebSocket 작동 방식
- 클라이언트가 HTTP를 통해 서버에 WebSocket 연결을 요청한다.
- 서버가 101 Switching Protocols 응답을 보내며 프로토콜을 WebSocket으로 전환한다.
- 연결이 성립되면, 양방향 통신이 가능해진다.
- 연결 종료 시 클라이언트 또는 서버가 close 프레임을 전송하여 연결을 닫는다.
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
아래는 실제 내가 프로젝트를 진행하며 작성했던 WebSocket 명세서이다
[WebSocket 명세서 예시] - SK AXIS: AI 면접관 도우미
항목 | 내용 |
URL | ws://sk-axis-fastapi:8000/ws/nonverbal |
Protocol | WebSocket |
연결 시점 | 면접 시작 시 Vue에서 연결 |
종료 시점 | 면접 종료 시 Vue에서 .close() 호출 |
전송 데이터 형식 (1초 주기)
[
{
"interviewee_id": 101,
"is_speaking": false,
"posture": {
"leg_spread": 0,
"leg_shake": 0,
"head_down": 0
},
"facial_expression": {
"smile": 0,
"neutral": 4,
"embarrassed": 0,
"tearful": 0,
"frown": 0
}
},
{
"interviewee_id": 102,
"is_speaking": true,
"posture": {
"leg_spread": 1,
"leg_shake": 0,
"head_down": 2
},
"facial_expression": {
"smile": 1,
"neutral": 3,
"embarrassed": 0,
"tearful": 0,
"frown": 0
}
}
]
코드 구현 예시
① websocket.py (FastAPI 라우터)
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
import json
router = APIRouter()
@router.websocket("/ws/nonverbal")
async def nonverbal_ws_endpoint(websocket: WebSocket):
await websocket.accept()
print("🟢 WebSocket 연결됨")
try:
while True:
data = await websocket.receive_text()
nonverbal_payload = json.loads(data)
# 로그 출력 또는 저장 로직 삽입
print(f"수신 데이터: {nonverbal_payload}")
# 필요시 응답을 클라이언트로 보낼 수 있음 (현재는 단방향)
# await websocket.send_text("수신 완료")
except WebSocketDisconnect:
print("🔴 WebSocket 연결 종료")
② main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from websocket import router as websocket_router
app = FastAPI()
# CORS 설정 (Vue와 통신 위해 필요)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 프로덕션에선 정확한 origin 설정 권장
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# WebSocket 라우터 등록
app.include_router(websocket_router)
③ WebSocketClient.vue (Vue 컴포넌트)
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
let socket = null
const sendData = () => {
const data = [
{
interviewee_id: 101,
is_speaking: false,
posture: { leg_spread: 0, leg_shake: 0, head_down: 0 },
facial_expression: { smile: 0, neutral: 4, embarrassed: 0, tearful: 0, frown: 0 }
},
{
interviewee_id: 102,
is_speaking: true,
posture: { leg_spread: 1, leg_shake: 0, head_down: 2 },
facial_expression: { smile: 1, neutral: 3, embarrassed: 0, tearful: 0, frown: 0 }
}
]
if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify(data))
}
}
onMounted(() => {
socket = new WebSocket('ws://sk-axis-fastapi:8000/ws/nonverbal')
socket.onopen = () => {
console.log('🟢 WebSocket 연결 성공')
setInterval(sendData, 1000) // 1초 주기 전송
}
socket.onclose = () => {
console.log('🔴 WebSocket 연결 종료')
}
socket.onerror = (err) => {
console.error('⚠️ WebSocket 에러 발생', err)
}
})
onBeforeUnmount(() => {
if (socket) {
socket.close()
}
})
</script>
3. WebSocket vs HTTP vs SSE 정리표

4. WebSocket 활용 분야
- 실시간 채팅 서비스 (예: Slack, Discord)
- 실시간 주식/코인 시세 스트리밍
- 온라인 게임 서버
- 실시간 알림 시스템 (Push Notification)
- 화상 회의 및 음성 통화 서비스
+ 보안과 WebSocket
WebSocket도 보안 연결을 위해 HTTPS의 대응인 WSS(WebSocket Secure) 프로토콜을 지원한다. wss://는 TLS 암호화가 적용된 WebSocket 연결을 의미하며, 중간자 공격(MITM)을 방지할 수 있다!
'웹 > 웹 지식' 카테고리의 다른 글
[웹 지식] 그놈의 CORS(Cross-Origin Resource Sharing) - 교차 출처 리소스 공유 (6) | 2025.06.18 |
---|---|
[웹 지식] Blob 개념 + 실제 프로젝트 적용 예시 (3) | 2025.05.23 |
[웹 지식] 액세스 토큰 + 리프레시 토큰 협동 과정 (1) | 2025.04.03 |
[웹 지식] OpenAPI vs Open API (1) | 2025.04.02 |
[웹 지식] 사용자 행동 기법(로그 데이터 분석, 세션 리플레이, A/B 테스트, 히트맵 분석, 퍼널 분석, 사용자 여정 맵, 심리적 트리거 등) (3) | 2025.02.18 |