Ruby로 최소한의 데코레이터 구축하기

Build a minimal decorator with Ruby in 30 minutes - Remi Mercier

작성자
Ruby Weekly
발행일
2025년 06월 12일

핵심 요약

  • 1 본 문서는 Ruby on Rails 애플리케이션에서 뷰 관련 로직을 모델에서 분리하기 위한 데코레이터 패턴의 구현 방법을 다룹니다.
  • 2 기존 `draper` gem의 제약으로 인해, `method_missing` 및 `SimpleDelegator`를 활용하여 최소한의 데코레이터를 직접 구축하는 과정을 상세히 설명합니다.
  • 3 최종적으로 Ruby의 `SimpleDelegator`를 통해 복잡한 위임 로직을 추상화하여 간결하고 효과적인 데코레이터 구현 방안을 제시합니다.

도입

Ruby on Rails 개발 시, 뷰(View)와 관련된 프레젠테이션 로직이 모델(Model)에 혼재되는 문제는 코드의 가독성과 유지보수성을 저해합니다. 일반적으로 이러한 문제를 해결하기 위해 데코레이터(Decorator) 패턴이 사용되며, `draper`와 같은 인기 있는 젬(gem)들이 활용됩니다. 그러나 특정 Rails 버전과의 호환성 문제 등으로 인해 `draper` 젬을 사용할 수 없는 상황이 발생할 수 있습니다. 본 문서는 이러한 제약 조건 속에서, 뷰 관련 메서드를 객체에 추가해야 하는 필요성에서 출발하여, Ruby의 기본 기능을 활용해 최소한의 데코레이터를 직접 구축하고, 점진적으로 개선해 나가는 과정을 설명합니다.

초기 문제 상황은 Teacher 모델에 available_places와 같은 비즈니스 로직 외에 뷰에서 필요한 colour_coded_availability와 같은 CSS 클래스 생성 로직이 포함되는 것이었습니다. 모델은 순수한 비즈니스 로직을 담당해야 하므로, 이러한 뷰 로직은 분리되어야 합니다. 이를 위해 TeacherDecorator라는 데코레이터 클래스를 생성하여 Teacher 인스턴스를 래핑하고 colour_coded_availability 메서드를 정의했습니다.

하지만 데코레이터를 적용한 후 teachers/index.html.erb 뷰에서 래핑된 teacher 객체의 full_name과 같은 모델 본연의 메서드를 호출할 때 NoMethodError가 발생했습니다. 이는 데코레이터가 래핑된 객체의 메서드를 알지 못하기 때문입니다. 이 문제를 해결하기 위해 Ruby의 핵심 기능인 method_missingrespond_to_missing?을 활용했습니다. method_missing을 오버라이드하여 데코레이터에 정의되지 않은 메서드 호출이 발생하면 래핑된 teacher 객체로 해당 호출을 public_send를 통해 위임하도록 구현했습니다. respond_to_missing? 또한 래핑된 객체의 메서드 응답 여부를 확인하도록 하여, NoMethodError 없이 메서드 호출이 가능해졌습니다.

이러한 위임 로직을 다른 데코레이터에서도 재사용하기 위해 ApplicationDecorator라는 상위 클래스를 생성하고, TeacherDecorator가 이를 상속하도록 하여 공통 위임 로직을 추상화했습니다. 이로써 각 데코레이터는 자신만의 뷰 로직에만 집중할 수 있게 되었습니다.

더 나아가, Rails의 기본 헬퍼 메서드(edit_teacher_path 등)가 데코레이터 인스턴스를 올바르게 처리하지 못하는 문제가 발생했습니다. 이는 헬퍼가 객체의 to_param 메서드를 호출하여 ID를 얻기 때문인데, 데코레이터가 이를 위임하지 않아 데코레이터 객체 자체가 경로에 포함되는 문제가 발생했습니다. 이 문제를 해결하기 위해 ApplicationDecoratordelegate :to_param, to: :record를 추가하여 to_param 메서드 호출 또한 래핑된 객체로 위임하도록 했습니다.

그러나 모든 Rails 기본 동작을 수동으로 위임하는 것은 복잡성을 증가시킬 수 있습니다. 이에 대한 궁극적인 해결책으로 Ruby 표준 라이브러리의 SimpleDelegator를 도입했습니다. SimpleDelegator는 생성자에 전달된 객체의 모든 지원되는 메서드 호출을 자동으로 위임하는 기능을 제공합니다. 이를 통해 ApplicationDecorator에서 initialize, method_missing, respond_to_missing?, to_param 등의 복잡한 위임 로직을 완전히 제거하고, 단지 ApplicationDecorator < SimpleDelegator로 상속받는 것만으로 모든 위임이 자동으로 처리되도록 구현했습니다. SimpleDelegator는 래핑된 객체에 __getobj__ 메서드를 통해 접근할 수 있도록 제공하며, 이를 alias_methodteacher와 같이 의미 있는 이름으로 변경하여 데코레이터 내부에서 사용의 편의성을 높였습니다. 이로써 데코레이터 코드는 놀랍도록 간결해졌고, 원하는 뷰 로직만 포함하게 되었습니다.

결론

본 문서는 Ruby on Rails 환경에서 뷰 로직과 모델 로직을 명확히 분리하기 위한 데코레이터 패턴의 구현 과정을 단계별로 제시했습니다. 초기 수동 구현부터 `method_missing`을 통한 위임, 그리고 최종적으로 Ruby의 강력한 표준 라이브러리인 `SimpleDelegator`를 활용하여 데코레이터 구현을 극도로 간결하고 효율적으로 만드는 방법을 보여주었습니다. `SimpleDelegator`를 사용함으로써 개발자는 복잡한 위임 로직에 대한 고민 없이, 오직 뷰를 위한 프레젠테이션 로직에만 집중할 수 있게 됩니다. 이는 코드의 유지보수성을 향상시키고, 객체 지향 원칙을 준수하는 데 크게 기여합니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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