ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 비동기 처리로 90% 이상의 성능 향상하기
    프로젝트 2024. 12. 3. 10:56

    서비스 개발을 하다 보면, 사용자에게 더 빠르고 효율적인 응답을 제공하는 것은 가장 중요한 과제 중 하나입니다. 이번 포스팅에서는 제가 진행한 HospitalInfoServiceMapService의 성능 최적화 사례를 공유합니다. 동기 처리 방식에서 발생하던 병목을 비동기 처리로 개선하여 전체 응답 시간을 약 26,846ms에서 2,679ms로 단축한 이야기를 다룹니다.

    1. 성능 저하의 원인 분석

    최적화 작업에 앞서 먼저 성능 저하의 원인을 분석했습니다. 기존 시스템에서는 Kakao API 호출을 포함한 여러 작업이 동기적으로 처리되고 있었습니다. 이러한 방식은 각 병원에 대한 지도 정보를 요청할 때 모든 요청이 차례로 진행되었고, 결과적으로 응답 시간이 매우 길어졌습니다. 특히 병원이 여러 개일 경우 각 API 호출이 직렬로 처리되어, 전체 응답 시간이 기하급수적으로 증가하였습니다.

    2. 주요 최적화 내용

    성능을 대폭 향상시키기 위해 아래와 같은 비동기 처리캐싱 전략을 도입하였습니다.

    2.1. 비동기 처리 도입 (CompletableFuture 활용)

    먼저, Kakao API 호출을 비동기 처리로 변경하였습니다. MapServicegetMapInfo 메서드를 비동기 메서드 (getMapInfoAsync)로 수정하여, 여러 병원의 지도 정보를 병렬로 요청할 수 있도록 구현했습니다. 이를 통해 각 호출이 독립적으로 이루어져 전체 응답 시간을 크게 줄일 수 있었습니다.

    아래는 변경된 코드 스니펫입니다:

    @Async("taskExecutor")
    @Transactional(readOnly = true)
    public CompletableFuture<MapInfoResponseDto> getMapInfoAsync(double originLat, double originLon, double destLat, double destLon) {
        try {
            MapInfoResponseDto result = getMapInfo(originLat, originLon, destLat, destLon);
            log.info("Fetched map info asynchronously for origin: {},{} and dest: {},{}", originLat, originLon, destLat, destLon);
            return CompletableFuture.completedFuture(result);
        } catch (Exception e) {
            log.error("Error fetching map info for origin: {},{} and dest: {},{}", originLat, originLon, destLat, destLon, e);
            return CompletableFuture.completedFuture(null);
        }
    }

    이 코드를 통해 HospitalInfoServicegetRangeAllHospital 메서드에서도 각 병원에 대한 지도 정보 요청을 비동기적으로 처리할 수 있게 되어, 실행 시간이 크게 개선되었습니다.

    2. 성능 개선 결과

    이번 최적화 작업을 통해 다음과 같은 놀라운 성능 향상을 이루었습니다:

    • 기존 실행 시간: 약 26,846ms
    • 최적화 후 실행 시간: 약 2,679ms
    • 개선 비율: 약 90% 이상의 성능 향상

    이렇게 비동기 처리와 캐싱 전략을 통해 전체 응답 시간을 대폭 줄여, 사용자 경험을 크게 개선할 수 있었습니다. 이 작업은 서비스의 가용성과 반응성을 높여주는 중요한 변곡점이 되었습니다.

    3. 결론 및 교훈

    이번 작업에서 중요한 교훈은 다음과 같습니다:

    1. 비동기 처리의 강력함: 많은 외부 API 호출이 필요한 서비스에서는 비동기 처리가 필수적입니다. CompletableFuture를 활용한 비동기 처리는 개발자가 다루기 쉽고, 효과적입니다.
    2. 병렬 처리와 캐싱의 조합: 병렬 처리와 적절한 캐싱 전략의 조합은 성능을 극대화할 수 있는 강력한 방법입니다.

    이 최적화 과정은 단순히 성능을 높이는 것을 넘어, 사용자가 더 만족할 수 있는 서비스를 제공하는 데 큰 도움이 되었습니다. 앞으로도 지속적인 성능 모니터링과 최적화를 통해 더욱 나은 사용자 경험을 제공하려 합니다.🚀

Designed by Tistory.