동적 필터 리팩토링으로 확장성과 유지보수성을 동시에 잡다!
동적 필터(Dynamic Filter)는 사용자의 선택에 따라 실시간으로 제휴점 수를 반영하여 직관적인 탐색 경험(Intuitive Search Experience)을 제공함
기존 구조는 페이지 타입별 필터 노출 정책을 처리하는 과정에서 코드 중복(Code Duplication)과 확장성 문제(Extensibility Issue) 발생
리팩토링을 통해 필터 노출 정책과 생성 흐름을 분리하고, 전략 패턴(Strategy Pattern)과 빌더 패턴(Builder Pattern)을 적용하여 구조 개선
개선된 구조는 페이지 타입별 정책 변경에 유연하게 대응하고, 유지보수성(Maintainability) 및 확장성(Scalability)을 향상시킴
확장성 저해 요인: 페이지 타입별 정책 분산
기존 동적 필터 구조는 페이지 타입별 필터 노출 정책을 처리하기 위해 조건문(Conditional Statements)과 중복된 Mapper(Duplicated Mappers)를 사용했다. 페이지 타입에 따라 필터를 숨기거나 노출하는 요구사항이 증가하면서, 코드 전반에 정책이 암묵적으로 흩어지는 문제가 발생했다.
AnchorMapper 내 조건문 추가: 단순 조건 처리
Creator 단계에서 페이지 타입 조건 처리: 복잡한 조건 처리
페이지 전용 Mapper 생성: 정책이 크게 다른 경우
이러한 방식은 단기적으로는 요구사항 반영에 용이했지만, 장기적으로는 유지보수성(Maintainability)을 저해하고 새로운 페이지 타입 추가 시 확장성(Extensibility)에 제약을 줬다.
리팩토링 목표: 정책과 생성 흐름의 분리
리팩토링의 핵심 목표는 필터 노출 정책과 필터 생성 흐름을 분리하는 것이었다. 필터 노출 정책은 변경 가능성이 높은 영역으로, 필터 생성 흐름은 안정적으로 유지되어야 하는 영역으로 간주했다. 이를 위해 전략 패턴(Strategy Pattern)을 활용하여 페이지 타입별 정책을 QuickFilterStrategy enum으로 명시적으로 정의하고, 필터 생성은 Builder 패턴(Builder Pattern)을 통해 하나의 공통된 파이프라인으로 통합했다.
정책 분리: QuickFilterStrategy enum
생성 통합: Builder와 Mapper 활용
확장성 확보: Predicate 조합으로 정책 표현
결과적으로 새로운 요구사항이 발생하더라도 기존 코드를 수정/복사하지 않고, 정책만 추가하는 구조를 목표로 했다.
QuickFilterStrategy: 정책의 캡슐화
QuickFilterStrategy enum은 페이지 타입별 필터 노출 정책을 캡슐화하여 코드 전반에 흩어져 있던 정책 분기를 제거했다. 각 전략은 모텔, 비모텔, 게스트하우스 할인 필터 조건과 카테고리 필터 포함 여부를 명확히 정의한다. 이를 통해 페이지 타입별 정책의 집합이 enum 하나로 고정되어 정책 변경 시 수정 지점이 명확해지고, 새로운 페이지 타입 추가 역시 구조적으로 자연스럽게 이루어지도록 했다.
모텔 할인 필터 조건: motelFilter ->
비모텔 할인 필터 조건: nonMotelFilter ->
게스트하우스 전용 할인 필터 조건: guestHouseFilter ->
결과적으로, 정책 변경(Policy Change)에 유연하게 대응하고 코드의 가독성(Readability)을 향상시켰다.
Builder 패턴: 필터 생성 파이프라인 통합
QuickFilterStrategy는 필터를 직접 생성하지 않고, QuickFilterBuilder에 책임을 위임하여 필터 생성 흐름을 통일했다. 전략은 어떤 Predicate를 사용할지 결정하고, 카테고리 필터 포함 여부를 결정하는 역할만 수행한다. 필터 생성, Content 조립, 결과 리스트 구성은 Builder와 Mapper의 책임으로 남겨두어, 필터 생성 로직의 일관성을 유지했다.
Predicate 결정: 어떤 Predicate를 사용할지 결정
카테고리 필터 포함 여부 결정: includeCategory
Builder와 Mapper 책임: Anchor 생성, Content 조립, 결과 리스트 구성
이러한 구조는 새로운 필터 요구사항이 발생하더라도 기존 코드를 수정하지 않고, Predicate 조합만으로 정책을 표현할 수 있도록 한다.
개선된 구조의 장점과 트레이드오프
리팩토링 이후 구조는 페이지 타입과 카테고리 분리를 명확히 하고, 필터 생성 과정을 하나의 공통된 흐름으로 통합했다. 페이지 타입별 정책은 전략(enum + Predicate)으로, 카테고리 조합 처리는 Creator/Builder로, 필터 생성 흐름은 Builder 체인으로 고정했다. 이를 통해 페이지 타입이나 카테고리별 요구사항이 추가되더라도 생성 흐름 자체는 변경되지 않으며 정책 정의만으로 확장이 가능해졌다.
확장성 향상: 정책 정의만으로 확장 가능
유지보수성 개선: 정책 변경 용이
구조 복잡도 증가: 초기 진입 비용 증가
결과적으로, 확장성(Scalability)과 유지보수성(Maintainability)을 확보했지만, 설계 이해를 위한 초기 학습 비용이 증가했다.