[TIG] Index 를 활용한 최적화

JEONG KI MIN·2025년 1월 16일

TIG

목록 보기
12/12

최근에 스타트업 면접을 보고왔는데, 면접관 분께서 제안해주신 방법으로 티그 최적화를 진행해보았다.

기존 방식

기존의 티그 홈화면 로직은 다음과 같다.

  1. 사용자의 위치 정보를 수집한다.
  2. 위치 정보를 바탕으로 근처에 있는 업체를 계산한다. 이때, Haversine 방식으로 거리를 계산한다.
  3. 근처 업체 뿐만 아니라, 인기 있는 업체들을 조회해서 추천해준다.

2번 방식이 딱봐도 오버헤드가 큰 작업일 것 같지 않나요?
데이터의 개수는 수백개 정도이지만 거리를 계산해주고 근처에 있는 업체순으로 리턴해주는 과정이 시간이 꽤 걸린다.

여태까지 코드 상에서의 최적화는 몇번 진행했었고, 로직의 개선도 있었지만 인덱스를 도입해보지는 않았다. 따라서 시도해보고자 한다!

로컬 환경에서 테스트 코드로 인덱스를 추가하기 전과 추가한 뒤의 실행시간을 비교해보았다.

인덱스 추가 전

일단 테스트 코드는 간단하게 구성했다.

@Test
public void testOptimizedParallelFindNearestClubs() {
    float requestLat = 37.5665f;
    float requestLon = 126.9780f;

    // 실행 시간을 담을 리스트
    List<Long> executionTimes = new ArrayList<>();

    // 10번 반복 실행
    for (int i = 0; i < 10; i++) {
        long start = System.currentTimeMillis();
        HomeResponse clubs = clubService.getHomeClubs(requestLat, requestLon);
        long end = System.currentTimeMillis();

        long elapsed = end - start;
        executionTimes.add(elapsed);
    }

    // 전체 실행 시간 출력
    System.out.println("All execution times (ms): " + executionTimes);

    // 평균값 계산
    double average = executionTimes.stream()
            .mapToLong(Long::longValue)
            .average()
            .orElse(0.0);

    System.out.println("Average execution time (ms): " + average);
}

홈화면 조회를 담당하는 로직을 10번 실행하고 해당 평균값을 확인해보고자 했다.

인덱스를 추가하기 전의 결과는 다음과 같다!

로컬 환경에서 테스트 했기 때문에 기존보다 실행시간이 긴 것인지는 잘 모르겠지만 원래보다 오래걸렸다...

인덱스 추가

일단 사용자의 위치정보를 (latitude, longitude) 를 바탕으로 계산을 진행하고, Club 엔티티에서도 위도와 경도 데이터를 기반으로 계산을 진행하기 때문에 가장 많이 쓰이는 필드가 위,경도 라고 판단했다.

따라서 인덱스를 추가해주었다.

CREATE INDEX idx_club_lat_lon
ON club (latitude, longitude);

위와 같이 DDL을 직접 작성하여 인덱스를 생성할 수 있다. 이 방법 말도 JPA를 사용하는 방법도 있다.

@Entity
@Table(
    name = "club",
    indexes = {
        @Index(name = "idx_club_lat_lon", columnList = "latitude, longitude")
    }
)
public class Club { ... }

위와 같이 진행하면 JPA에 의해 데이터베이스에 인덱스가 생성된다.

아무튼 인덱스를 추가해주고 잘 생성되었는지 확인했다.

show index from club;


맨위에 조회된 인덱스는 PK에 대한 인덱스이다. MySQL 에서는 아무런 인덱스를 추가하지 않아도 기본키에 대한 인덱스는 디폴트로 설정해준다.

인덱스 추가 후

인덱스가 추가 되었으니 이제 위,경도에 대한 조회 로직은 기존보다 빨리 수행될 것이라 생각했다.
테스트 코드의 실행결과는 다음과 같다.

그래도 의미 있게 실행속도가 개선된것을 볼 수 있다.
동일 환경에서 기존에는 4212.9 ms 이었고 인덱스 적용 후에는 1957.2 ms 가 소요되었다.
이는 53.54% 가 개선된 결과이다.

추가적인 최적화?

코드를 수정하고 인덱스를 추가해보는 과정에서 service 단의 코드가 많이 복잡하고 불필요한 로직이 많은것이 보였다.
추후에는 이런 과정들을 최적화해야겠다고 생각했다.

profile
열심히 해볼게요

2개의 댓글

comment-user-thumbnail
2025년 1월 19일

비슷한 내용을 고민하고 있었는데 재미있네요

1개의 답글