Skip to content

perf: 공간 쿼리를 이용한 가게 검색 성능 최적화#32

Merged
min-0 merged 3 commits intodevelopfrom
perf/spatial-search-optimization
Oct 13, 2025
Merged

perf: 공간 쿼리를 이용한 가게 검색 성능 최적화#32
min-0 merged 3 commits intodevelopfrom
perf/spatial-search-optimization

Conversation

@min-0
Copy link
Copy Markdown
Member

@min-0 min-0 commented Oct 13, 2025

📝 작업 내용

  • 기존 위도, 경도 컬럼으로 위치 검색 대신 공간 데이터를 추가하여 가게 검색 최적화

⚡ 주요 변경사항

  • Hibernate Spatial, JTS 라이브러리 의존성을 추가하여 공간 데이터 처리 기능을 도입
  • Store 엔티티의 위도, 경도 필드를 Point 타입으로 변경하여 공간 인덱스를 활용할 수 있도록 개선
  • Native Query를 사용하여 특정 영역 내 가게를 효율적으로 검색
  • 거리 계산 및 위치 필터링 로직을 DB의 공간 쿼리를 사용하도록 변경

📌 리뷰 포인트

📋 체크리스트

  • ✍ PR 제목 규칙을 맞췄나요? (예: feat: 기능1 추가)
  • 📝 관련 이슈를 등록했나요?
  • ✅ 모든 테스트가 통과했나요?
  • 🏗 빌드가 정상적으로 완료되었나요?

Summary by CodeRabbit

  • New Features
    • 지도 영역 내 가게와 메뉴를 한 번에 검색하고, 카테고리·메뉴명·지정 사각형 경계로 필터링합니다.
    • 사용자 위치 기준 거리 정보를 제공하며, 결과에 최저가 메뉴와 가격, 주소, 이미지가 포함됩니다.
  • Performance
    • 단일 데이터베이스 조회로 검색 속도와 응답 일관성이 개선되었습니다.
  • Refactor
    • 위치 정보를 단일 위치 필드로 통합해 거리 계산과 거리/가격 정렬의 정확도를 높였습니다.

min-0 added 3 commits October 14, 2025 00:20
- Hibernate Spatial, JTS 라이브러리 의존성을 추가하여 공간 데이터 처리 기능을 도입
- Store 엔티티의 위도, 경도 필드를 Point 타입으로 변경하여 공간 인덱스를 활용할 수 있도록 개선
- 기존에 애플리케이션 레벨에서 처리하던 거리 계산 및 위치 필터링 로직을 DB의 공간 쿼리를 사용하도록 변경하여 검색 성능을 최적화
- Native Query를 사용하여 특정 영역 내 가게를 효율적으로 검색
- 변경된 Repository 메소드를 사용하도록 StoreService의 `searchStores` 로직을 리팩토링
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 13, 2025

Walkthrough

런타임 의존성에 공간 기능(JTS, Hibernate Spatial)을 추가하고, Store 엔티티의 위도/경도 필드를 JTS Point로 교체했습니다. 저장소에 네이티브 공간 쿼리와 프로젝션을 도입해 서비스 로직을 DB 단일 호출로 재구성했으며, 거리/좌표 계산은 Point 기반으로 전환되었습니다.

Changes

Cohort / File(s) Summary
Build & Dependencies
build.gradle.kts
런타임 의존성 추가: org.hibernate.orm:hibernate-spatial, org.locationtech.jts:jts-core
Domain Entity: Store
src/main/kotlin/.../entity/Store.kt
테이블 매핑 변경: storestore_backup; latitude/longitude 제거, Point 타입 location(POINT SRID 4326, not null) 추가; JTS Point import
Repository & Projection
src/main/kotlin/.../repository/StoreRepository.kt
프로젝션 StoreSearchResult 추가; 네이티브 쿼리 findStoresAndMenusInArea(...) 도입(공간 필터 MBRContains/ ST_GeomFromText, 거리/메뉴/가격 등 선택); @Query, @Param import
Service: Search & Details Flow
src/main/kotlin/.../service/StoreService.kt
다단계 인메모리 필터링 제거 → 저장소 네이티브 쿼리 단일 호출로 대체; 결과 프로젝션 기반 DTO 구성 및 정렬(가격/거리); 거리 및 좌표 매핑을 store.location.x/y 사용으로 변경

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Client
  participant StoreService as StoreService
  participant StoreRepository as StoreRepository
  participant DB as Database (SQL + Spatial)

  Client->>StoreService: searchStores(category, menuName, bounds, userLatLng, sort)
  StoreService->>StoreRepository: findStoresAndMenusInArea(userLng, userLat, category, menuName, SW/NE)
  StoreRepository->>DB: Native SQL (MBRContains + ST_GeomFromText, distance calc)
  DB-->>StoreRepository: List<StoreSearchResult>
  StoreRepository-->>StoreService: 결과 반환
  StoreService->>StoreService: DTO 매핑 및 정렬(가격/거리)
  StoreService-->>Client: StoreSearchDto 리스트

  Note over StoreRepository,DB: 변경: 공간 인덱스/함수 활용한 단일 쿼리로 필터·최저가 선택·거리 계산 수행
Loading
sequenceDiagram
  autonumber
  participant Client as Client
  participant StoreService as StoreService
  participant DB as Database

  Client->>StoreService: getStoreDetails(storeId, userLatLng)
  StoreService->>DB: 조회 Store + 관련 데이터
  DB-->>StoreService: Store(entity with Point location)
  StoreService->>StoreService: distance = haversine(location.x, location.y, userLng, userLat)
  StoreService-->>Client: StoreDetailDto(위도=location.y, 경도=location.x, distance)
  
  Note over StoreService: 변경: 위도/경도 필드 → Point.x/.y 사용
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목은 “perf: 공간 쿼리를 이용한 가게 검색 성능 최적화”로 주요 변경 사항인 공간 쿼리를 활용한 검색 성능 개선을 명확히 요약하며 간결하고 구체적입니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch perf/spatial-search-optimization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/kotlin/com/eodigo/domain/restaurant/service/StoreService.kt (1)

90-106: 거리 계산 시 위도/경도 순서가 뒤바뀌었습니다.

Pointx는 경도, y는 위도입니다. 현재 calculateDistance 호출에서 lat2location.x(경도), lon2location.y(위도)를 전달하고 있어 계산이 완전히 틀어집니다. lat2 = store.location.y, lon2 = store.location.x로 교체해야 올바른 거리가 나옵니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfacd72 and dfef578.

📒 Files selected for processing (4)
  • build.gradle.kts (1 hunks)
  • src/main/kotlin/com/eodigo/domain/restaurant/entity/Store.kt (1 hunks)
  • src/main/kotlin/com/eodigo/domain/restaurant/repository/StoreRepository.kt (1 hunks)
  • src/main/kotlin/com/eodigo/domain/restaurant/service/StoreService.kt (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.kt

⚙️ CodeRabbit configuration file

src/**/*.kt: ## 1. Kotlin 코딩 컨벤션

  • Kotlin 공식 코딩 컨벤션을 준수해야 합니다.
  • 클래스는 PascalCase, 함수/변수는 camelCase, 상수는 UPPER_SNAKE_CASE로 작성하세요.
  • 변경 불가능한 데이터는 val을, 변경이 필요한 경우에만 var를 사용하세요.
  • Null Pointer Exception을 유발하는 !! 연산자 사용을 금지합니다.
  • 의미를 알 수 없는 숫자나 문자열(매직 넘버) 대신 명명된 상수를 사용하세요.

2. Spring Boot

  • Controller-Service-Repository 계층형 아키텍처의 책임을 분리하세요.
  • Controller의 요청/응답에는 반드시 DTO를 사용하고, 엔티티를 직접 노출하지 마세요.
  • 민감한 설정 정보(DB 계정, API 키 등)는 코드에 하드코딩하지 말고 외부에서 주입하세요.
  • @Autowired 필드 주입 대신 생성자 주입을 사용하세요.

3. JPA 및 데이터베이스

  • @entity 클래스에 Setter 사용을 지양하고, 비즈니스 메서드를 통해 상태를 변경하세요.
  • 데이터를 변경하지 않는 조회용 Service 메서드에는 @transactional(readOnly = true)를 적용하세요.
  • N+1 문제가 발생하는 쿼리가 있는지 확인하고, Fetch Join으로 최적화하세요.
  • 엔티티의 양방향 연관관계에서 toString()을 사용할 경우 순환 참조가 발생하지 않도록 주의하세요.

4. 예외 처리

  • @RestControllerAdvice를 사용하여 예외를 전역에서 일관되게 처리하세요.
  • RuntimeException 대신, 의미가 명확한 커스텀 예외(예: MemberNotFoundException)를 정의하여 사용하세요.

Files:

  • src/main/kotlin/com/eodigo/domain/restaurant/entity/Store.kt
  • src/main/kotlin/com/eodigo/domain/restaurant/service/StoreService.kt
  • src/main/kotlin/com/eodigo/domain/restaurant/repository/StoreRepository.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test

Comment thread build.gradle.kts
@min-0 min-0 merged commit a624f51 into develop Oct 13, 2025
2 checks passed
@min-0 min-0 deleted the perf/spatial-search-optimization branch October 13, 2025 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant