안녕하세요 이번 시간에는 리팩토링을 해보도록 하겠습니다.

전체 코드는 아래에서 보실 수 있습니다.

https://github.com/sug5806/board-project-rest

 

sug5806/board-project-rest

Contribute to sug5806/board-project-rest development by creating an account on GitHub.

github.com

 

기존에 QueryDSL을 사용하여 검색 유형(게시물 제목으로 검색, 유저 닉네임으로 검색)을 할때 if - else 구문을 통해 코드를 작성하였는데요 이렇게 될경우 코드가 지저분해짐과 동시에 코드를 수정할때 깜빡하고 까먹거나 철자 하나가 틀려 에러남에도 찾기 힘들어 질 수도 있습니다. 그래서 이것을 전략 패턴을 사용하여 바꿔보도록 하겠습니다.

코드 수정 : PostRepositoryImpl

생성 파일 :

  • 정렬 관련 (OrderTypeStrategy, OrderCreate, OrderPopular)
  • 검색 키워드관련 (SearchTypeStrategy, SearchTitle, SearchUser)

 

정렬 관련 코드

- OrderTypeStrategy

public interface OrderTypeStrategy {
    OrderSpecifier<?> getOrder();
}

- OrderCreate

@Component("create")
public class OrderCreate implements OrderTypeStrategy {
    @Override
    public OrderSpecifier<?> getOrder() {
        return post.date.createdAt.desc();
    }
}

- OrderPopular

@Component("popular")
public class OrderPopular implements OrderTypeStrategy {
    @Override
    public OrderSpecifier<?> getOrder() {
        return post.likeCount.desc();
    }
}

 

구현 클래스에 @Component("컴포넌트명") 을 붙여줘 스프링에서 자동으로 bean으로 등록하게끔 설정 해줍니다.

 

검색 키워드관련 코드 

- SearchTypeStrategy

public interface SearchTypeStrategy {
    BooleanExpression search(String query);
}

- SearchTitle

@Component("title")
public class SearchTitle implements SearchTypeStrategy {
    @Override
    public BooleanExpression search(String query) {
        return QPost.post.title.contains(query);
    }
}

- SearchUser

@Component("user")
public class SearchUser implements SearchTypeStrategy {
    @Override
    public BooleanExpression search(String query) {
        return QUser.user.nickname.eq(query);
    }
}

 

구현 클래스에 @Component("컴포넌트명") 을 붙여줘 스프링에서 자동으로 bean으로 등록하게끔 설정 해줍니다.

 

- PostRepositoryImpl

@RequiredArgsConstructor
public class PostRepositoryImpl implements PostRepositoryCustom {
    private final JPAQueryFactory jpaQueryFactory;
    private final Map<String, OrderTypeStrategy> orderTypeStrategyMap;
    private final Map<String, SearchTypeStrategy> searchTypeStrategyMap;
    
    
    ..............
    
        private BooleanExpression postSearchQuery(SearchDTO searchDTO) {
        SearchType searchType = SearchType.convertToType(searchDTO.getSearchType());

        if (Strings.hasText(searchDTO.getQuery())) {
            SearchTypeStrategy searchTypeStrategy = searchTypeStrategyMap.get(searchType.getType());

            return searchTypeStrategy.search(searchDTO.getQuery());
        }

        return null;

    }
    
    ............
    
        private OrderSpecifier<?> sortingCondition(Sort sort) {
        OrderSpecifier<?> orderBy = null;

        if (!sort.isEmpty()) {
            List<Sort.Order> orders = sort.toList();
            Sort.Order order = orders.get(0);
            OrderType orderType = OrderType.convertToType(order.getProperty());

            OrderTypeStrategy orderTypeStrategy = orderTypeStrategyMap.get(orderType.getType());

            orderBy = orderTypeStrategy.getOrder();
        }

        return orderBy;
    }
    
}

 

Map으로 선언하여 스프링에서 자동으로 아까 지정한 컴포넌트의 이름으로 인터페이스 타입을 구현한 클래스들을 주입시켜 줍니다.

그리하여 검색 타입에따라 SearchTitle, SearchUser를 사용하고 정렬 조건에따라 OrderPopular, OrderCreate를 사용하게됩니다.

+ Recent posts