사이드 프로젝트(6) - Match 정보 관리

김정훈·2024년 7월 23일
0

MatchList 간단 소개

회원의 최신 20경기 만을 관리합니다. 때문에 갱신할 때 MatchList를 항상 최신 경기로 update해야 합니다. 이 update 방식에 대한 고찰을 소개합니다.

delete + insert or update

delete + insert

기존 MatchList에서 update해야 할 index 범위를 찾고 delete한 후 새로운 Match들을 insert 한다.
장점 : 과정을 떠올리기 단순하고 query도 복잡하게 생각할 필요가 없다.
단점 : delete, insert query가 발생한다.

update

동일하게 index 범위를 찾은 다음 새로운 Match들로 update 한다. 교체될 객체의 id를 이용해 객체에 접근한 후 update 한다.
장점 : 성능이 좋다.
단점 : index에 순차적으로 접근하는 코드가 추가되며 update query이기 때문에 jpql이 다소 복잡하다.

update 선택

delte + insert는 쿼리가 두 배로 증가한다. 공부 프로젝트니까 성능을 위한 update 방식을 선택했다.

로직

우선 교체가 필요한 게임 수(새로운 게임 수 )를 계산한다.

 public int getCountNewMatch(String puuId, String summonerId) {
        String targetMatchId = getMatchService.getMatchIds(puuId, LOL.LastIndex, 1).get(0);
        List<Match> Match = matchService.findAllBySummonerId(summonerId);
        Integer gameCount = getGameCount(Match, targetMatchId);
        return Objects.requireNonNullElse(gameCount, LOL.gameCount);
    }
    private static @Nullable Integer getGameCount(List<Match> Match, String targetMatchId) {
        int result;
        if (!Match.isEmpty()) {
            result = IntStream.range(0, Match.size())
                    .filter(i -> targetMatchId.equals(Match.get(i).getMatchId()))
                    .findFirst()
                    .orElse(-1);  // 찾지 못한 경우 -1 반환
            if (result != -1) {
                return LOL.gameCount - (result + 1);
            }
        }
        return null;
    }

그 다음 교체할 범위의 첫 index를 찾고 개수만큼 반복하여 update 한다.

public void updateMatches(SummonerInfo summonerInfo, int newMatchCount, List<Match> newMatchList) {
        List<Match> originMatchList = summonerInfo.getMatchList(); // 기존 매치 리스트
        List<Match> updatedMatchList = new ArrayList<>(originMatchList); // 업데이트를 위한 새 리스트 생성

        // 새로운 매치 정보로 기존 리스트 업데이트
        int updateStartIndex = LOL.gameCount - newMatchCount; // 업데이트 시작할 인덱스
        for (int j = 0; j < newMatchCount; j++) {
            int updateIndex = updateStartIndex + j;
            Match newMatch = newMatchList.get(j);

            // 기존 매치 정보 업데이트 (in-place 업데이트로 리스트 크기 유지)
            updatedMatchList.set(updateIndex, newMatch);
            // 데이터베이스 업데이트 호출
            matchService.update(newMatch.getMatchId(), newMatch.getGameStartTimestamp(), newMatch.getKills(),
                    newMatch.getDeaths(), newMatch.getAssists(), newMatch.getKda(), newMatch.getChampionName(),
                    newMatch.getMainRune(), newMatch.getSubRune(), newMatch.getItemList(),
                    newMatch.getSummonerSpellList(), newMatch.getResult(),
                    originMatchList.get(updateIndex).getMatchId());
        }

        // 업데이트된 리스트로 소환사 정보 업데이트
        summonerInfo.updateMatchList(updatedMatchList);
    }

jpql

    @Modifying
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Query("update Match s SET " +
            "s.matchId = :matchId, " +
            "s.gameStartTimestamp = :gameStartTimestamp, " +
            "s.kills = :kills, " +
            "s.deaths = :deaths, " +
            "s.assists = :assists, " +
            "s.kda = :kda, " +
            "s.championName = :championName, " +
            "s.mainRune = :mainRune, " +
            "s.subRune = :subRune, " +
            "s.itemList = :itemList, " +
            "s.summonerSpellList = :summonerSpellList, " +
            "s.result = :result " +
            "WHERE s.matchId = :originMatchId")
    void update(@Param("matchId") String matchId,
                @Param("gameStartTimestamp") Long gameStartTimestamp,
                @Param("kills") Long kills,
                @Param("deaths") Long deaths,
                @Param("assists") Long assists,
                @Param("kda") String kda,
                @Param("championName") String championName,
                @Param("mainRune") Long mainRune,
                @Param("subRune") Long subRune,
                @Param("itemList") List<Integer> itemList,
                @Param("summonerSpellList") List<Integer> summonerSpellList,
                @Param("result") String result,
                @Param("originMatchId") String originMatchId);

구조는 단순하지만 업데이트 할 필드가 많아 망설였다. jpa의 save()를 쓰고 싶었는데 내 Match 엔티티의 id는 테이블을 관리하기 위한 DB의 id가 아니라 실제 Match의 id 정보라서 id 수정도 필요했기 때문에 어쩔 수 없이 직접 jpql을 작성했다.(id 예시 : KR65486546)

profile
백엔드 개발자

0개의 댓글