기록창고

CompletableFuture 을 이용한 비동기 요청 본문

JAVA

CompletableFuture 을 이용한 비동기 요청

방금시작한사람 2020. 6. 9. 15:48

Spring boot 개인 프로젝트 할 때, 다른 사이트의 API 를 요청해야 할 필요가 있었습니다.

 

레인보우식스 라는 게임의 Rank 정보를 가져와야 하는데 

region와 season을 파라미터로 가지고 있고, region 은 3개, season 1 ~ 17(현재시즌) 까지 조회를 하여

플레이어의 전체 시즌정보를 가져와야했습니다.

 

하나씩 for 문으로 돌리니 51개의 요청이 생성되고, 응답이 올때까지 기다려야 다음 포문을 실행하기 때문에

응답시간이 되게 오래걸렸습니다

 

for(int season = 1; season <= currentSeason; season++) {
    RankStatDto rankstatDto = ubiApi.getRankStat(platform, id, region, season);
    if(rankstatDto.getMaxMmr() == 0 && season != currentSeason) {
        continue; // 현재 시즌은 저장하지만, 이전 시즌이 플레이를 안한 경우는 무시
    }

    RankStat rankStat = new RankStat(rankstatDto, player);
    rankRepository.save(rankStat);
    player.getRankList().add(rankStat);
}

 

그래서 요청을 한번에 다 보내고, 모든 요청이 끝나면 종합하는 방식으로 바꿨습니다.

 

List<CompletableFuture<RankStatDto>> completableFutureList = new ArrayList<>();
for(int season = 1; season <= currentSeason; season++) {
    int finalSeason = season;
    completableFutureList.add(CompletableFuture.supplyAsync(() -> {
        return ubiApi.getRankStat(platform, id, region, finalSeason);
    }));
}

CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[completableFutureList.size()])).join();
List<RankStatDto> dtoList = completableFutureList.stream().map(CompletableFuture::join).collect(Collectors.toList());

for(RankStatDto dto : dtoList) {
    if(dto.getMaxMmr() == 0 && dto.getSeason() != currentSeason) {
        // 현재 시즌에 플레이 하지 않더라도 DB 에 저장해놔서, 이 메소드가 검색할 때 마다 호출되는 것을 막음
        continue;
    }
    RankStat rankStat = new RankStat(dto, player);
    rankRepository.save(rankStat);
    player.getRankList().add(rankStat);
}

 

한 지역별 시즌을 한번에 요청하는 코드입니다.

supplyAsync 함수를 이용하여 api 호출 결과를 가져옵니다. 

 

allOf 는 List를 받지 않으므로, 배열로 만들어 준다. 그리고 join 을 이용해 모든 비동기처리가 다 되길 기다리고 있습니다.

 

allOf 의 리턴 Void 이기 때문에, 따로 리턴값을 가지고 있지 않고, List 에 넣어놨던 비동처리가 모든 끝났기 때문에,

자바 스트림을 이용해 결과값을 가져와서 리스트로 만들어준 후, 그 이후 작업을 합니다..

 

- 비동기처리안에 DB 에 저장하는 코드도 넣을까 생각중입니다..

 

 

한번에 요청을 보내니, 약 2초정도가 걸리는데, 기존 20초 이상에서 굉장히 단축된 효과를 볼 수 있었습니다

 

 

 

'JAVA' 카테고리의 다른 글

@Lombok 생성자가 2개에 builder 적용하기  (0) 2020.06.26
Java Stream api 를 이용한 파싱  (0) 2020.06.18
기본형과 래퍼 클래스(Wrapper Class)  (0) 2020.02.18
String.equals()  (0) 2020.01.19
Collectors GroupingBy  (0) 2020.01.16
Comments