안녕하세요 이번 시간에는 리팩토링을 해보도록 하겠습니다.
전체 코드는 아래에서 보실 수 있습니다.
https://github.com/sug5806/board-project-rest
기존에 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를 사용하게됩니다.
'스프링 부트' 카테고리의 다른 글
@Bean과 @Component의 차이점 (0) | 2021.05.13 |
---|---|
스프링부트 게시판 API 만들기 - 끝 (AWS S3에 이미지 업로드 하기) (0) | 2021.05.05 |
스프링부트 게시판 API 만들기 - 13 게시물 좋아요 기능 만들기 (1) | 2021.05.04 |
스프링부트 게시판 API 만들기 - 12 (게시물 검색기능 및 QueryDSL) - 2 (0) | 2021.05.03 |
스프링부트 게시판 API 만들기 - 11 (게시물 검색기능 및 QueryDSL) - 1 (0) | 2021.05.01 |