📡

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 동작 확인

핵심 포인트

1

rails generate channel Chat → Channel 클래스 생성

2

subscribed에서 stream_from으로 채널 구독

3

ActionCable.server.broadcast로 메시지 브로드캐스트

4

클라이언트가 consumer.subscriptions.create로 구독

5

received 콜백에서 수신 데이터 처리

6

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 설정 필수

사용 사례

실시간 채팅 알림 시스템 실시간 대시보드 협업 편집 라이브 피드 실시간 음성 받아쓰기 (STT — WebSocket 프록시) 라이브 스트리밍 댓글/리액션