Action Cable
Rails 내장 WebSocket — 실시간 기능 구현
Action Cable은 Rails에 내장된 WebSocket 프레임워크로, 서버→클라이언트 실시간 통신을 가능하게 합니다.
서버 (Channel): ChatChannel 클래스에서 subscribed 메서드로 stream_from "chat_room_1" 형태로 채널을 구독하고, receive 메서드로 수신 데이터를 ActionCable.server.broadcast로 브로드캐스트합니다.
클라이언트 (JavaScript): consumer.subscriptions.create로 채널에 구독하고, received 콜백에서 수신 데이터를 DOM에 반영합니다.
Turbo Stream과 결합하면 JavaScript 없이도 실시간 DOM 업데이트가 가능합니다. Turbo::StreamsChannel.broadcast_append_to로 서버에서 직접 DOM 요소를 추가/수정/삭제할 수 있습니다.
WebSocket 활용 사례: 실시간 음성 받아쓰기 (STT)
WebSocket은 실시간 음성 인식(STT)에도 핵심적으로 사용됩니다. Deepgram, Azure Speech 같은 서비스는 WebSocket 연결을 열고 오디오 스트림을 100~200ms 단위로 연속 전송하면, 서버가 실시간으로 중간 결과(interim)와 최종 결과(final)를 반환합니다.
REST API 방식 (Groq Whisper): 녹음을 4초 세그먼트로 잘라 HTTP POST로 전송 → 지연 4~5초, 문맥 단절
WebSocket 방식 (Deepgram/Azure): 오디오 청크를 연속 스트리밍 → 지연 0.3~1초, 문맥 유지
Rails에서 구현 시, Action Cable을 WebSocket 프록시로 활용하여 브라우저 → Rails(Action Cable) → 외부 STT API(WebSocket) 형태로 연결할 수 있습니다.
Rails에서 WebSocket 사용 시 주의사항
1. 프로덕션 어댑터 필수
개발 환경:
async어댑터 (기본값, 단일 프로세스)프로덕션: 반드시
redis또는solid_cable어댑터 사용config/cable.yml에서 환경별 설정Rails 8부터 Solid Cable (DB 기반) 사용 가능 — Redis 없이도 프로덕션 운영
2. Nginx/리버스 프록시 설정
- WebSocket은 HTTP Upgrade 핸드셰이크가 필요하므로 Nginx에 별도 설정 필수:
location /cable {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
- 이 설정이 없으면 WebSocket 연결이 426 에러로 실패
3. 인증과 보안
ApplicationCable::Connection에서cookies.encrypted[:user_id]로 인증config.action_cable.allowed_request_origins— 허용 도메인 설정 필수 (CSRF 방지)프로덕션: 반드시
wss://(TLS) 사용,ws://는 중간자 공격에 취약
4. 커넥션 관리와 메모리
각 WebSocket 연결은 서버 메모리를 지속 점유 — 동시 접속자 × 연결당 메모리로 계산
Action Cable JS는 자동 재연결하지만, Channel의
unsubscribed콜백에서 리소스 정리 필수Puma의
max_threads설정이 동시 WebSocket 수를 제한 — 충분히 설정할 것
5. 수평 확장 (Scaling)
멀티 서버: Redis Pub/Sub로 서버 간 메시지 동기화
로드밸런서: Sticky Session 필요 (WebSocket은 연결 유지형이라 서버 고정 필요)
대규모 서비스: AnyCable 검토 — Go/Rust 기반으로 Ruby 대비 10배 성능, Action Cable API 호환
6. 테스트
ActionCable::Channel::TestCase로 Channel 단위 테스트assert_broadcast_on/assert_has_stream으로 브로드캐스트 검증통합 테스트: Capybara + JS 드라이버 (System Test)에서 WebSocket 동작 확인
핵심 포인트
rails generate channel Chat → Channel 클래스 생성
subscribed에서 stream_from으로 채널 구독
ActionCable.server.broadcast로 메시지 브로드캐스트
클라이언트가 consumer.subscriptions.create로 구독
received 콜백에서 수신 데이터 처리
Turbo Stream과 결합: broadcast_append_to로 DOM 자동 업데이트
장점
- ✓ Rails 내장 — 별도 설치 불필요
- ✓ Turbo Stream과 완벽 통합
- ✓ Channel 패턴으로 구조적
- ✓ 인증 자동 연동 (current_user)
- ✓ Rails 8: Solid Cable로 Redis 없이도 프로덕션 가능
단점
- ✗ WebSocket 연결 유지 비용 (메모리/커넥션)
- ✗ Redis 어댑터 필요 (프로덕션, Rails 7 이하)
- ✗ 수평 확장 시 Sticky Session 또는 AnyCable 필요
- ✗ 디버깅 어려움 (비동기 + 네트워크)
- ✗ Nginx에 WebSocket Upgrade 설정 필수