From e0e3d7153e8f8459a83690d214b1f79bab0053cd Mon Sep 17 00:00:00 2001 From: lulyulalla Date: Sat, 7 Jun 2025 02:03:15 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=98=A4=EC=B0=A8=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=86=8C=EC=88=98=EC=A0=90=204=EC=9E=90=EB=A6=AC=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20:=20refactor=20:=20=EC=98=A4=EC=B0=A8=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20=EC=86=8C=EC=88=98=EC=A0=90=203=EC=9E=90=EB=A6=AC?= =?UTF-8?q?=EA=B9=8C=EC=A7=80=20=EB=A7=9E=EC=9C=BC=EB=A9=B4=20=EB=A7=9E?= =?UTF-8?q?=EB=8A=94=EA=B1=B8=EB=A1=9C=20https://github.com/freeMates/Free?= =?UTF-8?q?Mates=5FBackend/issues/124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../freemates/controller/PlaceController.java | 3 +- .../jombi/freemates/service/PlaceService.java | 65 +++++++++++++++---- 2 files changed, 55 insertions(+), 13 deletions(-) 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/service/PlaceService.java b/src/main/java/jombi/freemates/service/PlaceService.java index 8b753d9..bce9924 100644 --- a/src/main/java/jombi/freemates/service/PlaceService.java +++ b/src/main/java/jombi/freemates/service/PlaceService.java @@ -1,10 +1,15 @@ package jombi.freemates.service; +import static java.util.stream.Collectors.toList; + +import java.math.BigDecimal; +import java.math.RoundingMode; 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 +123,55 @@ 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()); + + // 소수점 셋째 자리에서 반올림한 기준값 구하기 + BigDecimal bdX = BigDecimal.valueOf(xInput).setScale(3, RoundingMode.HALF_EVEN); + BigDecimal bdY = BigDecimal.valueOf(yInput).setScale(3, RoundingMode.HALF_EVEN); + + // DB에서 일단 모든 Place를 조회해 온 뒤(규모가 크지 않다면 충분히 괜찮음), + // 또는 범위 쿼리를 쓰려면 PlaceRepository에 추가 커스텀 메서드를 만들어도 됨. + List allPlaces = placeRepository.findAll(); + + // 필터링: 각 Place 엔티티가 가지고 있는 x, y를 double로 파싱 → 동일하게 소수점 4자리 반올림 → 비교 + List matched = allPlaces.stream() + .filter(p -> { + String px = p.getX(); + String py = p.getY(); + if (px == null || py == null || px.isBlank() || py.isBlank()) { + return false; + } + double xPlace, yPlace; + try { + xPlace = Double.parseDouble(px); + yPlace = Double.parseDouble(py); + } catch (NumberFormatException ex) { + return false; + } + + BigDecimal bdXPlace = BigDecimal.valueOf(xPlace).setScale(3, RoundingMode.HALF_EVEN); + BigDecimal bdYPlace = BigDecimal.valueOf(yPlace).setScale(3, RoundingMode.HALF_EVEN); + + return bdXPlace.equals(bdX) && bdYPlace.equals(bdY); + }) + .toList(); + + if (matched.isEmpty()) { + throw new CustomException(ErrorCode.PLACE_NOT_FOUND); + } + + // 최종 PlaceDto 리스트로 매핑하여 반환 + return matched.stream() + .map(this::convertToPlaceDto) + .collect(toList()); } /** From ce53099dc8168445196e5a99c5c6bb3408003a5e Mon Sep 17 00:00:00 2001 From: lulyulalla Date: Sat, 7 Jun 2025 02:36:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=98=A4=EC=B0=A8=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=86=8C=EC=88=98=EC=A0=90=204=EC=9E=90=EB=A6=AC=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20:=20refactor=20:=20=EC=98=A4=EC=B0=A8=EB=B2=94?= =?UTF-8?q?=EC=9C=84=2010m=EC=9D=B4=EB=82=B4=EC=97=90=20=EC=9E=A5=EC=86=8C?= =?UTF-8?q?=EB=93=A4=EC=9D=84=20=EB=9D=84=EC=9B=80=20https://github.com/fr?= =?UTF-8?q?eeMates/FreeMates=5FBackend/issues/124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../freemates/repository/PlaceRepository.java | 15 ++++++ .../jombi/freemates/service/PlaceService.java | 48 +++++-------------- 2 files changed, 27 insertions(+), 36 deletions(-) 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 bce9924..ac83f04 100644 --- a/src/main/java/jombi/freemates/service/PlaceService.java +++ b/src/main/java/jombi/freemates/service/PlaceService.java @@ -3,12 +3,8 @@ import static java.util.stream.Collectors.toList; -import java.math.BigDecimal; -import java.math.RoundingMode; 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; @@ -133,45 +129,25 @@ public List getPlacesByGeocode(String xStr, String yStr) { throw new CustomException(ErrorCode.INVALID_REQUEST); } - // 소수점 셋째 자리에서 반올림한 기준값 구하기 - BigDecimal bdX = BigDecimal.valueOf(xInput).setScale(3, RoundingMode.HALF_EVEN); - BigDecimal bdY = BigDecimal.valueOf(yInput).setScale(3, RoundingMode.HALF_EVEN); - - // DB에서 일단 모든 Place를 조회해 온 뒤(규모가 크지 않다면 충분히 괜찮음), - // 또는 범위 쿼리를 쓰려면 PlaceRepository에 추가 커스텀 메서드를 만들어도 됨. - List allPlaces = placeRepository.findAll(); - - // 필터링: 각 Place 엔티티가 가지고 있는 x, y를 double로 파싱 → 동일하게 소수점 4자리 반올림 → 비교 - List matched = allPlaces.stream() - .filter(p -> { - String px = p.getX(); - String py = p.getY(); - if (px == null || py == null || px.isBlank() || py.isBlank()) { - return false; - } - double xPlace, yPlace; - try { - xPlace = Double.parseDouble(px); - yPlace = Double.parseDouble(py); - } catch (NumberFormatException ex) { - return false; - } - - BigDecimal bdXPlace = BigDecimal.valueOf(xPlace).setScale(3, RoundingMode.HALF_EVEN); - BigDecimal bdYPlace = BigDecimal.valueOf(yPlace).setScale(3, RoundingMode.HALF_EVEN); - - return bdXPlace.equals(bdX) && bdYPlace.equals(bdY); - }) - .toList(); + // ±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(); } - // 최종 PlaceDto 리스트로 매핑하여 반환 + // Place → PlaceDto로 변환 return matched.stream() .map(this::convertToPlaceDto) - .collect(toList()); + .collect(Collectors.toList()); } /**