From ce87fbfc136d75f91c9563039118396edd4fc140 Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 31 Dec 2025 11:07:21 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=B4=EB=85=B8=ED=8E=A8=20=EB=AA=A9?= =?UTF-8?q?=EC=97=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Innopam/InnopamApiController.java | 23 +++-- .../Innopam/service/DetectMastService.java | 89 ++++++++++++------- 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java index 13bd6456..f3c835da 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java @@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch; +import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto; import com.kamco.cd.kamcoback.Innopam.service.DetectMastService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -126,20 +127,26 @@ public class InnopamApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @GetMapping("/pnu/{cprsBfYr}/{cprsAfYr}/{dtctSno}") - public void selectPnuList( + public List selectPnuList( @PathVariable String cprsBfYr, @PathVariable String cprsAfYr, @PathVariable String dtctSno) { DetectMastSearch detectMastSearch = new DetectMastSearch(); detectMastSearch.setCprsAdYr(cprsAfYr); detectMastSearch.setCprsBfYr(cprsBfYr); detectMastSearch.setDtctSno(Integer.parseInt(dtctSno)); - detectMastService.findPnuData(detectMastSearch); + return detectMastService.findPnuData(detectMastSearch); } - /** - * 탐지객체 PNU 단건 조회 - * - * @param detectMast - */ @GetMapping("/pnu/{cprsBfYr}/{cprsAfYr}/{dtctSno}/{featureId}") - public void selectPnuDetail(@RequestBody DetectMastDto detectMast) {} + public FeaturePnuDto selectPnuDetail( + @PathVariable String cprsBfYr, + @PathVariable String cprsAfYr, + @PathVariable String dtctSno, + @PathVariable String featureId) { + DetectMastSearch detectMastSearch = new DetectMastSearch(); + detectMastSearch.setCprsAdYr(cprsAfYr); + detectMastSearch.setCprsBfYr(cprsBfYr); + detectMastSearch.setDtctSno(Integer.parseInt(dtctSno)); + detectMastSearch.setFeatureId(featureId); + return detectMastService.findPnuDataDetail(detectMastSearch); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java index 6924fa90..1adf7774 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java @@ -1,17 +1,23 @@ package com.kamco.cd.kamcoback.Innopam.service; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto; import com.kamco.cd.kamcoback.Innopam.postgres.core.DetectMastCoreService; -import java.io.File; -import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor public class DetectMastService { + private final JsonFactory factory = new JsonFactory(); private final DetectMastCoreService detectMastCoreService; @Transactional @@ -36,11 +43,15 @@ public class DetectMastService { return detectMastCoreService.selectDetectMast(id); } - public void findPnuData(DetectMastSearch detectMast) { - // String pathNm = detectMastCoreService.findPnuData(detectMast); - String pathNm = "/Users/bokmin/detect/result/2023_2024/4"; - File geoJson = new File(pathNm); - List list = this.extractFeaturePnus(geoJson); + public List findPnuData(DetectMastSearch detectMast) { + String pathNm = detectMastCoreService.findPnuData(detectMast); + return this.extractFeaturePnusFast(pathNm); + } + + public FeaturePnuDto findPnuDataDetail(DetectMastSearch detectMast) { + String pathNm = detectMastCoreService.findPnuData(detectMast); + List pnu = this.extractFeaturePnusFast(pathNm); + return pnu.get(0); } private String randomPnu() { @@ -54,37 +65,51 @@ public class DetectMastService { return lawCode + sanFlag + bon + bu; } - private List extractFeaturePnus(File geoJsonFile) { + public List extractFeaturePnusFast(String dirPath) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode root = null; - try { - mapper.readTree(geoJsonFile); - } catch (IOException e) { - throw new RuntimeException(e); + Path basePath = Paths.get(dirPath); + if (!Files.isDirectory(basePath)) { + System.err.println("유효하지 않은 디렉터리: " + dirPath); + return List.of(); } - JsonNode features = root.get("features"); - List result = new ArrayList<>(); + // 병렬로 모으기 위한 thread-safe 컬렉션 + Queue out = new ConcurrentLinkedQueue<>(); - if (features != null && features.isArray()) { - for (JsonNode feature : features) { - JsonNode properties = feature.get("properties"); - if (properties == null) { - continue; - } + try (Stream stream = Files.walk(basePath)) { + stream + .filter(Files::isRegularFile) + .filter(p -> p.toString().toLowerCase().endsWith(".geojson")) + .parallel() // 병렬 + .forEach( + p -> { + try (InputStream in = Files.newInputStream(p); + JsonParser parser = factory.createParser(in)) { - String polygonId = properties.path("polygon_id").asText(null); - if (polygonId == null) { - continue; - } + // "polygon_id" 키를 만나면 다음 토큰 값을 읽어서 저장 + while (parser.nextToken() != null) { + if (parser.currentToken() == JsonToken.FIELD_NAME + && "polygon_id".equals(parser.getCurrentName())) { - String pnu = this.randomPnu(); + JsonToken next = parser.nextToken(); // 값으로 이동 + if (next == JsonToken.VALUE_STRING) { + String polygonId = parser.getValueAsString(); + out.add(new FeaturePnuDto(polygonId, this.randomPnu())); + } + } + } - result.add(new FeaturePnuDto(polygonId, pnu)); - } + } catch (Exception e) { + // 파일별 에러 로그는 최소화 + System.err.println("파싱 실패: " + p.getFileName() + " / " + e.getMessage()); + } + }); + + } catch (Exception e) { + System.err.println("디렉터리 탐색 실패: " + e.getMessage()); + return List.of(); } - return result; + return new ArrayList<>(out); } }