Rails ViewComponents: 깔끔하고 재사용 가능한 뷰를 위한 해법

ViewComponents, the Missing View Layer for Rails

작성자
발행일
2025년 11월 11일

핵심 요약

  • 1 ViewComponents는 Rails 뷰의 복잡성을 해소하고, 헬퍼, 인스턴스 변수, 인라인 로직으로 인한 비대화 및 강한 결합 문제를 해결하여 응집도 높은 UI 컴포넌트 개발을 가능하게 합니다.
  • 2 애플리케이션 특정(Application-specific) 및 범용(General-purpose) 컴포넌트, Slots, 조건부 렌더링, CSS 클래스 커스터마이징 등 ViewComponents의 다양한 기능을 활용하여 뷰 계층의 책임 분리와 재사용성을 극대화합니다.
  • 3 ViewComponents는 미리보기(Previewing) 및 통합된 테스트(Unit/System Test) 기능을 제공하여 UI 개발 워크플로우를 개선하고, 컨트롤러와 뷰의 역할을 명확히 분리하여 코드의 가독성과 유지보수성을 향상시킵니다.

도입

Rails 애플리케이션 개발 시 뷰(View) 레이어는 헬퍼, 인스턴스 변수, 인라인 로직 등으로 인해 빠르게 비대해지고 다른 뷰 관련 로직과 강하게 결합되는 경향이 있습니다. 이는 뷰가 여러 책임을 떠안게 만들어 유지보수성을 저해하며, 컨트롤러나 프레젠터(Presenter)를 활용하더라도 근본적인 문제 해결에는 한계가 있습니다. 이러한 문제점을 해결하고 뷰 계층의 응집도를 높이기 위해 'Rails의 누락된 뷰 레이어'라고 불리는 ViewComponents가 등장했습니다. ViewComponents는 뷰 관련 관심사를 단일 위치에 효과적으로 캡슐화하여, 재사용 가능한 UI 컴포넌트 구축을 위한 명확하고 격리된 방법을 제시합니다.

ViewComponents는 적절한 관심사 분리, 미리보기, 테스트 용이성 등 다양한 이점을 제공하며, UI 컴포넌트 개발 패러다임을 변화시킵니다. 특히 컴포넌트 객체와 렌더링 뷰 코드를 한 곳에 두는 co-location은 UI 컴포넌트가 단일 책임에 집중하도록 돕습니다. 본문에서는 사용자 목록 페이지 예시를 통해 ViewComponents의 적용 과정을 상세히 설명합니다. 초기에는 컨트롤러, 프레젠터, 뷰에 걸쳐 분산되어 있던 필터 설정, 사용자 데이터 래핑, 페이지네이션 구성, 테이블 렌더링, 드롭다운 액션 처리 등의 책임들이 ViewComponents를 통해 명확히 분리됩니다.

ViewComponents 적용 단계

  • 필터 컴포넌트 (Filters Component):
    • UsersFilterComponent (애플리케이션 특정): 사용자 필터링 로직을 정의합니다.
    • FilterComponent (범용): 재사용 가능한 필터 렌더링 로직을 처리합니다.
    • 이를 통해 컨트롤러에서 필터 관련 로직이 제거되고, index.html.erbUsersFilterComponent.new만 렌더링하게 됩니다.
  • 사용자 컴포넌트 (UserComponent):
    • 테이블 본문 내의 개별 사용자 렌더링 로직을 추상화합니다.
    • 기존 UserPresentercurrent_rolesdropdown_actions 메서드를 UserComponent 내부로 이동시켜 프레젠터를 제거하고 컨트롤러를 간소화합니다.
    • index.html.erb@users.each 루프 내에서 UserComponent.new(user:)를 렌더링합니다.
  • 사용자 테이블 컴포넌트 (UsersTableComponent와 Slots):
    • 테이블 전체 구조를 추상화하며, renders_many :users, UserComponent를 사용하여 사용자 컬렉션을 UserComponent로 렌더링합니다.
    • headers 메서드를 통해 테이블 헤더를 정의합니다.
    • index.html.erbUsersTableComponent.new(pagy: @pagy)를 블록 형태로 렌더링하고, with_users 슬롯을 통해 각 사용자를 전달합니다.
  • 테이블 컴포넌트 (TableComponent와 Slots):
    • 범용적인 테이블 구조(<thead>, <tbody>, <tfoot>)를 위한 컴포넌트입니다.
    • renders_one :header, renders_one :body, renders_one :footer 슬롯을 활용하여 테이블의 각 부분을 분리합니다.
    • UsersTableComponent는 이 TableComponent를 사용하여 일관된 스타일을 유지합니다.
  • CSS 클래스 커스터마이징:
    • TableComponentclasses 인자를 추가하여 최상위 요소에 커스텀 CSS 클래스를 적용할 수 있도록 합니다.
    • class_names 헬퍼를 활용하여 조건부 CSS 클래스 토글 기능을 구현합니다.
  • 페이지네이션 컴포넌트 (PaginationComponent와 조건부 렌더링):
    • 페이지네이션 관련 로직을 별도의 PaginationComponent로 추상화합니다.
    • UsersTableComponentrenders_one :pagination, PaginationComponent를 사용합니다.
    • #render? 메서드를 구현하여 특정 조건에서만 컴포넌트가 렌더링되도록 합니다.

미리보기 및 테스트

  • 미리보기 (Previewing): Rails Mailer와 유사하게 컴포넌트를 애플리케이션과 격리된 환경에서 테스트할 수 있는 미리보기 기능을 제공합니다. Lookbook과 같은 도구를 활용하면 더욱 강력한 기능을 사용할 수 있습니다.

  • 테스트 (Testing):

    • 단위 테스트 (Unit Test): 컴포넌트 내부에 정의된 메서드들의 로직을 검증합니다.
    • 시스템 테스트 (System Test): Capybara를 활용하여 컴포넌트의 HTML 출력이 예상대로 렌더링되는지 엔드투엔드 흐름을 테스트합니다.

결론

ViewComponents를 통해 뷰의 다양한 관심사를 추상화함으로써, 컨트롤러는 비즈니스 로직에 더 집중할 수 있게 되어 서비스 객체, 쿼리 객체, 폼 객체와 같은 개념을 도입하기에 자연스러운 환경이 조성됩니다. 최종적으로 컨트롤러와 뷰의 인터페이스는 훨씬 깔끔해지며, 다음 엔지니어는 뷰의 복잡한 세부 사항에 대해 걱정할 필요 없이 기능 요구사항에 집중할 수 있습니다. ViewComponents는 컴포넌트 로직, 렌더링, 미리보기, 테스트를 위한 전용 위치를 제공하여 코드의 가독성, 유지보수성, 재사용성을 크게 향상시키며, Rails 애플리케이션의 뷰 계층 개발 방식을 혁신하는 강력한 도구입니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

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