-
Notifications
You must be signed in to change notification settings - Fork 1
[feat] 지도에서 경사로, 엘리베이터를 거리순으로 조회하는 로직 구현 #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough지도 시설 검색 기능을 추가했다. 엘라스틱서치 문서/리포지토리/쿼리 리포지토리/서비스/컨트롤러를 신규 도입하고, 위경도+유형 조건으로 가까운 시설을 조회하는 GET API를 제공한다. DTO·엔티티·열거형을 추가했으며, 통합 테스트로 램프/엘리베이터 조회 및 정렬을 검증했다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as FacilitySearchController
participant Service as FacilityDocumentService
participant Repo as FacilityQuerySearchRepository
participant ES as Elasticsearch
Client->>Controller: GET /api/v1/facilities/search?lat,lon,facilityType
Controller->>Service: findNearbyFacilityDocuments(conditionDto)
Service->>Repo: findNearbyFacilitiesByType(condition)
Repo->>ES: Geo-distance query + type filter, sort by distance
ES-->>Repo: Documents
Repo-->>Service: List<WaybleFacilityResponseDto>
Service-->>Controller: List<WaybleFacilityResponseDto>
Controller-->>Client: CommonResponse.success(data)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 없음) Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (16)
src/main/java/com/wayble/server/explore/entity/FacilityType.java (1)
3-6: 도메인 중복 가능성: 기존 Type enum과의 관계 정리 제안direction.entity.type.Type에도 RAMP/ELEVATOR가 존재합니다. 중복 도메인을 유지할지, 재사용/매핑 전략을 둘지 명확히 하면 장기 유지보수 시 혼란을 줄일 수 있습니다.
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityDocumentRepository.java (1)
8-10: 불필요한 메서드 재정의 제거ElasticsearchRepository(CrudRepository)에서 이미 제공하는 findAll()을 재선언할 필요가 없습니다. 제거하여 인터페이스를 간결하게 유지하세요.
다음 수정안을 권장합니다:
public interface WaybleFacilityDocumentRepository extends ElasticsearchRepository<WaybleFacilityDocument, String> { - List<WaybleFacilityDocument> findAll(); }src/main/java/com/wayble/server/explore/controller/WaybleFacilitySearchController.java (2)
24-25: 사소한 스타일: 빈 문자열 매핑 제거@RequestMapping에 기본 경로가 있으므로 @GetMapping에 빈 문자열은 불필요합니다. 가독성을 위해 제거하세요.
- @GetMapping("") + @GetMapping public CommonResponse<List<WaybleFacilityResponseDto>> findNearbyFacilities(
25-29: 거리 반환 여부 검토PR 목표가 “거리 순 정렬”이라면, 응답에 distance 필드를 포함하면 클라이언트가 정렬 근거를 명확히 인지할 수 있습니다. 현재 DTO에는 위도/경도/유형만 있어 후처리가 어렵습니다.
원한다면 WaybleFacilityResponseDto에 Double distance 추가 및 리포지토리 매핑 개선안을 제안하겠습니다.
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityResponseDto.java (2)
16-22: NPE 방어 로직 추가 제안facilityDocument 또는 location이 null이면 NPE가 발생합니다. 사전 검증으로 방어하면 안정성이 높아집니다.
- public static WaybleFacilityResponseDto from(WaybleFacilityDocument facilityDocument) { - return WaybleFacilityResponseDto.builder() - .latitude(facilityDocument.getLocation().getLat()) - .longitude(facilityDocument.getLocation().getLon()) - .facilityType(facilityDocument.getFacilityType()) - .build(); - } + public static WaybleFacilityResponseDto from(WaybleFacilityDocument facilityDocument) { + java.util.Objects.requireNonNull(facilityDocument, "facilityDocument must not be null"); + java.util.Objects.requireNonNull(facilityDocument.getLocation(), "facilityDocument.location must not be null"); + return WaybleFacilityResponseDto.builder() + .latitude(facilityDocument.getLocation().getLat()) + .longitude(facilityDocument.getLocation().getLon()) + .facilityType(facilityDocument.getFacilityType()) + .build(); + }추가 import:
import java.util.Objects;
8-15: 식별자/거리 포함 고려클라이언트에서 마커 식별/후속 조회가 필요하다면 id 또는 distance를 DTO에 포함하는 것을 고려하세요.
src/main/java/com/wayble/server/explore/entity/WaybleFacilityDocument.java (1)
26-27: ES 매핑 명시화 제안: enum을 Keyword로 지정enum은 기본적으로 문자열로 저장되지만, Term Query 최적화를 위해 Keyword 명시를 권장합니다.
-import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; @@ - private FacilityType facilityType; + @Field(type = FieldType.Keyword) + private FacilityType facilityType;src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityConditionDto.java (1)
8-21: 테스트 보강 제안: Validation 실패 케이스
- facilityType 누락 시 400 반환 여부
- 위도/경도 범위 초과 시 400 반환 여부
위 케이스에 대한 통합/단위 테스트가 있는지 확인해 주세요. 없다면 추가를 권장합니다.
원하시면 검증 실패 케이스를 포함한 테스트 템플릿을 생성해 드리겠습니다.
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityQuerySearchRepository.java (4)
24-27: 매직 넘버 제거 및 주석 불일치(5km vs 10km) 수정 제안주석은 5km로 표기되어 있으나 값은 10.0입니다. 혼선을 방지하고 재사용성을 높이기 위해 상수로 분리하고 주석을 정정하세요.
아래와 같이 수정하면 가독성과 유지보수성이 좋아집니다.
private final ElasticsearchOperations operations; private static final IndexCoordinates INDEX = IndexCoordinates.of("wayble_facility_document"); private static final int LIMIT = 50; +private static final double DEFAULT_RADIUS_KM = 10.0; @@ - double radius = 10.0; // 기본 반경 5km + double radius = DEFAULT_RADIUS_KM; // 기본 반경 10km String radiusWithUnit = radius + "km";Also applies to: 34-36
31-33: 메서드 의도 명확화: 타입이 선택(optional)일 경우 네이밍/계약 보완메서드명이 findNearbyFacilitiesByType라서 타입이 필수처럼 읽히지만, 실제로는 facilityType이 null이면 전체를 조회합니다. 일관성을 위해 아래 중 하나를 권장합니다.
- 메서드명을 findNearbyFacilities로 변경하거나 Javadoc에 “facilityType이 null이면 전체 조회”라고 명시
- 혹은 facilityType을 필수로 강제(Bean Validation 또는 Objects.requireNonNull 사용)
83-87: LIMIT와 반경을 외부 파라미터로 열어 확장성 확보현재 LIMIT(50)과 반경(10km)은 고정입니다. 향후 요구사항(“더 많이/덜 보기”, “반경 슬라이더”)을 고려하면 pageable과 radiusKm를 외부에서 주입받는 설계가 유리합니다. Zone 검색과의 API 일관성도 좋아집니다.
- Service/Controller 레이어에서 Pageable과 radiusKm(double)를 받아 Repository에 전달
- 기본값(DEFAULT_RADIUS_KM, 기본 LIMIT)은 null/미지정 시에만 적용
93-99: 정렬 거리(sort values)를 응답에 포함하는 방안 검토(Zone API와 일관성)현재 응답 DTO에는 거리 값이 없습니다. Zone 검색 응답처럼 ES sort values를 활용해 거리(km)를 포함하면 FE/테스트에서 반복 계산(haversine) 없이도 정렬/표시가 가능하고, API 간 일관성이 향상됩니다.
예시(개념):
- SearchHit.getSortValues()의 첫 번째 값을 미터로 간주 후 km로 변환하여 DTO에 distance 필드 추가
- WaybleFacilityResponseDto에 distance(Double) 추가 및 from(hit, doc) 팩토리 제공
src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java (4)
81-99: 테스트 데이터 저장 최적화: saveAll 사용루프 내에서 save를 두 번 호출하기보다 saveAll(List.of(...))로 묶으면 호출 수를 절반으로 줄여 테스트 시간을 단축할 수 있습니다.
- waybleFacilityDocumentRepository.save(rampDocument); - waybleFacilityDocumentRepository.save(elevatorDocument); + waybleFacilityDocumentRepository.saveAll(List.of(rampDocument, elevatorDocument));
251-254: 랜덤 씨드 고정으로 테스트 재현성 확보현재 무작위 데이터를 매 실행 시 생성합니다. 씨드를 고정하면 드문 플레이키니스 가능성을 줄이고 디버깅이 쉬워집니다.
- Random rnd = new Random(); + Random rnd = new Random(42);
101-106: 데이터 정리 범위 검토: deleteAll은 다른 테스트에 영향 가능테스트 종료 시 deleteAll은 인덱스의 모든 문서를 제거합니다. 동일 인덱스를 공유하는 다른 테스트가 있다면 간섭이 발생할 수 있습니다. 테스트에서 생성한 문서의 id를 수집해 deleteAllById로 한정 삭제하는 방안을 고려하세요.
138-141: 테스트 로그 과다 출력 정리System.out.println/printf가 다수 포함되어 있어 CI 로그를 오염시킬 수 있습니다. 실패 시에만 출력되도록 Logger(DEBUG)로 내리거나 제거를 권장합니다.
예:
- 테스트 성공 시 출력 제거
- 실패 메시지는 assert에 포함하여 가독성 유지
Also applies to: 155-156, 169-176, 196-198, 212-214, 227-234
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/main/java/com/wayble/server/explore/controller/WaybleFacilitySearchController.java(1 hunks)src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityConditionDto.java(1 hunks)src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityRegisterDto.java(1 hunks)src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityResponseDto.java(1 hunks)src/main/java/com/wayble/server/explore/entity/FacilityType.java(1 hunks)src/main/java/com/wayble/server/explore/entity/WaybleFacilityDocument.java(1 hunks)src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityDocumentRepository.java(1 hunks)src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityQuerySearchRepository.java(1 hunks)src/main/java/com/wayble/server/explore/service/WaybleFacilityDocumentService.java(1 hunks)src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
src/main/java/com/wayble/server/explore/entity/FacilityType.java (1)
src/main/java/com/wayble/server/direction/entity/type/Type.java (1)
Getter(5-22)
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityConditionDto.java (8)
src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneCreateDto.java (1)
AdminWaybleZoneCreateDto(9-39)src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneDetailDto.java (2)
FacilityInfo(40-43)AdminWaybleZoneDetailDto(10-59)src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java (1)
Builder(10-30)src/main/java/com/wayble/server/explore/dto/recommend/WaybleZoneRecommendConditionDto.java (1)
Builder(8-23)src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneUpdateDto.java (1)
AdminWaybleZoneUpdateDto(9-63)src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneThumbnailDto.java (1)
AdminWaybleZoneThumbnailDto(6-16)src/main/java/com/wayble/server/direction/dto/TransportationRequestDto.java (1)
Location(12-16)src/main/java/com/wayble/server/direction/entity/WaybleMarker.java (1)
WaybleMarker(5-11)
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityQuerySearchRepository.java (1)
src/main/java/com/wayble/server/explore/repository/search/WaybleZoneQuerySearchRepository.java (1)
Repository(23-126)
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityDocumentRepository.java (2)
src/main/java/com/wayble/server/explore/repository/WaybleZoneDocumentRepository.java (1)
WaybleZoneDocumentRepository(9-12)src/main/java/com/wayble/server/explore/service/WaybleZoneDocumentService.java (1)
Service(13-36)
src/main/java/com/wayble/server/explore/entity/WaybleFacilityDocument.java (5)
src/main/java/com/wayble/server/explore/entity/WaybleZoneDocument.java (2)
ToString(10-68)fromEntity(43-54)src/main/java/com/wayble/server/direction/entity/transportation/Facility.java (1)
Entity(11-46)src/main/java/com/wayble/server/explore/entity/EsWaybleZoneFacility.java (1)
ToString(6-34)src/main/java/com/wayble/server/explore/service/WaybleZoneDocumentService.java (2)
Service(13-36)saveDocumentFromEntity(25-27)src/main/java/com/wayble/server/explore/repository/WaybleZoneDocumentRepository.java (1)
WaybleZoneDocumentRepository(9-12)
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityRegisterDto.java (7)
src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneCreateDto.java (1)
AdminWaybleZoneCreateDto(9-39)src/main/java/com/wayble/server/common/dto/FacilityDto.java (1)
Builder(5-13)src/main/java/com/wayble/server/wayblezone/dto/WaybleZoneRegisterDto.java (1)
Builder(8-21)src/main/java/com/wayble/server/admin/dto/wayblezone/AdminWaybleZoneDetailDto.java (2)
FacilityInfo(40-43)AdminWaybleZoneDetailDto(10-59)src/main/java/com/wayble/server/explore/dto/recommend/WaybleZoneRecommendConditionDto.java (1)
Builder(8-23)src/main/java/com/wayble/server/explore/dto/common/FacilityResponseDto.java (1)
Builder(6-29)src/main/java/com/wayble/server/explore/dto/search/request/WaybleZoneSearchConditionDto.java (1)
Builder(10-30)
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityResponseDto.java (3)
src/main/java/com/wayble/server/explore/dto/common/FacilityResponseDto.java (1)
Builder(6-29)src/main/java/com/wayble/server/common/dto/FacilityDto.java (1)
Builder(5-13)src/main/java/com/wayble/server/explore/dto/search/response/WaybleZoneSearchResponseDto.java (1)
Builder(8-22)
src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java (2)
src/test/java/com/wayble/server/explore/WaybleZoneRecommendApiIntegrationTest.java (1)
createRandomFacility(370-383)src/test/java/com/wayble/server/explore/WaybleZoneSearchApiIntegrationTest.java (7)
Test(201-256)createRandomFacility(580-593)Test(258-310)Test(419-474)Test(364-417)Test(312-362)Test(476-531)
🔇 Additional comments (8)
src/main/java/com/wayble/server/explore/entity/FacilityType.java (1)
3-6: LGTM: 단순 enum 정의 적절필요 상수만 담은 단순 enum 도입은 명확하고 사용처와도 일관됩니다.
src/main/java/com/wayble/server/explore/service/WaybleFacilityDocumentService.java (1)
19-21: 위임 계층 구성 적절컨트롤러 → 서비스 → 쿼리 리포지토리로의 위임 구조가 명확합니다. 메서드 명과 역할도 일관적입니다.
src/main/java/com/wayble/server/explore/entity/WaybleFacilityDocument.java (1)
17-25: LGTM: GeoPoint 매핑 적절@GeoPointField 사용으로 위치 기반 정렬/검색에 적합합니다. 인덱스명과 문서 구조도 일관적입니다.
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityRegisterDto.java (1)
9-22: 좌표 검증 일관성 좋음위도/경도 범위 및 NotNull 검증이 기존 DTO들과 일관되며 적절합니다.
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityDocumentRepository.java (1)
8-10: ID 타입 확인 요청엔티티의 id가 String이며 저장 시 외부에서 직접 지정하는지(예: UUID) 또는 ES 자동 생성인지에 따라 컨벤션이 달라질 수 있습니다. 현재 사용처에서 id 생성 전략이 명확한지 확인 부탁드립니다.
src/main/java/com/wayble/server/explore/repository/facility/WaybleFacilityQuerySearchRepository.java (2)
31-36: ES bool 쿼리 + geo-distance 정렬 + 페이지네이션 구성, 전반적으로 적절합니다
- 시설 타입 필터(옵션) + 위치 기반 필터 + 거리 오름차순 정렬 + LIMIT(50) 페이징 조합이 요구사항(가까운 순 조회)에 부합합니다.
- NativeQuery 사용과 DTO 매핑도 깔끔합니다.
Also applies to: 68-87, 89-99
41-48: facilityType 필드 매핑 확인 필요: "facilityType.keyword" 사용의 호환성 점검현재 term 쿼리 필드가 "facilityType.keyword"로 지정되어 있습니다. Enum 필드는 대개 keyword 타입으로 매핑되어 별도의 ".keyword" 서브필드가 없을 수 있습니다. 매핑이 keyword 단일 필드라면 "facilityType"에 대해 term 쿼리를 수행해야 합니다. 매핑과 불일치 시 결과가 비어버릴 수 있습니다.
매핑이 keyword 단일 필드인 경우 다음과 같이 변경을 권장합니다.
- .term(t -> t - .field("facilityType.keyword") - .value(condition.facilityType().name()) - ) + .term(t -> t + .field("facilityType") + .value(condition.facilityType().name()) + )확인을 위해 운영/테스트 ES 인덱스의 매핑에서 facilityType 필드 타입과 서브필드 존재 여부를 검증해 주세요.
src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java (1)
108-118: 테스트 시나리오 전반은 목적에 부합합니다
- MockMvc로 API 호출 → JSON 파싱 → DTO 리스트 검증 → 거리 오름차순 확인 플로우가 명료합니다.
- null 필드 체크 및 타입 필터링 검증도 적절합니다.
Also applies to: 121-176, 179-235
| FacilityType facilityType | ||
| ) { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null 허용 시 NPE 위험: facilityType에 @NotNull 추가 필요
WaybleFacilityQuerySearchRepository에서 condition.facilityType().name()을 사용하는 것으로 보입니다. facilityType이 null이면 NPE가 발생합니다. NotNull 제약을 추가하세요.
다음 수정안을 제안합니다:
- FacilityType facilityType
+ @NotNull(message = "시설 타입 입력은 필수입니다.")
+ FacilityType facilityType테스트에 facilityType 누락 케이스(Negative)도 추가해 주세요.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| FacilityType facilityType | |
| ) { | |
| } | |
| // src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityConditionDto.java | |
| import javax.validation.constraints.NotNull; // ← make sure this import is present | |
| public class WaybleFacilityConditionDto { | |
| // … | |
| public WaybleFacilityConditionDto( | |
| @NotNull(message = "시설 타입 입력은 필수입니다.") | |
| FacilityType facilityType | |
| ) { | |
| this.facilityType = facilityType; | |
| } | |
| // … | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityConditionDto.java
around lines 19-21, facilityType is nullable which risks NPE when calling
condition.facilityType().name(); add a @NotNull annotation to the facilityType
field (and import the correct javax/jakarta validation package used by the
project) so validation fails early, update constructor/getter if needed to
retain the annotation, and add a unit test that covers the negative case where
facilityType is missing to ensure validation prevents the NPE.
| FacilityType facilityType | ||
| ){ | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
등록 시 facilityType 필수값 보장 필요
등록 DTO에서도 facilityType 누락을 방지하기 위해 @NotNull을 추가하세요.
- FacilityType facilityType
+ @NotNull(message = "시설 타입 입력은 필수입니다.")
+ FacilityType facilityType📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| FacilityType facilityType | |
| ){ | |
| } | |
| @NotNull(message = "시설 타입 입력은 필수입니다.") | |
| FacilityType facilityType | |
| ){ | |
| } |
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/dto/facility/WaybleFacilityRegisterDto.java
around lines 21-23, the facilityType field in the registration DTO is missing a
nullability constraint; add the @NotNull annotation to the facilityType
declaration (and the corresponding import, e.g.
javax.validation.constraints.NotNull or jakarta.validation.constraints.NotNull
depending on the project), ensuring the constructor/field carries the annotation
so validation will reject requests without facilityType; run/adjust any
validation tests or configuration if needed to enable request-level validation.
| import jakarta.transaction.Transactional; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
트랜잭션 어노테이션 일관성/적용 범위 조정
- jakarta.transaction.Transactional 보다는 Spring 관리형 트랜잭션(org.springframework.transaction.annotation.Transactional) 사용을 권장합니다.
- 읽기 전용 서비스이므로 readOnly = true 지정 또는 제거가 적절합니다(ES 조회는 트랜잭션 불필요).
다음 수정안을 제안합니다:
-import jakarta.transaction.Transactional;
+import org.springframework.transaction.annotation.Transactional;
@@
-@Transactional
+@Transactional(readOnly = true)
public class WaybleFacilityDocumentService {Also applies to: 12-15
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/explore/service/WaybleFacilityDocumentService.java
around lines 6-8 (also applies to lines 12-15), replace the import of
jakarta.transaction.Transactional with Spring's
org.springframework.transaction.annotation.Transactional and adjust the
annotation usage: for this read-only ES query service either annotate the
class/methods with @Transactional(readOnly = true) or remove transactional
annotations entirely if Elasticsearch operations do not require a transaction;
ensure imports and annotations are updated consistently across the indicated
lines.
| assertThat(dtoList).isNotEmpty(); | ||
|
|
||
| // null 값 검증 | ||
| for (WaybleFacilityResponseDto dto : dtoList) { | ||
| assertThat(dto.latitude()).isNotNull(); | ||
| assertThat(dto.longitude()).isNotNull(); | ||
| assertThat(dto.facilityType()).isNotNull(); | ||
| assertThat(dto.facilityType()).isEqualTo(FacilityType.RAMP); | ||
| System.out.println(dto); | ||
| } | ||
|
|
||
| // 거리순 정렬 검증 | ||
| if (dtoList.size() > 1) { | ||
| for (int i = 0; i < dtoList.size() - 1; i++) { | ||
| WaybleFacilityResponseDto current = dtoList.get(i); | ||
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | ||
|
|
||
| double currentDistance = haversine(LATITUDE, LONGITUDE, | ||
| current.latitude(), current.longitude()); | ||
| double nextDistance = haversine(LATITUDE, LONGITUDE, | ||
| next.latitude(), next.longitude()); | ||
|
|
||
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | ||
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | ||
| } | ||
| // 마지막 요소의 거리도 출력 | ||
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | ||
| double lastDistance = haversine(LATITUDE, LONGITUDE, | ||
| last.latitude(), last.longitude()); | ||
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
반경(10km) 이내 제한 검증과 LIMIT(50) 상한 검증 추가 제안
현재는 정렬만 검증합니다. Repository가 반경 10km 및 LIMIT 50을 적용하므로, 응답이 반경 내이며 결과 수가 상한을 넘지 않는지도 함께 검증하면 회귀를 더 잘 잡아냅니다.
아래와 같이 보강을 제안합니다(반경 상수는 Repository 기본값 10km 기준).
assertThat(dtoList).isNotEmpty();
+ // LIMIT(50) 검증
+ assertThat(dtoList.size()).isLessThanOrEqualTo(50);
@@
// 마지막 요소의 거리도 출력
WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1);
double lastDistance = haversine(LATITUDE, LONGITUDE,
last.latitude(), last.longitude());
System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance);
+ // 반경(10km) 이내 검증 (±50m 허용)
+ assertThat(lastDistance)
+ .withFailMessage("반경 초과: 마지막 요소 거리=%.5f km", lastDistance)
+ .isLessThanOrEqualTo(10.05);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| assertThat(dtoList).isNotEmpty(); | |
| // null 값 검증 | |
| for (WaybleFacilityResponseDto dto : dtoList) { | |
| assertThat(dto.latitude()).isNotNull(); | |
| assertThat(dto.longitude()).isNotNull(); | |
| assertThat(dto.facilityType()).isNotNull(); | |
| assertThat(dto.facilityType()).isEqualTo(FacilityType.RAMP); | |
| System.out.println(dto); | |
| } | |
| // 거리순 정렬 검증 | |
| if (dtoList.size() > 1) { | |
| for (int i = 0; i < dtoList.size() - 1; i++) { | |
| WaybleFacilityResponseDto current = dtoList.get(i); | |
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | |
| double currentDistance = haversine(LATITUDE, LONGITUDE, | |
| current.latitude(), current.longitude()); | |
| double nextDistance = haversine(LATITUDE, LONGITUDE, | |
| next.latitude(), next.longitude()); | |
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | |
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | |
| } | |
| // 마지막 요소의 거리도 출력 | |
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | |
| double lastDistance = haversine(LATITUDE, LONGITUDE, | |
| last.latitude(), last.longitude()); | |
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | |
| } | |
| assertThat(dtoList).isNotEmpty(); | |
| // LIMIT(50) 검증 | |
| assertThat(dtoList.size()).isLessThanOrEqualTo(50); | |
| // null 값 검증 | |
| for (WaybleFacilityResponseDto dto : dtoList) { | |
| assertThat(dto.latitude()).isNotNull(); | |
| assertThat(dto.longitude()).isNotNull(); | |
| assertThat(dto.facilityType()).isNotNull(); | |
| assertThat(dto.facilityType()).isEqualTo(FacilityType.RAMP); | |
| System.out.println(dto); | |
| } | |
| // 거리순 정렬 검증 | |
| if (dtoList.size() > 1) { | |
| for (int i = 0; i < dtoList.size() - 1; i++) { | |
| WaybleFacilityResponseDto current = dtoList.get(i); | |
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | |
| double currentDistance = haversine(LATITUDE, LONGITUDE, | |
| current.latitude(), current.longitude()); | |
| double nextDistance = haversine(LATITUDE, LONGITUDE, | |
| next.latitude(), next.longitude()); | |
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | |
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | |
| } | |
| // 마지막 요소의 거리도 출력 | |
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | |
| double lastDistance = haversine(LATITUDE, LONGITUDE, | |
| last.latitude(), last.longitude()); | |
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | |
| // 반경(10km) 이내 검증 (±50m 허용) | |
| assertThat(lastDistance) | |
| .withFailMessage("반경 초과: 마지막 요소 거리=%.5f km", lastDistance) | |
| .isLessThanOrEqualTo(10.05); | |
| } |
🤖 Prompt for AI Agents
In src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java
around lines 146 to 176, add assertions to enforce the repository constraints:
compute the haversine distance for each dto and assert it is <= 10.0 km (use a
RADIUS_KM constant set to 10.0 to match the repo default), and assert that
dtoList.size() is <= 50 to verify the LIMIT; keep the existing sort-checks
intact and place the new size check before iterating, and the per-item radius
check inside the loop alongside the non-null assertions.
| assertThat(dtoList).isNotEmpty(); | ||
|
|
||
| // null 값 검증 | ||
| for (WaybleFacilityResponseDto dto : dtoList) { | ||
| assertThat(dto.latitude()).isNotNull(); | ||
| assertThat(dto.longitude()).isNotNull(); | ||
| assertThat(dto.facilityType()).isNotNull(); | ||
| assertThat(dto.facilityType()).isEqualTo(FacilityType.ELEVATOR); | ||
| System.out.println(dto); | ||
| } | ||
|
|
||
| // 거리순 정렬 검증 | ||
| if (dtoList.size() > 1) { | ||
| for (int i = 0; i < dtoList.size() - 1; i++) { | ||
| WaybleFacilityResponseDto current = dtoList.get(i); | ||
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | ||
|
|
||
| double currentDistance = haversine(LATITUDE, LONGITUDE, | ||
| current.latitude(), current.longitude()); | ||
| double nextDistance = haversine(LATITUDE, LONGITUDE, | ||
| next.latitude(), next.longitude()); | ||
|
|
||
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | ||
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | ||
| } | ||
| // 마지막 요소의 거리도 출력 | ||
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | ||
| double lastDistance = haversine(LATITUDE, LONGITUDE, | ||
| last.latitude(), last.longitude()); | ||
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
엘리베이터 테스트에도 동일한 반경/LIMIT 검증 적용
위 경사로 테스트와 동일한 검증을 엘리베이터 케이스에도 추가해 주세요. 상한 및 반경 준수 여부를 양 테스트에서 모두 확인하는 것이 안전합니다.
assertThat(dtoList).isNotEmpty();
+ // LIMIT(50) 검증
+ assertThat(dtoList.size()).isLessThanOrEqualTo(50);
@@
WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1);
double lastDistance = haversine(LATITUDE, LONGITUDE,
last.latitude(), last.longitude());
System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance);
+ // 반경(10km) 이내 검증 (±50m 허용)
+ assertThat(lastDistance)
+ .withFailMessage("반경 초과: 마지막 요소 거리=%.5f km", lastDistance)
+ .isLessThanOrEqualTo(10.05);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| assertThat(dtoList).isNotEmpty(); | |
| // null 값 검증 | |
| for (WaybleFacilityResponseDto dto : dtoList) { | |
| assertThat(dto.latitude()).isNotNull(); | |
| assertThat(dto.longitude()).isNotNull(); | |
| assertThat(dto.facilityType()).isNotNull(); | |
| assertThat(dto.facilityType()).isEqualTo(FacilityType.ELEVATOR); | |
| System.out.println(dto); | |
| } | |
| // 거리순 정렬 검증 | |
| if (dtoList.size() > 1) { | |
| for (int i = 0; i < dtoList.size() - 1; i++) { | |
| WaybleFacilityResponseDto current = dtoList.get(i); | |
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | |
| double currentDistance = haversine(LATITUDE, LONGITUDE, | |
| current.latitude(), current.longitude()); | |
| double nextDistance = haversine(LATITUDE, LONGITUDE, | |
| next.latitude(), next.longitude()); | |
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | |
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | |
| } | |
| // 마지막 요소의 거리도 출력 | |
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | |
| double lastDistance = haversine(LATITUDE, LONGITUDE, | |
| last.latitude(), last.longitude()); | |
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | |
| } | |
| } | |
| assertThat(dtoList).isNotEmpty(); | |
| // LIMIT(50) 검증 | |
| assertThat(dtoList.size()).isLessThanOrEqualTo(50); | |
| // null 값 검증 | |
| for (WaybleFacilityResponseDto dto : dtoList) { | |
| assertThat(dto.latitude()).isNotNull(); | |
| assertThat(dto.longitude()).isNotNull(); | |
| assertThat(dto.facilityType()).isNotNull(); | |
| assertThat(dto.facilityType()).isEqualTo(FacilityType.ELEVATOR); | |
| System.out.println(dto); | |
| } | |
| // 거리순 정렬 검증 | |
| if (dtoList.size() > 1) { | |
| for (int i = 0; i < dtoList.size() - 1; i++) { | |
| WaybleFacilityResponseDto current = dtoList.get(i); | |
| WaybleFacilityResponseDto next = dtoList.get(i + 1); | |
| double currentDistance = haversine(LATITUDE, LONGITUDE, | |
| current.latitude(), current.longitude()); | |
| double nextDistance = haversine(LATITUDE, LONGITUDE, | |
| next.latitude(), next.longitude()); | |
| assertThat(currentDistance).isLessThanOrEqualTo(nextDistance); | |
| System.out.printf("Index %d: Distance = %.3f km%n", i, currentDistance); | |
| } | |
| // 마지막 요소의 거리도 출력 | |
| WaybleFacilityResponseDto last = dtoList.get(dtoList.size() - 1); | |
| double lastDistance = haversine(LATITUDE, LONGITUDE, | |
| last.latitude(), last.longitude()); | |
| System.out.printf("Index %d: Distance = %.3f km%n", dtoList.size() - 1, lastDistance); | |
| // 반경(10km) 이내 검증 (±50m 허용) | |
| assertThat(lastDistance) | |
| .withFailMessage("반경 초과: 마지막 요소 거리=%.5f km", lastDistance) | |
| .isLessThanOrEqualTo(10.05); | |
| } |
🤖 Prompt for AI Agents
In src/test/java/com/wayble/server/explore/WaybleFacilityApiIntegrationTest.java
around lines 204 to 235, the elevator test currently checks non-null fields and
ordering by distance but lacks the same radius and LIMIT validations used in the
ramp test; add assertions to (1) assert dtoList.size() is <= the shared LIMIT
constant used by the ramp test, and (2) assert every dto's computed haversine
distance from (LATITUDE, LONGITUDE) is <= the shared RADIUS constant (or the
same radius value used in the ramp test). Use the existing LATITUDE, LONGITUDE,
LIMIT and RADIUS values (or extract them to shared test constants if needed) and
place these checks before/alongside the distance-order assertions so both
elevator and ramp tests enforce identical bounding/limit constraints.
seung-in-Yoo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
테스트 코드 구현한거 보면서 많이 배워가네요 수고하셨습니다🙂
✔️ 연관 이슈
📝 작업 내용
스크린샷 (선택)
Summary by CodeRabbit