개발 일지/주간 개발 일지

[05월 1주차] 프론트엔드 에러 해결 및 querydsl -BooleanExpression을 활용한 리팩토링

계란💕 2023. 5. 6. 14:41

Note


BooleanBuilder => BooleanExpression 리팩토링

  • 기존에는 쿼리 클래스 안에 projection()이라는 메서드 안에 변수 BooleanBuilder search를 선언했다. 
  • 그 다음 쿼리의 where절에 넣고 싶은 조건을 search.and(조건) 형태로 여러 개 나열하는 방식이었다.  
  • 하지만, BooleanBuilder를 사용하면 predicate() 메서드가 길어져서 가독성이 떨어졌다. 그리고 해당 조건에 대해 재사용이 불가능하다는 단점이 있었다. 
  • 그래서 김영한 강사님께서 알려주신 BooleanExpression을 적용하기로 했다. 

 

 

 

  Ex) 검색 조건 쿼리 - BooleanBuilder 를 사용한 이전 코드 

<hide/>
public BooleanBuilder predicate(Member memberVO) {
    BooleanBuilder search = new BooleanBuilder();
    if (StringUtil.isNotEmpty(Member.getMemberId())) {
        search.and(member.memberId.containsIgnoreCase(Member.getMemberId()));
    }
    if (StringUtil.isNotEmpty(Member.getMembeNm())) {
        search.and(member.memberNm.containsIgnoreCase(Member.getMembeNm()));
    }
    return search;
}

public List<Member> getSearchedMemberList(Member memberVO) {
    return queryFactory
            .select(projection())
            .from(member)
            .where(predicate(Member)
            .fetch();
}
  • 위와 같이 "predicate()" 이라는 메서드가 꼭 필요하다. 
  • get 메서드의 return문을 보면 where 절 안에 predicate()이 들어가 있는데 predicate()라는 단어만 봤을 때는 어떤 조건인지 정확하게 파악하기 힘들다. 
  • 따라서, 각 조건에 대한 메서드를 분리하려고 한다. 

 

 

  Ex) 검색 조건 쿼리 - BooleanExpression 적용 후

<hide/>
private BooleanExpression eqMemberId(String memberId) {
    if (!StringUtil.isEmpty(memberId)) {
        return member.memberId.containsIgnoreCase(memberId);
    }
    return null;
}

private BooleanExpression eqMemberNm(String MemberNm) {
    if (!StringUtil.isEmpty(MemberNm)) {
        return member.MemberNm.containsIgnoreCase(MemberNm);
    }
    return null;
}

public List<Member> getSearchedMemberList(Member memberVO) {
    return queryFactory
            .select(projection())
            .from(member)
            .where(eqMemberId(memberVO.getMemberId()),
                   eqMemberNm(memberVO.getMemberNm()),
            )
            .fetchOne();
}

 

  • 위와 같이 WHERE 절  안에 여러 개의 조건을 메서드명으로 명확하게 구분해서 하나씩 넣을 수 있다. 
  • 그러면  predicate() 라는 메서드가 필요없어진다. 
  • 위에 예시는 MemberId, MemberNm 을 가지고 검색하는 메서드인데 해당 필드에 값을 넣지 않아도 검색되도록 해야하기 때문에 VO 에 값이 들어왔는지 아닌지 확인하는 if 문이 필요하다.

 

에러 해결


<hide/>
Already included file name 'c:/learning/LearningDetail.vue' differs from file name 'c:/LearningDetail.vue' only in casing.
  The file is in the program because:
    Imported via "@/components/ai/learning/LearningDetail.vue" from file 'c:/learning/LearningDetail.vue'
    Root file specified for compilation
    Root file specified for compilationVetur(1261)
  • 오류
  • 원인: 부모, 자식 컴포넌트에 import 문을 중복으로 선언했다. 
  • 해결

failed to resolve component

  • 오류: 학습 paramEdit 컴포넌트를 해결할 수 없다?
  • 원인: import문 없이 컴포넌트를 바로 사용했다.
  • 해결: import  추가

typeError

Uncaught (in promise) TypeError: data.includes is not a function
  • 오류: typeError
  • 원인: GET 요청의 결과로 받은 데이터를 담는데 오류가 있었다. 
  • 해결: 
    • axios의 http 요청으로 res 데이터를 받는다. 
    • res.data를 그대로 넣는게 아니라 res.data.list 같은 형태로 필요한 부분만 해당 컴포넌트의 변수 state의 list 안에 넣어준다.

property "(메서드명)" was accessed during render but is not defined on instance;

  • 오류 [Vue warn]: Property "getModelParamList" was accessed during render but is not defined on instance. 
  • 원인: ParamEdit 컴포넌트에서 watch() 부분이 잘못됐다.
  • 해결
    • 1)  tableData
      • 파람리스트 정보를 입력할 때마다 store에 커밋해준다. 
    • 2) getLearning: Learning 데이터에 변화가 생긴 경우, 콤보 박스에서 다른 modeld 를 선택한 경우가 이에 해당한다. 
      • LearningEdit 컴포넌트에서 store.set 한다. 
      • 그러면Learning 데이터가 바뀔 때마다 get()의 결과가 바뀔 것이다.
      • 바뀔 때마다 해당 내용을 LearningParamEdit 에서 store.get 해서 해당 내용의 바뀐 modelId를 읽어와서 이에 대한 파람리스트를 조회해준다. 

 

  • 오류
  • 원인
  • 해결: