Rails의 delegated_type 명확하게 만들기

Making Rails delegated_type’s clearer - Kasper Timm Hansen

작성자
발행일
2025년 06월 29일

핵심 요약

  • 1 Rails의 `delegated_type`은 다중 테이블 상속을 위임(delegation) 방식으로 구현하지만, 현재 구조와 명칭은 도메인 모델링 및 코드 가독성 측면에서 개선이 필요합니다.
  • 2 작성자는 내부 타입의 독립성 부족, `-able` 접미사 사용, `ActiveSupport::Concern` 활용 방식 등 여러 문제점을 지적하며, 이는 개발자가 기능을 오해할 수 있게 만든다고 설명합니다.
  • 3 이에 대한 해결책으로 명확한 네이밍 컨벤션, 추상 부모 클래스 도입, 네임스페이스 활용, 그리고 `composed_with_delegate`와 같은 새로운 명칭 제안을 통해 `delegated_type`의 사용성과 일관성을 높이는 방안을 제시합니다.

도입

이 글은 Ruby on Rails 프레임워크의 `delegated_type` 기능에 대한 심층적인 분석과 개선 방안을 다룹니다. 저자는 `delegated_type`의 이름 자체가 기능의 본질을 명확히 전달하지 못하며, 강제된 구조가 특정 도메인 모델링 문제를 야기한다고 지적합니다. `delegated_type`은 Django에서 영감을 받은 다중 테이블 상속을 위임 방식으로 구현한 것으로, 외부 "메타데이터" 타입이 내부 "콘텐츠" 타입을 감싸는 형태로 설명될 수 있습니다. 외부 타입은 내부 타입 간에 공통된 데이터와 동작을 처리하며, 내부 타입은 각기 다른 데이터와 동작을 독립적으로 가질 수 있습니다. 본 글은 이러한 `delegated_type`의 문제점을 진단하고, 더욱 명확하고 일관성 있는 사용을 위한 구체적인 개선 방안을 제시합니다.

저자는 delegated_type의 현재 구조가 몇 가지 도메인 모델링 문제를 내포하고 있다고 설명합니다. 가장 큰 문제점은 MessageComment와 같은 내부 타입이 Entry와 같은 외부 타입 없이는 독립적으로 존재할 수 없음에도 불구하고, 코드 상에서는 이러한 제약이 명확히 드러나지 않는다는 점입니다. 이는 개발자가 내부 타입을 독립적인 최상위 모델로 오인하게 만들 수 있습니다. 저자는 이러한 내부 타입들을 Entry::MessageEntry::Comment와 같이 외부 타입의 네임스페이스 내에 두어 실제 도메인 모델링을 반영해야 한다고 주장합니다. 그러나 현재 delegated_type은 이러한 네임스페이스를 사용할 경우 entry_comment와 같은 어색한 접두사 메서드를 생성하는 문제가 있습니다.

이에 대한 개선 방안으로 저자는 다음과 같은 제안을 합니다:

  • 명시적 제약 조건 추가: 내부 타입이 외부 타입 없이는 존재할 수 없음을 명확히 하기 위해 has_one :entry, as: :entryable, touch: true, required: true와 같이 required: true 옵션을 추가하고, delegated_type에는 inverse_of: :entry, dependent: :destroy를 수동으로 할당해야 한다고 제안합니다.
  • 네이밍 컨벤션 개선: entryable과 같은 -able 접미사 사용에 대한 불만을 표하며, 이는 잘못된 네이밍의 신호라고 지적합니다. 대신 delegate와 같이 기능의 본질을 더 잘 나타내는 이름을 사용할 것을 제안합니다. 예를 들어, delegated_type :delegate, types: %w[Message Comment], dependent: :destroy와 같이 변경할 수 있습니다.
  • 추상 부모 클래스 도입 및 네임스페이스 활용: ActiveSupport::Concern 모듈을 사용하는 대신, 내부 타입들이 상속받을 추상 부모 클래스인 Entry::Delegate를 도입할 것을 제안합니다. Entry::Delegateself.abstract_class = true를 설정하고 has_one :entry, as: :delegate, touch: true, required: true를 포함하여, MessageComment 같은 내부 타입들이 이를 상속받도록 합니다. 이는 Entry 네임스페이스가 자신의 위임된 타입 정의를 소유하게 하여 불필요한 보일러플레이트를 줄이고, 애플리케이션 내의 여러 delegated_type 패턴에 일관성을 부여합니다. 또한, delegate_type 컬럼 이름이 delegate_type으로 명명되어 패턴의 일관성을 강화합니다.
  • 네임스페이스 지원 강화: delegated_type이 각 타입에 대해 메서드를 생성할 때, Entry::Message와 같은 네임스페이스 접두사를 자동으로 제거하여 생성된 메서드 이름이 불필요한 접두사를 가지지 않도록 수정하는 방안을 제시합니다. 이를 통해 app/models/entry 디렉토리에서 위임된 타입들을 직접 찾을 수 있게 되어 코드 탐색이 용이해집니다.
  • 명칭 재고: 저자는 delegated_type이라는 이름이 기능의 핵심을 충분히 전달하지 못한다고 판단하여, composed_with_delegate와 같은 대안적인 명칭을 제안하며, 이는 Entry가 내부의 가변적인 타입들과 구성된다는 점을 강조합니다.
  • 렌더링 개선: Entry 모델에 render_in 메서드를 정의하여 render entry와 같이 호출할 때 delegate 타입에 따라 _message.html.erb 또는 _comment.html.erb와 같은 적절한 부분 템플릿을 자동으로 렌더링하도록 개선하는 방안을 제시합니다. 이는 뷰 레이어에서 delegated_type을 다루는 방식을 간소화합니다.

결론

이 글은 Rails의 `delegated_type`이 가진 내재적인 문제점들을 날카롭게 분석하고, 이에 대한 실용적이고 구조적인 개선 방안들을 제시합니다. 명확한 네이밍 컨벤션, 추상 부모 클래스를 통한 상속 구조 확립, 그리고 네임스페이스의 적극적인 활용은 `delegated_type`의 사용성을 크게 향상시키고 코드의 가독성 및 유지보수성을 높일 수 있습니다. 또한, `composed_with_delegate`와 같은 명칭 변경 제안은 기능의 본질을 더 잘 표현함으로써 개발자들의 이해를 돕고자 하는 저자의 깊은 고민을 보여줍니다. 궁극적으로 이러한 제안들은 Rails 개발자들이 `delegated_type` 패턴을 보다 효과적이고 일관되게 적용하여 견고한 도메인 모델을 구축하는 데 기여할 것입니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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