Rails 뷰의 문제점
기존 뷰는 다음과 같은 문제를 야기합니다.
* 다중 모델/변수 접근: 뷰에서 여러 모델에 직접 접근하여 데이터 흐름 추적이 어렵습니다.
* 비즈니스 로직 침투: 뷰에 if current_user.subscription.active? 같은 비즈니스 로직이 혼재되어 책임 분리를 위반합니다.
* 성능 문제: user.articles.count와 같은 N+1 쿼리를 유발하여 성능을 저하시킵니다.
* 로직 분산: 동일한 비즈니스 규칙이 여러 뷰에 중복 구현되어 변경 시 일관성 유지가 어렵습니다.
* 테스트 어려움: 뷰 로직은 격리 테스트가 어렵고 통합 테스트에 의존하게 됩니다.
뷰 모델(View Model) 소개
뷰 모델은 컨트롤러와 뷰 사이에 위치하는 순수 Ruby 클래스입니다. 모델과 컨텍스트를 받아 뷰가 호출할 메서드를 제공하며, 프리젠테이션 결정을 처리하고 해당 요청의 유일한 DTO 역할을 합니다.
컨트롤러 및 뷰 사용 예시:
컨트롤러에서 UserProfileViewModel 인스턴스를 생성하여 데이터를 주입하고, 뷰에서는 @vm.display_name이나 @vm.show_premium_content처럼 뷰 모델의 메서드를 호출하여 렌더링합니다. 이로써 뷰는 프리젠테이션에만 집중합니다.
뷰 모델의 장점
- 로직 중앙화 및 단방향 흐름: 모든 프리젠테이션 로직이 컨트롤러에 집중되며, 뷰 모델을 통해 뷰에 전달되는 명확한 단방향 흐름을 확립합니다.
- 성능 향상: 필요한 데이터를 미리 로드(eager loading)하여 N+1 쿼리를 방지합니다.
- 의미론적 명확성: 뷰는 구현 세부사항 없이 의도를 명확히 전달하는 메서드를 호출합니다.
- 쉬운 테스트: 순수 Ruby 객체이므로 단위 테스트가 용이하며, 컨트롤러 요청 스펙으로 데이터 구성을 검증할 수 있습니다.
대안
- Presenters/Decorators (Draper): 단일 모델의 단순 프리젠테이션 로직에 적합합니다.
- View Components (ViewComponent): 재사용 가능한 UI 요소에 유용합니다.
- Cells: UI의 특정 부분에 대한 미니 컨트롤러로, UI와 로직을 강하게 연결합니다.