Active Job 및 Turbo Broadcast Later를 위한 ViewComponent 직렬화

Serializing ViewComponent for Active Job and Turbo Broadcast Later

작성자
발행일
2025년 09월 14일

핵심 요약

  • 1 ViewComponent를 Active Job의 `broadcast_action_later_to`와 연동하기 위한 직렬화 방안이 제시되었습니다.
  • 2 ViewComponent의 `initialize` 메서드 제약으로 인해 `serializable` 클래스 메서드와 커스텀 `ViewComponentSerializer`를 활용한 해결책이 제안되었습니다.
  • 3 Hotwire 컴포넌트의 비동기적 백그라운드 갱신을 가능하게 하여 DOM ID 및 스트림 타겟 관리의 복잡성을 줄이는 것이 핵심 목표입니다.

도입

최근 Rails 애플리케이션에서 ViewComponent 사용이 증가함에 따라, 특히 Hotwire와 연동하여 컴포넌트의 비동기적 갱신을 구현하려는 요구가 커지고 있습니다. 기존 Rails 애플리케이션에서 `turbo_stream_from`을 통해 컴포넌트를 갱신할 때, Stream 및 Broadcast 렌더러 간의 DOM ID와 스트림 타겟을 일치시키는 과정은 번거로울 수 있습니다. 이 글은 이러한 문제를 해결하고 Hotwire 컴포넌트의 갱신 로직을 백그라운드 작업으로 옮겨 효율성을 높이기 위한 ViewComponent 직렬화 방법을 탐구합니다.

ViewComponent를 Turbo Rails의 broadcast_action_later_to와 함께 사용하려면 ViewComponent 객체가 Active Job에 의해 직렬화될 수 있어야 합니다. 이는 broadcast_action_later_to가 인수를 직렬화하여 백그라운드 Job으로 실행하기 때문입니다. 그러나 ViewComponent를 직렬화하는 과정에는 몇 가지 도전 과제가 존재합니다. 특히 ViewComponent의 initialize 메서드가 컬렉션 렌더링을 위해 파라미터 내성(introspection)을 수행하므로, 일반적인 방식으로 initialize를 재정의하거나 모듈을 prepend하는 것이 복잡성을 야기합니다. 이러한 제약 사항을 고려하여, 저자는 다음의 해결책을 제시합니다.

serializable 클래스 메서드 도입

ViewComponent의 인스턴스 생성 시 new 대신 serializable 클래스 메서드를 사용합니다. 이 메서드는 ViewComponent를 인스턴스화하면서 초기화 인수를 @serializable_args 인스턴스 변수에 저장하여 직렬화에 필요한 정보를 보존합니다.

ruby module ViewComponent module Serializable extend ActiveSupport::Concern included do attr_reader :serializable_args end class_methods do def serializable(*args) new(*args).tap do |instance| instance.instance_variable_set(:@serializable_args, args) end end ruby2_keywords(:serializable) end end end

커스텀 ViewComponentSerializer 구현

Active Job이 ViewComponent 객체를 직렬화하고 역직렬화할 수 있도록 ActiveJob::Serializers::ObjectSerializer를 상속받는 ViewComponentSerializer를 정의합니다.

  • serialize? 메서드는 인수가 ViewComponent::Base의 인스턴스이고 serializable_args에 응답하는지 확인하여 직렬화 대상을 식별합니다.

  • serialize 메서드는 ViewComponent의 클래스 이름과 serializable_args를 직렬화하여 저장합니다.

  • deserialize 메서드는 저장된 클래스 이름과 인수를 사용하여 ViewComponent 객체를 재구성합니다.

ruby class ViewComponentSerializer < ActiveJob::Serializers::ObjectSerializer def serialize?(argument) argument.is_a?(ViewComponent::Base) && argument.respond_to?(:serializable_args) end def serialize(view_component) super( "component" => view_component.class.name, "arguments" => ActiveJob::Arguments.serialize(view_component.serializable_args), ) end def deserialize(hash) hash["component"].safe_constantize&.new(*ActiveJob::Arguments.deserialize(hash["arguments"])) end ActiveJob::Serializers.add_serializers(self) end

이러한 접근 방식은 broadcast_action_later_to와 같은 비동기 작업에서 ViewComponent를 renderable로 전달할 수 있게 하여, 백그라운드에서 Hotwire 컴포넌트 갱신을 처리하는 유연성을 제공합니다. 저자는 이 기능이 Rails, Active Job, Turbo의 현재 상태에서 일급 시민(first-class) 행동으로 간주되어야 한다고 주장하며, 라이브러리 유지보수자들이 인체공학, 복잡성, 성능 간의 최적의 균형을 찾도록 독려하고 있습니다.

결론

이 글은 ViewComponent를 Active Job 및 Turbo Broadcast later와 연동하여 비동기적인 컴포넌트 갱신을 구현하는 실용적인 방법을 제시합니다. `serializable` 클래스 메서드와 커스텀 `ViewComponentSerializer`를 통해 ViewComponent의 직렬화 문제를 해결함으로써, 개발자는 Hotwire 기반의 동적 UI를 백그라운드 작업으로 처리하여 애플리케이션의 성능과 유지보수성을 향상시킬 수 있습니다. 저자는 이 기능이 Rails 생태계의 핵심 부분으로 통합되어야 한다는 의견을 피력하며, 라이브러리 차원에서의 공식적인 지원을 기대하고 있습니다. 이는 ViewComponent의 활용 범위를 넓히고 더욱 견고한 Rails 애플리케이션을 구축하는 데 기여할 것입니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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