이제 rack.response_finished는 나의 가장 친한 친구입니다

Friendship Ended with Rack::BodyProxy

작성자
발행일
2025년 08월 26일

핵심 요약

  • 1 rack.response_finished는 Rack 미들웨어에서 응답 완료 후 작업을 효율적으로 처리하기 위한 새로운 표준 후처리 메커니즘입니다.
  • 2 기존 Rack::BodyProxy는 미들웨어의 후처리 작업을 가능하게 했으나, 객체 할당 오버헤드와 실행 시점 문제로 성능 저하를 유발했습니다.
  • 3 rack.response_finished는 Rails ActionDispatch::Executor를 포함한 주요 웹 서버 및 프레임워크에 채택되며 Rack 생태계의 성능 최적화에 기여하고 있습니다.

도입

Rack은 Ruby 웹 애플리케이션과 웹 서버 간의 인터페이스를 정의하며, 응답은 상태, 헤더, 본문의 세 가지 요소를 포함합니다. 특히 본문은 단순한 문자열 배열뿐만 아니라 #each 메서드를 구현하여 스트리밍 방식으로 처리될 수도 있습니다. 이러한 유연성은 미들웨어에서 응답 본문이 완전히 생성된 후에 특정 작업을 수행해야 할 때 복잡성을 야기하며, 본 글은 이 문제를 해결하기 위한 Rack의 진화 과정을 다룹니다.

Rack::BodyProxy의 등장과 한계

Rack 미들웨어는 응답 본문이 스트리밍될 때 본문 내용 생성 전에 #call이 반환되어 후처리 작업이 어려웠습니다. 이를 해결하기 위해 Rack 명세에 #close 훅이 추가되었고, Rack::BodyProxy가 도입되었습니다.

BodyProxy는 본문 객체를 래핑하여 #close 호출 시 등록된 콜백을 실행, 본문 반복 후 작업을 수행하게 했습니다. 그러나 BodyProxy는 다음과 같은 한계를 가집니다.

  • 객체 할당 오버헤드: 미들웨어마다 BodyProxy 객체를 중첩 할당하여 가비지 컬렉션 부하를 증가시키고 성능 병목을 유발합니다.
  • 실행 시점 문제: BodyProxy는 본문 반복 직후 실행되지만, 웹 서버와 리버스 프록시 간의 연결이 완전히 닫히기 전일 수 있습니다. 이로 인해 지표 전송 같은 작업이 연결을 불필요하게 유지시켜 성능 저하를 초래하는 사례가 있었습니다 (GitHub, Shopify).

rack.response_finished의 부상

BodyProxy의 한계를 극복하기 위해 rack.after_reply 개념이 Puma에 2011년 도입되었고, 이후 Unicorn에도 추가되었습니다. 이는 Rack 3 SPEC의 선택적 부분인 rack.response_finished로 표준화되었습니다. 웹 서버는 env[“rack.response_finished”]를 통해 지원을 알리고, 미들웨어는 여기에 콜백을 등록하여 응답 본문 전송 및 연결 종료 후 작업을 수행할 수 있습니다.

rack.response_finished 콜백은 (env, status, headers, error) 인자를 받으며, BodyProxy와 달리 객체 할당 없이 후처리 작업이 가능합니다. 초기에는 채택이 더뎠지만, Falcon과 Pitchfork에 이어 Rails Event Reporter PR을 통해 ActionDispatch::Executor에 rack.response_finished 지원이 추가되면서 전환점을 맞았습니다. 이는 요청 컨텍스트를 정확한 시점에 클리어하고 요청 요약 로깅 등을 효율적으로 수행하게 했습니다.

현재 Rack 3.2에서는 Rack::ConditionalGet과 Rack::Head에서 BodyProxy가 제거되었으며, Rack::TempfileReaper, ActiveSupport::Cache::Strategy::LocalCache, 그리고 Puma에서도 rack.response_finished 지원이 활발히 추가되고 있습니다.

결론

rack.response_finished는 Rack::BodyProxy가 가진 객체 할당 오버헤드와 부적절한 실행 시점 문제를 해결하는 강력하고 효율적인 대안입니다. 이 새로운 메커니즘은 응답이 완전히 처리되고 연결이 닫힌 후에 후처리 작업을 수행할 수 있도록 하여, 웹 애플리케이션의 성능을 최적화하고 더욱 견고한 미들웨어 설계를 가능하게 합니다. Rails를 비롯한 주요 프레임워크와 웹 서버에서 rack.response_finished의 채택이 가속화됨에 따라, Rack 개발자들은 이제 BodyProxy 대신 이 새로운 친구와 함께 더 나은 아키텍처를 구축할 수 있게 될 것입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!