From 6d689ca481147015125bb14b0c0ab42df18ad30f Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 11:50:26 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[refactor]=20=EC=97=90=EB=9F=AC=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../direction/exception/DirectionErrorCase.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java b/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java index 0977327c..e8594877 100644 --- a/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java +++ b/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java @@ -8,10 +8,13 @@ @RequiredArgsConstructor public enum DirectionErrorCase implements ErrorCase { - PATH_NOT_FOUND(400, 4001, "해당하는 경로를 찾을 수 없습니다."), - ES_INDEXING_FAILED(500, 4002, "ElasticSearch 인덱싱에 실패했습니다."), - HISTORY_NOT_FOUND(400, 4004, "검색 기록이 없습니다."), - DISTANCE_TOO_FAR(400, 4002, "거리가 30km 이상입니다."); + ES_INDEXING_FAILED(500, 4001, "ElasticSearch 인덱싱에 실패했습니다."), + HISTORY_NOT_FOUND(400, 4002, "검색 기록이 없습니다."), + + PATH_NOT_FOUND(400, 4003, "해당하는 경로를 찾을 수 없습니다."), + DISTANCE_TOO_FAR(400, 4004, "거리가 30km 이상입니다."), + SYSTEM_ERROR(500, 4005, "길찾기 시스템에 오류가 발생했습니다."), + NO_NEARBY_STATIONS(400, 4006, "주변에 정류장이 없습니다."); private final Integer httpStatusCode; private final Integer errorCode; From 0368fb57310c755c34444725f1f0e402bb6a21fd Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 15:15:07 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[refactor]=20=EB=A9=94=EB=AA=A8=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TransportationService.java | 118 ++++++++++++------ 1 file changed, 80 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/service/TransportationService.java b/src/main/java/com/wayble/server/direction/service/TransportationService.java index 6a37f975..230d8e45 100644 --- a/src/main/java/com/wayble/server/direction/service/TransportationService.java +++ b/src/main/java/com/wayble/server/direction/service/TransportationService.java @@ -52,50 +52,78 @@ private NodeRef toNodeRef(Node node) { } public TransportationResponseDto findRoutes(TransportationRequestDto request){ - - TransportationRequestDto.Location origin = request.origin(); - TransportationRequestDto.Location destination = request.destination(); - // 1. 거리 검증 (30km 제한) - double distance = haversine(origin.latitude(), origin.longitude(), - destination.latitude(), destination.longitude()); - if (distance >= DISTANCE_CONSTRAINT) { - throw new ApplicationException(DISTANCE_TOO_FAR); - } + List> allRoutes = null; + List> pagedRoutes = null; + List routeList = null; + TransportationRequestDto.Location origin = null; + TransportationRequestDto.Location destination = null; + Node start = null; + Node end = null; + TransportationResponseDto.PageInfo pageInfo = null; + + try { + origin = request.origin(); + destination = request.destination(); + // 1. 거리 검증 (30km 제한) + double distance = haversine(origin.latitude(), origin.longitude(), + destination.latitude(), destination.longitude()); + if (distance >= DISTANCE_CONSTRAINT) { + throw new ApplicationException(DISTANCE_TOO_FAR); + } - // 2. 임시 노드 생성 - Node start = Node.createNode(-1L, origin.name(), DirectionType.FROM_WAYPOINT ,origin.latitude(), origin.longitude()); - Node end = Node.createNode(-2L, destination.name(), DirectionType.TO_WAYPOINT,destination.latitude(), destination.longitude()); + // 2. 임시 노드 생성 + start = Node.createNode(-1L, origin.name(), DirectionType.FROM_WAYPOINT ,origin.latitude(), origin.longitude()); + end = Node.createNode(-2L, destination.name(), DirectionType.TO_WAYPOINT,destination.latitude(), destination.longitude()); - // 3. 여러 경로 찾기 - List> allRoutes = findMultipleTransportationRoutes(start, end); + // 3. 여러 경로 찾기 + allRoutes = findMultipleTransportationRoutes(start, end); - // 4. 페이징 처리 - int startIndex = (request.cursor() != null) ? request.cursor() : 0; - int pageSize = (request.size() != null) ? request.size() : 5; // 기본값 5로 설정 - int endIndex = Math.min(startIndex + pageSize, allRoutes.size()); - boolean hasNext = endIndex < allRoutes.size(); - Integer nextCursor = hasNext ? endIndex : null; - TransportationResponseDto.PageInfo pageInfo = new TransportationResponseDto.PageInfo(nextCursor, hasNext); + // 4. 페이징 처리 + int startIndex = (request.cursor() != null) ? request.cursor() : 0; + int pageSize = (request.size() != null) ? request.size() : 5; // 기본값 5로 설정 + int endIndex = Math.min(startIndex + pageSize, allRoutes.size()); + boolean hasNext = endIndex < allRoutes.size(); + Integer nextCursor = hasNext ? endIndex : null; + pageInfo = new TransportationResponseDto.PageInfo(nextCursor, hasNext); - // 경로를 찾지 못한 경우 처리 - if (allRoutes.isEmpty()) { - throw new ApplicationException(PATH_NOT_FOUND); - } + // 경로를 찾지 못한 경우 처리 + if (allRoutes.isEmpty()) { + throw new ApplicationException(PATH_NOT_FOUND); + } - // 페이징된 경로들을 Route 객체로 변환 - List routeList = new ArrayList<>(); - List> pagedRoutes = allRoutes.subList(startIndex, endIndex); - for (int i = 0; i < pagedRoutes.size(); i++) { - List internalRoute = pagedRoutes.get(i); + // 페이징된 경로들을 Route 객체로 변환 + routeList = new ArrayList<>(); + pagedRoutes = allRoutes.subList(startIndex, endIndex); + + for (int i = 0; i < pagedRoutes.size(); i++) { + List internalRoute = pagedRoutes.get(i); + + List enrichedRoute = enrichRoutesWithServiceInfo(internalRoute); + + TransportationResponseDto.Route routeObj = createRoute(enrichedRoute, startIndex + i + 1); + routeList.add(routeObj); + } + + TransportationResponseDto result = new TransportationResponseDto(routeList, pageInfo); - // InternalStep을 TransportationResponseDto.Step으로 변환 (API 호출 포함) - List enrichedRoute = enrichRoutesWithServiceInfo(internalRoute); + return result; + } finally { + // 메모리 정리 + if (allRoutes != null) { + allRoutes.clear(); + allRoutes = null; + } + if (pagedRoutes != null) { + pagedRoutes = null; + } + routeList = null; - TransportationResponseDto.Route routeObj = createRoute(enrichedRoute, startIndex + i + 1); - routeList.add(routeObj); + origin = null; + destination = null; + start = null; + end = null; + pageInfo = null; } - - return new TransportationResponseDto(routeList, pageInfo); } private TransportationResponseDto.Route createRoute(List steps, int routeIndex) { @@ -316,6 +344,16 @@ private List> findAlternativeRoutesEfficiently( usedEdges.addAll(newUsedEdges); alternativeRoutes.add(newRoute); + + // 메모리 정리 + if (newUsedEdges != null) { + newUsedEdges.clear(); + newUsedEdges = null; + } + if (penalizedWeightMap != null) { + penalizedWeightMap.clear(); + penalizedWeightMap = null; + } } return alternativeRoutes; @@ -559,8 +597,10 @@ private List runDijkstra(Map> graph, Node start, } distance.put(start.getId(), 0); + // PriorityQueue 크기 제한 + final Map finalDistance = distance; PriorityQueue pq = new PriorityQueue<>(Math.min(1000, nodes.size()), - Comparator.comparingInt(n -> distance.get(n.getId()))); + Comparator.comparingInt(n -> finalDistance.getOrDefault(n.getId(), Integer.MAX_VALUE))); pq.add(start); int visitedCount = 0; @@ -690,7 +730,9 @@ private List runDijkstra(Map> graph, Node start, current = prevNode.get(current.getId()); } - return mergeConsecutiveRoutes(pathEdges, requestId); + List result = mergeConsecutiveRoutes(pathEdges, requestId); + + return result; } private List enrichRoutesWithServiceInfo(List steps) { From 02a6b98429ccfc104d078417baa0575726114db0 Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 16:45:52 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[refactor]=20=EB=94=94=EB=A0=89=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../direction/dto/{ => internal}/InternalStep.java | 2 +- .../server/direction/dto/{ => internal}/NodeRef.java | 2 +- .../dto/{ => internal}/TransportationGraphDto.java | 2 +- .../EdgeBoundingBoxProjection.java | 2 +- .../{ => transportation}/EdgeRepository.java | 5 +++-- .../{ => transportation}/ElevatorRepository.java | 2 +- .../{ => transportation}/FacilityRepository.java | 2 +- .../NodeBoundingBoxProjection.java | 2 +- .../{ => transportation}/NodeRepository.java | 5 +++-- .../{ => transportation}/RouteRepository.java | 2 +- .../{ => transportation}/WheelchairInfoRepository.java | 2 +- .../server/direction/service/BusInfoService.java | 2 +- .../server/direction/service/FacilityService.java | 10 +++++----- 13 files changed, 21 insertions(+), 19 deletions(-) rename src/main/java/com/wayble/server/direction/dto/{ => internal}/InternalStep.java (92%) rename src/main/java/com/wayble/server/direction/dto/{ => internal}/NodeRef.java (68%) rename src/main/java/com/wayble/server/direction/dto/{ => internal}/TransportationGraphDto.java (89%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/EdgeBoundingBoxProjection.java (87%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/EdgeRepository.java (92%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/ElevatorRepository.java (89%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/FacilityRepository.java (87%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/NodeBoundingBoxProjection.java (79%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/NodeRepository.java (86%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/RouteRepository.java (88%) rename src/main/java/com/wayble/server/direction/repository/{ => transportation}/WheelchairInfoRepository.java (91%) diff --git a/src/main/java/com/wayble/server/direction/dto/InternalStep.java b/src/main/java/com/wayble/server/direction/dto/internal/InternalStep.java similarity index 92% rename from src/main/java/com/wayble/server/direction/dto/InternalStep.java rename to src/main/java/com/wayble/server/direction/dto/internal/InternalStep.java index a41c6631..d4ecdc81 100644 --- a/src/main/java/com/wayble/server/direction/dto/InternalStep.java +++ b/src/main/java/com/wayble/server/direction/dto/internal/InternalStep.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.dto; +package com.wayble.server.direction.dto.internal; import java.util.List; diff --git a/src/main/java/com/wayble/server/direction/dto/NodeRef.java b/src/main/java/com/wayble/server/direction/dto/internal/NodeRef.java similarity index 68% rename from src/main/java/com/wayble/server/direction/dto/NodeRef.java rename to src/main/java/com/wayble/server/direction/dto/internal/NodeRef.java index d6d7f543..c26e6d40 100644 --- a/src/main/java/com/wayble/server/direction/dto/NodeRef.java +++ b/src/main/java/com/wayble/server/direction/dto/internal/NodeRef.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.dto; +package com.wayble.server.direction.dto.internal; public record NodeRef( Long id, diff --git a/src/main/java/com/wayble/server/direction/dto/TransportationGraphDto.java b/src/main/java/com/wayble/server/direction/dto/internal/TransportationGraphDto.java similarity index 89% rename from src/main/java/com/wayble/server/direction/dto/TransportationGraphDto.java rename to src/main/java/com/wayble/server/direction/dto/internal/TransportationGraphDto.java index ebdddb47..b061b6fa 100644 --- a/src/main/java/com/wayble/server/direction/dto/TransportationGraphDto.java +++ b/src/main/java/com/wayble/server/direction/dto/internal/TransportationGraphDto.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.dto; +package com.wayble.server.direction.dto.internal; import com.wayble.server.direction.entity.transportation.Edge; import org.springframework.data.util.Pair; diff --git a/src/main/java/com/wayble/server/direction/repository/EdgeBoundingBoxProjection.java b/src/main/java/com/wayble/server/direction/repository/transportation/EdgeBoundingBoxProjection.java similarity index 87% rename from src/main/java/com/wayble/server/direction/repository/EdgeBoundingBoxProjection.java rename to src/main/java/com/wayble/server/direction/repository/transportation/EdgeBoundingBoxProjection.java index 66e911d1..16589705 100644 --- a/src/main/java/com/wayble/server/direction/repository/EdgeBoundingBoxProjection.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/EdgeBoundingBoxProjection.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.type.DirectionType; diff --git a/src/main/java/com/wayble/server/direction/repository/EdgeRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/EdgeRepository.java similarity index 92% rename from src/main/java/com/wayble/server/direction/repository/EdgeRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/EdgeRepository.java index d0dbce87..c6b3c365 100644 --- a/src/main/java/com/wayble/server/direction/repository/EdgeRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/EdgeRepository.java @@ -1,7 +1,8 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.transportation.Edge; -import com.wayble.server.direction.repository.EdgeBoundingBoxProjection; +import com.wayble.server.direction.repository.transportation.EdgeBoundingBoxProjection; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/wayble/server/direction/repository/ElevatorRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/ElevatorRepository.java similarity index 89% rename from src/main/java/com/wayble/server/direction/repository/ElevatorRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/ElevatorRepository.java index c659d629..1a5930a3 100644 --- a/src/main/java/com/wayble/server/direction/repository/ElevatorRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/ElevatorRepository.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.transportation.Elevator; import com.wayble.server.direction.entity.transportation.Facility; diff --git a/src/main/java/com/wayble/server/direction/repository/FacilityRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/FacilityRepository.java similarity index 87% rename from src/main/java/com/wayble/server/direction/repository/FacilityRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/FacilityRepository.java index 77b4ab09..514b862f 100644 --- a/src/main/java/com/wayble/server/direction/repository/FacilityRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/FacilityRepository.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.transportation.Facility; diff --git a/src/main/java/com/wayble/server/direction/repository/NodeBoundingBoxProjection.java b/src/main/java/com/wayble/server/direction/repository/transportation/NodeBoundingBoxProjection.java similarity index 79% rename from src/main/java/com/wayble/server/direction/repository/NodeBoundingBoxProjection.java rename to src/main/java/com/wayble/server/direction/repository/transportation/NodeBoundingBoxProjection.java index b5a02b97..69f3f651 100644 --- a/src/main/java/com/wayble/server/direction/repository/NodeBoundingBoxProjection.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/NodeBoundingBoxProjection.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.type.DirectionType; diff --git a/src/main/java/com/wayble/server/direction/repository/NodeRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/NodeRepository.java similarity index 86% rename from src/main/java/com/wayble/server/direction/repository/NodeRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/NodeRepository.java index b5b0bc52..00646aab 100644 --- a/src/main/java/com/wayble/server/direction/repository/NodeRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/NodeRepository.java @@ -1,7 +1,8 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.transportation.Node; -import com.wayble.server.direction.repository.NodeBoundingBoxProjection; +import com.wayble.server.direction.repository.transportation.NodeBoundingBoxProjection; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/wayble/server/direction/repository/RouteRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/RouteRepository.java similarity index 88% rename from src/main/java/com/wayble/server/direction/repository/RouteRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/RouteRepository.java index c052ecc5..3d6cee9d 100644 --- a/src/main/java/com/wayble/server/direction/repository/RouteRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/RouteRepository.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/com/wayble/server/direction/repository/WheelchairInfoRepository.java b/src/main/java/com/wayble/server/direction/repository/transportation/WheelchairInfoRepository.java similarity index 91% rename from src/main/java/com/wayble/server/direction/repository/WheelchairInfoRepository.java rename to src/main/java/com/wayble/server/direction/repository/transportation/WheelchairInfoRepository.java index 41aea5f4..5907b70e 100644 --- a/src/main/java/com/wayble/server/direction/repository/WheelchairInfoRepository.java +++ b/src/main/java/com/wayble/server/direction/repository/transportation/WheelchairInfoRepository.java @@ -1,4 +1,4 @@ -package com.wayble.server.direction.repository; +package com.wayble.server.direction.repository.transportation; import com.wayble.server.direction.entity.transportation.Wheelchair; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/wayble/server/direction/service/BusInfoService.java b/src/main/java/com/wayble/server/direction/service/BusInfoService.java index fec024bc..f40c4c4c 100644 --- a/src/main/java/com/wayble/server/direction/service/BusInfoService.java +++ b/src/main/java/com/wayble/server/direction/service/BusInfoService.java @@ -7,7 +7,7 @@ import com.wayble.server.direction.external.opendata.OpenDataProperties; import com.wayble.server.direction.external.opendata.dto.OpenDataResponse; import com.wayble.server.direction.external.opendata.dto.StationSearchResponse; -import com.wayble.server.direction.repository.RouteRepository; +import com.wayble.server.direction.repository.transportation.RouteRepository; import com.wayble.server.direction.dto.response.TransportationResponseDto; import java.net.URI; diff --git a/src/main/java/com/wayble/server/direction/service/FacilityService.java b/src/main/java/com/wayble/server/direction/service/FacilityService.java index 77715b54..7ae2f6d6 100644 --- a/src/main/java/com/wayble/server/direction/service/FacilityService.java +++ b/src/main/java/com/wayble/server/direction/service/FacilityService.java @@ -8,12 +8,12 @@ import com.wayble.server.direction.external.kric.dto.KricToiletRawItem; import com.wayble.server.direction.external.kric.dto.KricToiletRawResponse; +import com.wayble.server.direction.repository.transportation.ElevatorRepository; +import com.wayble.server.direction.repository.transportation.FacilityRepository; +import com.wayble.server.direction.repository.transportation.NodeRepository; +import com.wayble.server.direction.repository.transportation.RouteRepository; +import com.wayble.server.direction.repository.transportation.WheelchairInfoRepository; -import com.wayble.server.direction.repository.ElevatorRepository; -import com.wayble.server.direction.repository.FacilityRepository; -import com.wayble.server.direction.repository.NodeRepository; -import com.wayble.server.direction.repository.RouteRepository; -import com.wayble.server.direction.repository.WheelchairInfoRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.Builder; From c3b90c8f1072bf50d3b55942d6ada39283b6098b Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 17:10:27 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[refactor]=20=EC=A4=91=EB=B3=B5=EB=90=9C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TransportationService.java | 54 +++++++------------ .../direction/service/util/HaversineUtil.java | 4 ++ 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/service/TransportationService.java b/src/main/java/com/wayble/server/direction/service/TransportationService.java index 230d8e45..d64f5e1d 100644 --- a/src/main/java/com/wayble/server/direction/service/TransportationService.java +++ b/src/main/java/com/wayble/server/direction/service/TransportationService.java @@ -1,19 +1,21 @@ package com.wayble.server.direction.service; import com.wayble.server.common.exception.ApplicationException; -import com.wayble.server.direction.dto.InternalStep; -import com.wayble.server.direction.dto.NodeRef; -import com.wayble.server.direction.dto.TransportationGraphDto; +import com.wayble.server.direction.dto.internal.InternalStep; +import com.wayble.server.direction.dto.internal.NodeRef; +import com.wayble.server.direction.dto.internal.TransportationGraphDto; import com.wayble.server.direction.dto.request.TransportationRequestDto; import com.wayble.server.direction.dto.response.TransportationResponseDto; import com.wayble.server.direction.entity.transportation.Edge; import com.wayble.server.direction.entity.transportation.Node; import com.wayble.server.direction.entity.transportation.Route; import com.wayble.server.direction.entity.type.DirectionType; -import com.wayble.server.direction.repository.EdgeBoundingBoxProjection; -import com.wayble.server.direction.repository.EdgeRepository; -import com.wayble.server.direction.repository.NodeBoundingBoxProjection; -import com.wayble.server.direction.repository.NodeRepository; +import com.wayble.server.direction.repository.transportation.EdgeBoundingBoxProjection; +import com.wayble.server.direction.repository.transportation.EdgeRepository; +import com.wayble.server.direction.repository.transportation.NodeBoundingBoxProjection; +import com.wayble.server.direction.repository.transportation.NodeRepository; +import com.wayble.server.direction.service.util.HaversineUtil; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.util.Pair; @@ -65,7 +67,7 @@ public TransportationResponseDto findRoutes(TransportationRequestDto request){ origin = request.origin(); destination = request.destination(); // 1. 거리 검증 (30km 제한) - double distance = haversine(origin.latitude(), origin.longitude(), + double distance = HaversineUtil.haversineKm(origin.latitude(), origin.longitude(), destination.latitude(), destination.longitude()); if (distance >= DISTANCE_CONSTRAINT) { throw new ApplicationException(DISTANCE_TOO_FAR); @@ -494,7 +496,7 @@ private TransportationGraphDto buildGraph(List nodes, List edges, No graph.get(startId).add(edge); - int weight = (int)(haversine( + int weight = (int)(HaversineUtil.haversineKm( start.getLatitude(), start.getLongitude(), end.getLatitude(), end.getLongitude() ) * METER_CONVERSION); @@ -523,7 +525,7 @@ private void addOriginDestinationWalkConnections(Map> graph, Ma Edge walkEdge = Edge.createEdge(-1L, startNode, candidate, DirectionType.WALK); graph.get(startNode.getId()).add(walkEdge); - int weight = (int)(haversine( + int weight = (int)(HaversineUtil.haversineKm( startNode.getLatitude(), startNode.getLongitude(), candidate.getLatitude(), candidate.getLongitude() ) * METER_CONVERSION); @@ -540,7 +542,7 @@ private void addOriginDestinationWalkConnections(Map> graph, Ma } graph.get(candidate.getId()).add(walkEdge); - int weight = (int)(haversine( + int weight = (int)(HaversineUtil.haversineKm( candidate.getLatitude(), candidate.getLongitude(), endNode.getLatitude(), endNode.getLongitude() ) * METER_CONVERSION); @@ -567,11 +569,11 @@ private List findNearbyNodes(List nodes, double lat, double lon, int } // 정확한 거리 계산 - double distance = haversine(lat, lon, node.getLatitude(), node.getLongitude()) * METER_CONVERSION; + double distance = HaversineUtil.haversineKm(lat, lon, node.getLatitude(), node.getLongitude()) * METER_CONVERSION; return distance <= maxDistanceMeters; }) .sorted(Comparator.comparingDouble(node -> - haversine(lat, lon, node.getLatitude(), node.getLongitude()))) + HaversineUtil.haversineKm(lat, lon, node.getLatitude(), node.getLongitude()))) .limit(MAX_NEARBY_NODES) .collect(Collectors.toList()); } @@ -633,7 +635,7 @@ private List runDijkstra(Map> graph, Node start, for (Node nearbyNode : nearbyNodes) { if (visited.contains(nearbyNode.getId())) continue; - double walkDistance = haversine( + double walkDistance = HaversineUtil.haversineKm( curr.getLatitude(), curr.getLongitude(), nearbyNode.getLatitude(), nearbyNode.getLongitude() ) * METER_CONVERSION; @@ -668,7 +670,7 @@ private List runDijkstra(Map> graph, Node start, Pair key = Pair.of(edge.getStartNode().getId(), edge.getEndNode().getId()); int baseWeight = weightMap.getOrDefault(key, - (int)(haversine( + (int)(HaversineUtil.haversineKm( edge.getStartNode().getLatitude(), edge.getStartNode().getLongitude(), edge.getEndNode().getLatitude(), edge.getEndNode().getLongitude() ) * METER_CONVERSION) @@ -843,7 +845,7 @@ private List mergeConsecutiveRoutes(List pathEdges, long req Node walkEndNode = pathEdges.get(j - 1).getEndNode(); if (walkStartNode != null && walkEndNode != null) { - double distanceKm = haversine( + double distanceKm = HaversineUtil.haversineKm( walkStartNode.getLatitude(), walkStartNode.getLongitude(), walkEndNode.getLatitude(), walkEndNode.getLongitude() ); @@ -964,7 +966,7 @@ private int calculateTransferWalkDistance(String fromStation, String toStation, } if (fromNode != null && toNode != null) { - double distanceKm = haversine( + double distanceKm = HaversineUtil.haversineKm( fromNode.getLatitude(), fromNode.getLongitude(), toNode.getLatitude(), toNode.getLongitude() ); @@ -999,28 +1001,12 @@ private String getRouteName(List pathEdges, int start, int end) { return null; } - public static double haversine( - double lat1, double lon1, - double lat2, double lon2 - ) { - final int R = 6_371; // 지구 반지름 (km) - double φ1 = Math.toRadians(lat1); - double φ2 = Math.toRadians(lat2); - double Δφ = Math.toRadians(lat2 - lat1); - double Δλ = Math.toRadians(lon2 - lon1); - - double a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) - + Math.cos(φ1) * Math.cos(φ2) - * Math.sin(Δλ / 2) * Math.sin(Δλ / 2); - double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - return R * c; // km 단위 거리 반환 - } private Node findNearestNode(List nodes, double lat, double lon) { return nodes.stream() .min(Comparator.comparingDouble(n -> - haversine(lat, lon, n.getLatitude(), n.getLongitude()))) + HaversineUtil.haversineKm(lat, lon, n.getLatitude(), n.getLongitude()))) .orElse(null); } diff --git a/src/main/java/com/wayble/server/direction/service/util/HaversineUtil.java b/src/main/java/com/wayble/server/direction/service/util/HaversineUtil.java index 3baf2280..c3e6561d 100644 --- a/src/main/java/com/wayble/server/direction/service/util/HaversineUtil.java +++ b/src/main/java/com/wayble/server/direction/service/util/HaversineUtil.java @@ -13,4 +13,8 @@ public static double haversine(double lat1, double lon1, double lat2, double lon double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return EARTH_RADIUS * c; } + + public static double haversineKm(double lat1, double lon1, double lat2, double lon2) { + return haversine(lat1, lon1, lat2, lon2) / 1000.0; + } } From 471d7d280a8d706f10e5eb31538a9704156d6a69 Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 18:55:51 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[refactor]=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AC=EC=9A=A9=EC=9D=84=20=EC=84=B8=EB=B6=84?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TransportationService.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/service/TransportationService.java b/src/main/java/com/wayble/server/direction/service/TransportationService.java index d64f5e1d..61a25e14 100644 --- a/src/main/java/com/wayble/server/direction/service/TransportationService.java +++ b/src/main/java/com/wayble/server/direction/service/TransportationService.java @@ -26,6 +26,8 @@ import static com.wayble.server.direction.exception.DirectionErrorCase.PATH_NOT_FOUND; import static com.wayble.server.direction.exception.DirectionErrorCase.DISTANCE_TOO_FAR; +import static com.wayble.server.direction.exception.DirectionErrorCase.NO_NEARBY_STATIONS; +import static com.wayble.server.direction.exception.DirectionErrorCase.SYSTEM_ERROR; @Slf4j @Service @RequiredArgsConstructor @@ -208,7 +210,7 @@ private List> findMultipleTransportationRoutes(Node startTmp, Node nearestToEnd = findNearestNode(nodes, endTmp.getLatitude(), endTmp.getLongitude()); if (nearestToStart == null || nearestToEnd == null) { - throw new ApplicationException(PATH_NOT_FOUND); + throw new ApplicationException(NO_NEARBY_STATIONS); } // 3. 임시 노드 추가 @@ -223,9 +225,9 @@ private List> findMultipleTransportationRoutes(Node startTmp, return result; - } catch (OutOfMemoryError e) { - log.error("Out of memory error in transportation route finding: {}", e.getMessage()); - throw new ApplicationException(PATH_NOT_FOUND); + } catch (Exception e) { + log.error("Unexpected error in transportation route finding: {}", e.getMessage(), e); + throw e; } finally { // 5. 메모리 정리 (finally 블록에서 확실히 실행) if (nodes != null) { @@ -521,6 +523,9 @@ private void addOriginDestinationWalkConnections(Map> graph, Ma // 2. 출발지에서 인근 정류장으로 도보 연결 List startCandidates = findNearbyNodes(nodes, startTmp.getLatitude(), startTmp.getLongitude(), ORIGIN_DESTINATION_WALK_DISTANCE); + if (startCandidates.isEmpty()) { + throw new ApplicationException(NO_NEARBY_STATIONS); + } for (Node candidate : startCandidates) { Edge walkEdge = Edge.createEdge(-1L, startNode, candidate, DirectionType.WALK); graph.get(startNode.getId()).add(walkEdge); @@ -534,6 +539,9 @@ private void addOriginDestinationWalkConnections(Map> graph, Ma // 3. 인근 정류장에서 도착지로 도보 연결 List endCandidates = findNearbyNodes(nodes, endTmp.getLatitude(), endTmp.getLongitude(), ORIGIN_DESTINATION_WALK_DISTANCE); + if (endCandidates.isEmpty()) { + throw new ApplicationException(NO_NEARBY_STATIONS); + } for (Node candidate : endCandidates) { Edge walkEdge = Edge.createEdge(-2L, candidate, endNode, DirectionType.WALK); @@ -1005,6 +1013,10 @@ private String getRouteName(List pathEdges, int start, int end) { private Node findNearestNode(List nodes, double lat, double lon) { return nodes.stream() + .filter(node -> { + double distance = HaversineUtil.haversineKm(lat, lon, node.getLatitude(), node.getLongitude()) * 1000; // m 단위 + return distance <= ORIGIN_DESTINATION_WALK_DISTANCE; // 1000m 이내 + }) .min(Comparator.comparingDouble(n -> HaversineUtil.haversineKm(lat, lon, n.getLatitude(), n.getLongitude()))) .orElse(null); From be1a51f40b264ea258d6cf8528b0aa8be5eb04c2 Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 18:58:55 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[refactor]=20=EA=B3=B5=EA=B3=B5api=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9,=20=EB=8D=94=EB=AF=B8=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=95=A8=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../direction/service/BusInfoService.java | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/service/BusInfoService.java b/src/main/java/com/wayble/server/direction/service/BusInfoService.java index f40c4c4c..99fccdef 100644 --- a/src/main/java/com/wayble/server/direction/service/BusInfoService.java +++ b/src/main/java/com/wayble/server/direction/service/BusInfoService.java @@ -10,7 +10,6 @@ import com.wayble.server.direction.repository.transportation.RouteRepository; import com.wayble.server.direction.dto.response.TransportationResponseDto; -import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -31,11 +30,6 @@ public TransportationResponseDto.BusInfo getBusInfo(String stationName, Long bus List isLowFloor = new ArrayList<>(); Integer dispatchInterval = null; - // 나중에 서비스키 문제 해결되면 이 함수 호출 제거 - return createDummyBusInfo(stationName, busId, x, y); - - - /* boolean isShuttleBus = false; if (busId != null) { var routeName = routeRepository.findRouteNameById(busId); @@ -103,29 +97,7 @@ public TransportationResponseDto.BusInfo getBusInfo(String stationName, Long bus } return new TransportationResponseDto.BusInfo(isShuttleBus, isLowFloor, dispatchInterval); - */ - - } - - // 나중에 이 함수 제거 - private TransportationResponseDto.BusInfo createDummyBusInfo(String stationName, Long busId, Double x, Double y) { - - // 셔틀버스 여부 확인 (기존 로직 유지) - boolean isShuttleBus = false; - if (busId != null) { - var route = routeRepository.findById(busId); - isShuttleBus = route.isPresent() && route.get().getRouteName().contains("마포"); - } - - // 랜덤 더미 데이터 생성 - List isLowFloor = new ArrayList<>(); - isLowFloor.add(Math.random() < 0.7); - isLowFloor.add(Math.random() < 0.5); - Integer dispatchInterval = (int) (Math.random() * 15) + 1; - - - return new TransportationResponseDto.BusInfo(isShuttleBus, isLowFloor, dispatchInterval); } private OpenDataResponse fetchArrivals(String stationId, Long busId) { From 8a9cb5725e8440a6b4cbe9399fbcabd16c816523 Mon Sep 17 00:00:00 2001 From: hyoin Date: Thu, 28 Aug 2025 19:04:48 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[refactor]=C2=A0=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=97=90=EB=9F=AC=EC=BC=80=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wayble/server/direction/exception/DirectionErrorCase.java | 3 +-- .../wayble/server/direction/service/TransportationService.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java b/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java index e8594877..af8c4c5c 100644 --- a/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java +++ b/src/main/java/com/wayble/server/direction/exception/DirectionErrorCase.java @@ -13,8 +13,7 @@ public enum DirectionErrorCase implements ErrorCase { PATH_NOT_FOUND(400, 4003, "해당하는 경로를 찾을 수 없습니다."), DISTANCE_TOO_FAR(400, 4004, "거리가 30km 이상입니다."), - SYSTEM_ERROR(500, 4005, "길찾기 시스템에 오류가 발생했습니다."), - NO_NEARBY_STATIONS(400, 4006, "주변에 정류장이 없습니다."); + NO_NEARBY_STATIONS(400, 4005, "주변에 정류장이 없습니다."); private final Integer httpStatusCode; private final Integer errorCode; diff --git a/src/main/java/com/wayble/server/direction/service/TransportationService.java b/src/main/java/com/wayble/server/direction/service/TransportationService.java index 61a25e14..7016253b 100644 --- a/src/main/java/com/wayble/server/direction/service/TransportationService.java +++ b/src/main/java/com/wayble/server/direction/service/TransportationService.java @@ -27,7 +27,6 @@ import static com.wayble.server.direction.exception.DirectionErrorCase.PATH_NOT_FOUND; import static com.wayble.server.direction.exception.DirectionErrorCase.DISTANCE_TOO_FAR; import static com.wayble.server.direction.exception.DirectionErrorCase.NO_NEARBY_STATIONS; -import static com.wayble.server.direction.exception.DirectionErrorCase.SYSTEM_ERROR; @Slf4j @Service @RequiredArgsConstructor