티스토리 뷰

728x90

사이드프로젝트를 하면서 검색조건에 따른 검색 쿼리를 개발하였다.

검색쿼리를 개발하는 데에 있어서 다양한 방법이 있었지만

나의 경우는

 

jpql보단 Querydsl 를 활용하였고,

Where조건보단 BooleanBuilder를 활용하여 보다 관리하기 편하도록 했고,

DTO에 전달할 값을 명시하여, API통신할 때 전달 데이터를 정의하였다. 

 

위의 방법에 따라 작성한 글이다. 

 

 

 

🚨 들어가기에 앞서...  | Querydsl, DTO,  BooleanBuilder를 사용한 이유


JPQL이 아닌 Querydsl를 사용한 이유

Querydsl은 JPQL 빌더이다.

솔직히 아무거나 사용해도 상관없는데 실제로 회사에서 일해보니까 Querydsl이 코드 지향적이라 관리하기 편했다

JPQL 같은 경우는 코드가 커질 경우 JPA, Spring Data Jpa, Querydsl 등 섞이니까 혼잡해지더라...

그래서 최대한 JPQL은 사용하지 않고, Querydsl를 사용했고, 간단한 쿼리는 Spring Data Jpa를 활용하려 했다.

또한 JPQL은 파라미터 바인딩 직접해야하고, Querydsl은 파라미터 바인딩 자동 처리해 주는 이점도 있다.

Querydsl에서 제공해주는 메서드들도 유용하니 Querydsl를 사용한 적이 없다면 오늘 포스팅을 집중해서 봐 보도록 하자.

 

리턴 값으로  엔티티가 아닌 DTO를 사용한 이유

리턴값으로 엔티티를 넘겨주어도 되지만 나같은 경우는

Team에서 팀이름, 한줄 소개, 팀 고유번호, 팀원 수를 

Member에서 팀장 이름을 넘겨줘야 했다.

그래서 DTO를 만들어 정의했다. 

 

검색 조건으로 where이 아닌 BooleanBuilder를 사용한 이유

동적 쿼리를 해결하는 두 가지 방법이 존재한다.

다중 검색조건으로 where를 사용한 적도 있었고 BooleanBuilder를 사용한 적도 있었다.

결과적으로 말하자면 사용 방식에 차이에 따른 관리에 초점을 두었는데 

where를 사용하게 되면 익숙하고 쉽지만, 아래와 같이 코드 블록 밖으로 메서드들이 생겨나게 되고

코드가 많아질 경우 관리가 어려워졌다. 

 

아래 코드를 보고 한 파일안에 where를 30번 사용한다고 상상해 보라...

 

where의 사용

그래서 하나의 코드 블록 안에서 사용할 수 있는 BooleanBuilder를 활용하여

파일 안에 코드가  많아지더라도 한눈에 알아볼 수 있는 이점이 있는 

BooleanBuilder를 사용하였다.

 

BooleanBuilder의 사용

 

나 같은 경우는 BooleanBuilder가 훨씬 편했다.

 

 

⭐️ 팀 검색 API 개발하기


Controller

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/team")
public class TeamController {

    private final TeamService teamService;
    private final MemberService memberService;

@ApiOperation(value = "find", notes = "팀 찾기")
@PostMapping("/find")
public CommonResponse<?> joinTeam(@RequestBody TeamSearchCond condition) {
    List<TeamSearchParam> findTeam = teamService.findTeam(condition);
    return CommonResponse.createSuccess(findTeam);
	}
}

팀 찾기 하는 로직의 일부이다. 검색 결과를 찾으면 CommonResponse로 값을 담아 데이터와 메시지를 전달한다.

 

컨트롤러에서는 TeamSearchCond라는 팀 찾기 검색조건을 정의해 둔 DTO를 만들어두었다.

 

컨트롤러에서는 데이터를 받고, 넘겨주는 행위밖에 하지 않는다. 

 

검색조건에서는 Service의 역할이 중요하지 않으므로 

 

Controller DTO, Repository 위주로 다뤄보겠다.

 

DTO(검색  조건  데이터)

@Data
public class TeamSearchCond {
    //검색조건으로 넘어오는 데이터
    private String teamName;
    private Integer teamSerialNo;
}

DTO(검색 결과를 반환할 데이터)

@Getter
@ToString
public class TeamSearchParam {
    // 검색조건 결과 반환 데이터
    private String teamName;
    private String oneIntro;
    private Integer teamSerialNo;
    private String name;
    private int memberCount;


    @QueryProjection
    public TeamSearchParam(String teamName, String oneIntro, Integer teamSerialNo, String name, int memberCount) {
        this.teamName = teamName;
        this.oneIntro = oneIntro;
        this.teamSerialNo = teamSerialNo;
        this.name = name;
        this.memberCount = memberCount;
    }
}

 

나 같은 경우는 DTO를 분리하였다. 

 

Repository(Querydsl)

@Repository
@RequiredArgsConstructor
public class TeamCustomImpl{
    private final JPAQueryFactory queryFactory;

    public List<TeamSearchParam> getInfoBySerialNoOrTeamName(TeamSearchCond condition) {
        BooleanBuilder builder = new BooleanBuilder();

        if (StringUtils.hasText(condition.getTeamName())) {
            builder.and(team.teamName.eq(condition.getTeamName()));
        }

        if (condition.getTeamSerialNo() != null) {
            builder.and(team.teamSerialNo.eq(condition.getTeamSerialNo()));
        }



        return queryFactory
                .select(new QTeamSearchParam(team.teamName, team.oneIntro, team.teamSerialNo, member.name, team.MemberCount))
                .from(teamMemberInfo)
                .leftJoin(teamMemberInfo.team, team)
                .leftJoin(teamMemberInfo.member, member)
                .on(teamMemberInfo.authority.eq(AuthorityStatus.valueOf("LEADER")))
                .where(builder)
                .fetch();
    }

}

결과의 리턴값이 TeamSerachParam이라는 것 

DTO에서 @QueryProjection을 통해 Q파일을 만들어주었고 new QTeamSearchParam를 통해 select값을 정의해준다.

team과 member가 연관관계 매핑되어 있는 teamMemberInfo를 통해 join을 걸고 

LEADER인 경우만 데이터를 가져온다.

⭐️ 팀 생성 및 검색 API 실행

swagger 테스트

# 프런트에서 teamName을 검색 조건을 전달받는다.

# 팀이름에 대한 결과

 

 

# 프런트에서 팀 고유번호를 검색 조건으로 전달받는다.

teamSerialNo: 5409

# 고유코드에 대한 결과

 

 

728x90
댓글
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday