Spring/프로젝트 코드 리뷰

Spring WatchaPedia 클론코딩 프로젝트 취향 분석(선호 배우, 국가, 장르, 감상 시간)

code2772 2023. 3. 8. 01:30
728x90
반응형

🎬 선호배우 분석 Service

public List<Map.Entry<String, String>> peopleCnt(Long userIdx){
    Map<Long, Integer> peopleMap = new HashMap<>();
    List<Long> movIdxs = starRepository.findStarMovie(userIdx);
    List<String> peopleList = List.of(movieRepository.findPeopleList(movIdxs).toString()
            .split("\\[")[1].split("]")[0].split(", "));
    for(String str: peopleList){
        String[] personList = str.split(",");
        for(String per : personList){
            if(per.contains("주연")){
                Long personIdx = 0L;
                try {
                    if (per.contains("(")) {
                        personIdx = Long.valueOf(per.split("\\(")[0]);
                    } else personIdx = Long.valueOf(per);

                    if (peopleMap.get(personIdx) != null) {
                        peopleMap.put(personIdx, 1 + peopleMap.get(personIdx));
                    } else {
                        peopleMap.put(personIdx, 1);
                    }
                }catch(NumberFormatException e){}
            }
        }
    }
    List<Map.Entry<Long, Integer>> entryList = new LinkedList<>(peopleMap.entrySet());
    entryList.sort(((o1, o2) -> o2.getValue() - o1.getValue()));

    Pageable pageable = PageRequest.of(0, 1);
    Map<String, String> resultMap = new HashMap<String, String>();
    for(int i=0; i<=5; i++){
        try{
            Person person = personRepository.findById(entryList.get(i).getKey()).get();
            resultMap.put((person.getPerPhoto()!=null?person.getPerPhoto()+"|":"")+person.getPerName()+","+person.getPerIdx()
                    ,entryList.get(i).getValue()+","+movieRepository.actorMovie("%,"+person.getPerIdx()+"(주연%",pageable).get(0));
        }catch (IndexOutOfBoundsException e){
            System.out.println("인물 부족");
        }
    }
    List<Map.Entry<String, String>> result = new LinkedList<>(resultMap.entrySet());
    result.sort(((o1, o2) -> Integer.parseInt(o2.getValue().split(",")[0]) - Integer.parseInt(o1.getValue().split(",")[0])));
    return result;
}

사용자가 감상한 또는 평가한 tb_star 테이블의 idx를 찾는다. 이 후 이 tb_star의 idx와 콘텐츠 idx의 연관성을 찾아들어가 해당 콘텐츠의 출연/제작, 국가, 장르, 런닝타임 등을 뽑아와 카운트를 하여 나의 취향을 분석하는 부분이다.
 
🎬 콘텐츠(영화) Repository

@Query(value = "SELECT movCountry, COUNT(movCountry) FROM tbMovie WHERE movIdx in :idxs GROUP BY movCountry HAVING COUNT(movCountry) > 0")
List<String> findCountryCnt(@Param("idxs") List<Long> idxs);
@Query(value = "SELECT movGenre, COUNT(movGenre) FROM tbMovie WHERE movIdx in :idxs GROUP BY movGenre HAVING COUNT(movGenre) > 0")
List<String> findGenreCnt(@Param("idxs") List<Long> idxs);
@Query(value = "SELECT movPeople FROM tbMovie WHERE movIdx in :idxs")
List<String> findPeopleList(@Param("idxs") List<Long> idxs);
@Query(value = "SELECT movTime FROM tbMovie WHERE movIdx in :idxs")
List<String> timeList(@Param("idxs") List<Long> idxs);
@Query(value = "SELECT movTitle FROM tbMovie WHERE movPeople LIKE :idx ORDER BY movIdx DESC")
List<String> actorMovie(@Param("idx") String idx, Pageable pageable);

@Query는 domain model이 아닌 Repository안에있는 메서드에 위치, 테이블이 아닌 엔티티 객체를 대상으로 검색하는 객체지향 쿼리, SQL 추상화로 인해 특정 db sql 에 의존하지 않음. @Param 을 통해 매개변수로 넘어온 값을 JPQL에 들어갈 변수로 지정한다. 더 복잡한 SQL 문을 스프링에서 사용하기 위해 Query 엔티티를 사용하였다.
 
🎬 선호배우 타임리프

<ul class="css-1m9zbc5-VisualUl" th:remove="all-but-first">
  <li class="css-wj6fn0" th:each="person : ${actorMap}">
    <a th:title="${#strings.contains(person.getKey(), '|')}?
      (${#strings.arraySplit((#strings.arraySplit(person.getKey(),',')[0]),'|')[1]})
      :${#strings.arraySplit(person.getKey(),',')[0]}" class="css-1aaqvgs-InnerPartOfListWithImage"
      th:href="'/personDetail/'+${#strings.arraySplit(person.getKey(),',')[1]}">
      <div class="css-cssveg">
        <div class="css-13zlig9">
          <div class="css-1q751em-ProfilePhotoImage"
              th:styleappend="'background:url('+${#strings.arraySplit(person.getKey(),'|')[0]}+') no-repeat center;repeat center; background-size: cover;'"></div>
        </div>
      </div>
      <div class="css-zoy7di">
        <div class="css-qkf9j">
          <div class="css-17vuhtq">
            <div class="css-1pfpne2-PersonTitle e72a1w70"><span
                class="css-1neatfa-PersonName e72a1w71" th:text="${#strings.contains(person.getKey(), '|')}?
                (${#strings.arraySplit((#strings.arraySplit(person.getKey(),',')[0]),'|')[1]})
                :${#strings.arraySplit(person.getKey(),',')[0]}">김태리</span><span
                class="css-104v25a-PersonDetail e72a1w72" th:text="${#strings.arraySplit(person.getValue(),',')[0]}+'편'">100점 • 3편</span></div>
          </div>
          <div class="css-1evnpxk-StyledSubtitle" th:text="${#strings.arraySplit(person.getValue(),',')[1]}">리틀 포레스트</div>
        </div>
        <div></div>
      </div>
    </a></li>

1. 선호 배우는 먼저 HTML 내에 타임리프를 적용하였다. all-but-first와  th:each를 사용하여 리스트의 첫 번째 부분을 반복하였다.
2. 이전 디테일 페이지와 유사하게 먼저 DB에 있는 인물의 정보를 나누기 위해 split을 이용하여 나눠 인물들을 출력시켰다. 
3. 선호배우와 유사하게 선호국가, 장르, 감상시간 모두 유사하게 추출하였다.
 
 
🎬 선호배우 웹페이지 출력화면 

🎬 선호국가, 선호장르 웹페이지 출력화면 

🎬 감상 시간 웹페이지 출력화면 

 

반응형