diff --git a/src/main/java/jombi/freemates/controller/PlaceController.java b/src/main/java/jombi/freemates/controller/PlaceController.java index b2ee1ab..422fd81 100644 --- a/src/main/java/jombi/freemates/controller/PlaceController.java +++ b/src/main/java/jombi/freemates/controller/PlaceController.java @@ -2,6 +2,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import jombi.freemates.model.constant.Author; import jombi.freemates.model.constant.CategoryType; import jombi.freemates.model.dto.PlaceDto; @@ -112,7 +113,7 @@ public ResponseEntity> getPlacesByCategory( """ ) @GetMapping("/geocode") - public ResponseEntity getPlaceByGeocode( + public ResponseEntity> getPlaceByGeocode( @RequestParam String x, @RequestParam String y ) { diff --git a/src/main/java/jombi/freemates/repository/PlaceRepository.java b/src/main/java/jombi/freemates/repository/PlaceRepository.java index 2ca629e..9444864 100644 --- a/src/main/java/jombi/freemates/repository/PlaceRepository.java +++ b/src/main/java/jombi/freemates/repository/PlaceRepository.java @@ -1,5 +1,6 @@ package jombi.freemates.repository; +import java.util.List; import java.util.Optional; import java.util.UUID; import jombi.freemates.model.constant.CategoryType; @@ -45,4 +46,18 @@ public interface PlaceRepository extends JpaRepository { Optional findByXAndY(String x, String y); + @Query( + value = "SELECT * " + + "FROM place p " + + "WHERE CAST(p.x AS double precision) BETWEEN :xMin AND :xMax " + + " AND CAST(p.y AS double precision) BETWEEN :yMin AND :yMax", + nativeQuery = true + ) + List findByCoordinateRange( + @Param("xMin") double xMin, + @Param("xMax") double xMax, + @Param("yMin") double yMin, + @Param("yMax") double yMax + ); + } diff --git a/src/main/java/jombi/freemates/service/PlaceService.java b/src/main/java/jombi/freemates/service/PlaceService.java index 8b753d9..ac83f04 100644 --- a/src/main/java/jombi/freemates/service/PlaceService.java +++ b/src/main/java/jombi/freemates/service/PlaceService.java @@ -1,10 +1,11 @@ package jombi.freemates.service; +import static java.util.stream.Collectors.toList; + import java.time.Duration; import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.stream.Collectors; import jombi.freemates.model.constant.CategoryType; import jombi.freemates.model.dto.KakaoPlaceCrawlDetail; import jombi.freemates.model.dto.PlaceDto; @@ -118,19 +119,35 @@ public Page getPlacesByCategory(CategoryType category, Pageable pageab * 좌표에 따른 장소 조회 */ @Transactional(readOnly = true) - public PlaceDto getPlacesByGeocode( - String x, - String y - ) { - if (x == null || x.trim().isEmpty() || y == null || y.trim().isEmpty()) { - throw new CustomException(ErrorCode.INVALID_REQUEST); - } - Optional placeOpt = placeRepository.findByXAndY(x, y); - if (placeOpt.isEmpty()) { - log.warn("좌표 ({}, {})에 해당하는 장소가 없습니다.", x, y); - throw new CustomException(ErrorCode.PLACE_NOT_FOUND); // 또는 예외 처리 + public List getPlacesByGeocode(String xStr, String yStr) { + double xInput; + double yInput; + try { + xInput = Double.parseDouble(xStr); + yInput = Double.parseDouble(yStr); + } catch (NumberFormatException e) { + throw new CustomException(ErrorCode.INVALID_REQUEST); } - return convertToPlaceDto(placeOpt.get()); + + // ±0.0001(= tolerance) 범위를 오차로 설정 + double tolerance = 0.0001; // 0.0001은 약 11m 정도의 거리 + double xMin = xInput - tolerance; + double xMax = xInput + tolerance; + double yMin = yInput - tolerance; + double yMax = yInput + tolerance; + + // 네이티브 쿼리로 DB에서 범위 내의 장소만 한 번에 조회 + List matched = placeRepository.findByCoordinateRange(xMin, xMax, yMin, yMax); + if (matched.isEmpty()) { + throw new CustomException(ErrorCode.PLACE_NOT_FOUND); + // 혹은 빈 리스트를 반환하고 싶다면 아래처럼: + // return Collections.emptyList(); + } + + // Place → PlaceDto로 변환 + return matched.stream() + .map(this::convertToPlaceDto) + .collect(Collectors.toList()); } /**