Rack에서 스트리밍 바디는 애플리케이션이 body
로 호출 가능한 객체(예: proc
)를 반환할 때 작동합니다. Rack은 먼저 헤더를 전송한 후, write
, flush
, close
를 구현하는 스트림 객체를 전달하여 연결을 닫지 않고 클라이언트에 데이터를 푸시할 수 있게 합니다. 이는 실시간 진행률 표시줄이나 로그 표시, 그리고 연결을 다시 열지 않고 새로운 데이터가 도착할 때까지 요청을 유지하는 롱 폴링 구현에 유용합니다. Puma와 같은 서버에서 스트리밍 바디를 사용할 경우, 각 요청이 스레드를 점유하여 동시 연결 수가 많아지면 스레드 부족 현상이 발생할 수 있습니다. 이를 해결하기 위해 Ruby Fibers를 사용하는 Falcon 서버가 대안으로 제시됩니다. Falcon은 각 요청을 경량의 파이버에서 실행하여 단일 스레드 내에서 수백 개의 협력적 파이버를 멀티플렉싱함으로써 Puma의 스레드 한계를 극복하고 병렬 처리를 가능하게 합니다.
Server-Sent Events (SSE)는 서버에서 클라이언트로만 이벤트를 전송하는 표준으로, HTTP 연결을 유지합니다. 브라우저에서는 JavaScript EventSource
API를 사용하고, 서버는 Content-Type: text/event-stream
헤더로 응답합니다. 본문에서는 Thread::Queue
를 사용하여 이벤트 생산과 소비를 분리하고, 스트림 스레드가 블로킹되는 것을 방지하기 위해 Thread.new
로 백그라운드 스레드에서 이벤트를 생성하는 예시를 보여줍니다. 이는 데이터 소스를 유연하게 변경하고(예: Redis pub/sub 또는 PostgreSQL LISTEN/NOTIFY) 경쟁 조건을 피하는 데 도움이 됩니다.
WebSockets은 HTTP 핸드셰이크(101 Switching Protocols) 이후 TCP 연결을 유지하여 클라이언트와 서버가 동시에 데이터를 주고받을 수 있는 전이중(full-duplex) 프로토콜입니다. 이는 채팅과 같은 양방향 통신 애플리케이션에 이상적입니다. WebSocket 프로토콜을 직접 구현하는 것은 복잡하지만, faye-websocket
gem을 사용하면 낮은 수준의 세부 사항을 추상화하여 쉽게 구현할 수 있습니다. 본문에서는 faye-websocket
gem을 활용하여 활성 연결을 관리하고, 메시지를 모든 연결된 클라이언트에 브로드캐스트하는 간단한 채팅 애플리케이션의 Rack 서버 및 HTML 클라이언트 구현 예시를 제시합니다. ping: KEEPALIVE
매개변수를 사용하여 연결을 유지하고, web_socket.rack_response
를 통해 올바른 핸드셰이크 헤더를 포함한 Rack 배열을 반환하는 방법을 설명합니다.