트러블슈팅

인기 메뉴 조회 성능 개선 - 인덱스 도입

sudaruuu 2026. 4. 1. 16:31

 

2026.03.27 - [Spring 2기 과제] - 포인트 기반 커피 주문 결제 시스템 (도메인 설계)

 

포인트 기반 커피 주문 결제 시스템 (도메인 설계)

https://github.com/Banhklo2/coffee-order-system.git GitHub - Banhklo2/coffee-order-system: Spring Boot 기반 포인트 기반 커피 주문 결제 시스템Spring Boot 기반 포인트 기반 커피 주문 결제 시스템. Contribute to Banhklo2/coffee-o

sudaruuu.tistory.com

 

문제 상황

인기 메뉴 조회 기능을 구현하면서,

최근 7일 데이터를 기준으로 주문 정보를 조회하는 로직을 작성했다.

public List<PopularMenuResponse> getPopularMenus() {
    LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);
    return menuRepository.findPopularMenus(sevenDaysAgo, PageRequest.of(0, 3));
}

 

해당 로직은 내부적으로 다음과 같은 조건을 사용한다.

WHERE created_at >= NOW() - INTERVAL 7 DAY

 

하지만 이 경우, 데이터가 많아질수록

Order 테이블 전체를 탐색해야 하는 구조이기 때문에 성능 저하가 발생할 수 있다.


원인 분석

인덱스가 없는 상태에서는 DB가 조건을 만족하는 데이터를 찾기 위해

테이블 전체를 순회하는 풀 테이블 스캔(Full Table Scan)이 발생한다.

 

즉, 다음과 같은 비효율적인 방식으로 동작한다.

  • 모든 Order 데이터를 조회
  • created_at 조건을 하나씩 비교
  • 최근 7일 데이터 필터링

데이터가 많아질수록 조회 성능이 급격히 저하될 수 있다.


해결 방법

created_at 컬럼에 인덱스를 추가하여

최근 7일 데이터를 빠르게 조회할 수 있도록 개선했다.

@Entity
@Table(
        name = "orders",
        indexes = {
                @Index(name = "idx_order_created_at", columnList = "created_at")
        }
)
public class Order extends BaseEntity {
}

 

또한 BaseEntity의 컬럼명을 명시하여 DB 컬럼과의 일관성을 확보했다.

@CreatedDate
@Column(name = "created_at", updatable = false, nullable = false)
private LocalDateTime createdAt;

테스트 및 검증

1️⃣ EXPLAIN을 통한 실행 계획 확인

인덱스가 실제로 사용되는지 확인하기 위해 다음 쿼리를 실행하였다.

EXPLAIN
SELECT *
FROM orders
WHERE created_at >= NOW() - INTERVAL 7 DAY;

2️⃣ 실행 결과


3️⃣ 결과 분석

  • key: idx_order_created_at
    created_at 인덱스가 사용됨
  • type: range
    인덱스를 활용한 범위 조회 수행

즉, Order 테이블 전체를 조회하는 것이 아니라
인덱스를 기반으로 최근 7일 데이터만 효율적으로 탐색하도록 개선되었다.


개선 효과

  • 풀 테이블 스캔 → 인덱스 기반 조회로 변경
  • 조회 범위를 전체 데이터 → 최근 7일 데이터로 축소
  • 인기 메뉴 조회 성능 개선

핵심 개념 정리

인덱스 + 범위 조건 → range scan 발생

WHERE created_at >= ?

 

이와 같이 범위 조건이 있을 경우,

DB는 인덱스를 활용한 range scan 방식으로 데이터를 조회한다.


정리

  • created_at 컬럼에 인덱스를 추가하여 조회 성능을 개선하였다.
  • EXPLAIN을 통해 실제 인덱스 사용 여부를 확인하였다.
  • range scan을 통해 불필요한 전체 탐색을 줄일 수 있었다.

성능 개선 작업에서는
단순히 "인덱스를 추가했다"가 아니라
실제로 인덱스가 사용되는지 검증하는 과정이 중요하다는 것을 확인할 수 있었다.


느낀 점

인덱스를 단순히 추가하는 것에서 끝나는 것이 아니라,

실제로 실행 계획을 통해 인덱스가 사용되는지 검증하는 과정이 중요하다는 것을 이해하게 되었다.