Spring/프로젝트 코드 리뷰

Spring 클론코딩 프로젝트 콘텐츠 DetailPage( 비슷한 장르의 작품 추천)

code2772 2023. 3. 6. 09:06
728x90
반응형

🎬 MovieRespose - Containing 이용하여 유사 장르 뽑기

List<Movie> findByMovGenreContaining(String genre);

🎬 MovieService

@Transactional(readOnly = true)
public List<MovieResponse> similarGenre(String genre, Long movieIdx){
    List<MovieResponse> result = new ArrayList<>();

    List<Long> movieIdxList = new ArrayList<>(16);
    if(genre.contains("/")){
        List<String> genreList = Arrays.stream(genre.split("/")).toList();
        HashMap<Long, Integer> containMovie = new HashMap<>();
        for(String idx: genreList){
            for(Movie mov: movieRepository.findByMovGenreContaining(idx)){
                containMovie.put(mov.getMovIdx(),
                        containMovie.get(mov.getMovIdx()) != null ?
                                containMovie.get(mov.getMovIdx()) + 1 : 1
                );
            }
        }
        List<Map.Entry<Long, Integer>> entryList = new LinkedList<>(containMovie.entrySet());
        entryList.sort(((o1, o2) -> o2.getValue() - o1.getValue()));
        for(Map.Entry<Long, Integer> entry : entryList){
            movieIdxList.add(entry.getKey());
        }
    }else{
        for(Movie idx: movieRepository.findByMovGenreContaining(genre)){
            movieIdxList.add(idx.getMovIdx());
        }
    }

    for(Long idx: movieIdxList){
        if(idx == movieIdx) continue;
        MovieDto dto = MovieDto.from(movieRepository.getReferenceById(idx));
        double sum = 0;

        if(dto.starList().size() > 0){
            for(Star star: dto.starList()){
                sum += star.getStarPoint();
            }
            result.add(MovieResponse.of(dto.movIdx(), dto.movThumbnail(),dto.movTitle(),dto.movWatch(),Math.round((sum / dto.starList().size()) * 10.0) / 10.0));
        }else{
            result.add(MovieResponse.of(dto.movIdx(), dto.movThumbnail(),dto.movTitle(),dto.movWatch(),0.0));
        }
    }
    return result;
}

장르가 예를들어 액션/가족/코미디 와 같이 데이터베이스에 크롤링간 들어가있다. 그렇기 때문에 해당 장르와 유사한 장르를 구별하기 위해 

List<String> genreList = Arrays.stream(genre.split("/")).toList();

split을 해주어 genreList를 만들어 두었다. 그렇게 for문을 이용하여 반복을 돌려 기존에 만들어 준 Containing을 이용하여 장르가 겹치는 콘텐츠를 유사한 콘텐츠로 만들기
 
🎬 MovieController 에서 이제 서비스에서 만들었던 similarGenre를 기입해준다.

//        비슷한 장르 영화
        List<MovieResponse> similarGenre = movieService.similarGenre(movie.genre(), movie.idx());

 
🎬 타임리프 출력 코드

 <!--    비슷한 작품 -->
    <attr sel="section[data-rowindex='13']" th:if="${similarGenre.size()} > 0">
        <attr sel="ul.css-27z1qm-VisualUl-ContentGrid" th:remove="all-but-first">
            <attr sel="li.css-1hp6p72" th:each="mov : ${similarGenre}">
                <attr sel="a" th:title="mov.title" th:href="'/movie/' + ${mov.idx}"/>
                <attr sel="img.css-qhzw1o-StyledImg" th:src="${mov.thumbnail}"/>

                <attr sel="div.css-1qmeemv">
                    <!--                넷플릭스 아이콘-->
                    <attr sel="div.css-5o7sb2" th:if="${mov.watch} != null and ${#strings.contains(mov.watch,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b')}"/>
                    <!--                왓챠 아이콘 -->
                    <attr sel="div.css-oobk33" th:if="${mov.watch} != null and ${#strings.contains(mov.watch,'aHR0cHM6Ly93YXRjaGEuY29tL3dhd')}"/>
                </attr>
                <attr sel="div.css-ixy093">
                    <attr sel="div.css-niy0za" th:text="${mov.title}"/>
                    <attr sel="div.css-m9i0qw" th:if="${mov.avgStar} != 0.0" th:text="'평균 ★ ' + (${mov.avgStar} != 0 ? ${mov.avgStar} : _)"/>
                </attr>
            </attr>
        </attr>
    </attr>
</thlogic>

🎬 해당 콘텐츠와 비슷한 작품 추천 화면

반응형