From 94ea935317f6aeb328cbe76cc664539960dffa1e Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Mon, 1 Dec 2025 14:24:41 +0900 Subject: [PATCH] =?UTF-8?q?List=20=EC=B0=B8=EC=A1=B0=20=ED=95=B4?= =?UTF-8?q?=EC=A0=9C=20=EC=A0=81=EC=9A=A9=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InferenceResultApiController.java | 358 +++++++++--------- .../ChangeDetectionRepositoryImpl.java | 42 +- 2 files changed, 206 insertions(+), 194 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java index 5b568525..f9f0096b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java @@ -40,128 +40,129 @@ public class InferenceResultApiController { @Operation(summary = "추론관리 분석결과 목록 조회", description = "분석상태, 제목으로 분석결과를 조회 합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Page.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/list") public ApiResponseDto> getInferenceResultList( - @Parameter(description = "분석상태", example = "0002") @RequestParam(required = false) - String statCode, - @Parameter(description = "제목", example = "변화탐지") @RequestParam(required = false) String title, - @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") - int page, - @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") - int size, - @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") - @RequestParam(required = false) - String sort) { + @Parameter(description = "분석상태", example = "0002") @RequestParam(required = false) + String statCode, + @Parameter(description = "제목", example = "변화탐지") @RequestParam(required = false) String title, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size, + @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") + @RequestParam(required = false) + String sort) { InferenceResultDto.SearchReq searchReq = - new InferenceResultDto.SearchReq(statCode, title, page, size, sort); + new InferenceResultDto.SearchReq(statCode, title, page, size, sort); Page analResList = - inferenceResultService.getInferenceResultList(searchReq); + inferenceResultService.getInferenceResultList(searchReq); return ApiResponseDto.ok(analResList); } @Operation(summary = "추론관리 분석결과 요약정보", description = "분석결과 요약정보를 조회합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = InferenceResultDto.AnalResSummary.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = InferenceResultDto.AnalResSummary.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/summary/{id}") public ApiResponseDto getInferenceResultSummary( - @Parameter(description = "목록 id", example = "1") @PathVariable Long id) { + @Parameter(description = "목록 id", example = "1") @PathVariable Long id) { return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id)); } @Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = InferenceResultDto.Detail.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = InferenceResultDto.Detail.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/detail/{id}") public ApiResponseDto getInferenceDetail( - @Parameter(description = "목록 id", example = "1") @PathVariable Long id) { + @Parameter(description = "목록 id", example = "1") @PathVariable Long id) { return ApiResponseDto.ok(inferenceResultService.getDetail(id)); } @Operation(summary = "추론관리 분석결과 상세 목록", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Page.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/geom/{id}") public ApiResponseDto> getInferenceResultGeomList( - @Parameter(description = "분석결과 id", example = "1") @PathVariable Long id, - @Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false) - String targetClass, - @Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false) - String compareClass, - @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) - List mapSheetNum, - @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") - int page, - @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") - int size, - @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") - @RequestParam(required = false) - String sort) { + @Parameter(description = "분석결과 id", example = "1") @PathVariable Long id, + @Parameter(description = "기준년도 분류", example = "land") @RequestParam(required = false) + String targetClass, + @Parameter(description = "비교년도 분류", example = "waste") @RequestParam(required = false) + String compareClass, + @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) + List mapSheetNum, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size, + @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") + @RequestParam(required = false) + String sort) { InferenceResultDto.SearchGeoReq searchGeoReq = - new InferenceResultDto.SearchGeoReq( - targetClass, compareClass, mapSheetNum, page, size, sort); + new InferenceResultDto.SearchGeoReq( + targetClass, compareClass, mapSheetNum, page, size, sort); Page geomList = - inferenceResultService.getInferenceResultGeomList(id, searchGeoReq); + inferenceResultService.getInferenceResultGeomList(id, searchGeoReq); return ApiResponseDto.ok(geomList); } // @Operation(summary = "학습모델 결과 처리", description = "실제 학습모델 GeoJSON 파일을 처리하여 데이터베이스에 저장합니다.") -// @ApiResponses( -// value = { -// @ApiResponse( -// responseCode = "200", -// description = "처리 성공", -// content = -// @Content( -// mediaType = "application/json", -// schema = -// @Schema(implementation = LearningModelResultDto.ProcessResponse.class))), -// @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), -// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) -// }) -// @PostMapping("/learning-model/process") + // @ApiResponses( + // value = { + // @ApiResponse( + // responseCode = "200", + // description = "처리 성공", + // content = + // @Content( + // mediaType = "application/json", + // schema = + // @Schema(implementation = + // LearningModelResultDto.ProcessResponse.class))), + // @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), + // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + // }) + // @PostMapping("/learning-model/process") public ApiResponseDto processLearningModelResult( - @RequestBody LearningModelResultDto.ProcessRequest request) { + @RequestBody LearningModelResultDto.ProcessRequest request) { try { logger.info("Processing learning model result file: {}", request.getFilePath()); @@ -169,53 +170,55 @@ public class InferenceResultApiController { int processedFeatures = learningModelResultProcessor.processLearningModelResult(filePath); LearningModelResultDto.ProcessResponse response = - LearningModelResultDto.ProcessResponse.builder() - .success(true) - .message("학습모델 결과 처리가 완료되었습니다.") - .processedFeatures(processedFeatures) - .filePath(request.getFilePath()) - .build(); + LearningModelResultDto.ProcessResponse.builder() + .success(true) + .message("학습모델 결과 처리가 완료되었습니다.") + .processedFeatures(processedFeatures) + .filePath(request.getFilePath()) + .build(); logger.info( - "Successfully processed {} features from file: {}", - processedFeatures, - request.getFilePath()); + "Successfully processed {} features from file: {}", + processedFeatures, + request.getFilePath()); return ApiResponseDto.ok(response); } catch (Exception e) { logger.error("Failed to process learning model result: {}", request.getFilePath(), e); LearningModelResultDto.ProcessResponse response = - LearningModelResultDto.ProcessResponse.builder() - .success(false) - .message("학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) - .processedFeatures(0) - .filePath(request.getFilePath()) - .build(); + LearningModelResultDto.ProcessResponse.builder() + .success(false) + .message("학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) + .processedFeatures(0) + .filePath(request.getFilePath()) + .build(); return ApiResponseDto.ok(response); } } - // @Operation(summary = "학습모델 결과 일괄 처리", description = "여러 학습모델 GeoJSON 파일을 일괄 처리하여 데이터베이스에 저장합니다.") -// @ApiResponses( -// value = { -// @ApiResponse( -// responseCode = "200", -// description = "처리 성공", -// content = -// @Content( -// mediaType = "application/json", -// schema = -// @Schema( -// implementation = LearningModelResultDto.BatchProcessResponse.class))), -// @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), -// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) -// }) -// @PostMapping("/learning-model/process-batch") + // @Operation(summary = "학습모델 결과 일괄 처리", description = "여러 학습모델 GeoJSON 파일을 일괄 처리하여 데이터베이스에 + // 저장합니다.") + // @ApiResponses( + // value = { + // @ApiResponse( + // responseCode = "200", + // description = "처리 성공", + // content = + // @Content( + // mediaType = "application/json", + // schema = + // @Schema( + // implementation = + // LearningModelResultDto.BatchProcessResponse.class))), + // @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), + // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + // }) + // @PostMapping("/learning-model/process-batch") public ApiResponseDto - processBatchLearningModelResults( - @RequestBody LearningModelResultDto.BatchProcessRequest request) { + processBatchLearningModelResults( + @RequestBody LearningModelResultDto.BatchProcessRequest request) { try { logger.info("Processing {} learning model result files", request.getFilePaths().size()); @@ -225,64 +228,65 @@ public class InferenceResultApiController { } int totalProcessedFeatures = - learningModelResultProcessor.processMultipleLearningModelResults(filePaths); + learningModelResultProcessor.processMultipleLearningModelResults(filePaths); LearningModelResultDto.BatchProcessResponse response = - LearningModelResultDto.BatchProcessResponse.builder() - .success(true) - .message("일괄 학습모델 결과 처리가 완료되었습니다.") - .totalProcessedFeatures(totalProcessedFeatures) - .processedFileCount(request.getFilePaths().size()) - .filePaths(request.getFilePaths()) - .build(); + LearningModelResultDto.BatchProcessResponse.builder() + .success(true) + .message("일괄 학습모델 결과 처리가 완료되었습니다.") + .totalProcessedFeatures(totalProcessedFeatures) + .processedFileCount(request.getFilePaths().size()) + .filePaths(request.getFilePaths()) + .build(); logger.info( - "Successfully processed {} features from {} files", - totalProcessedFeatures, - request.getFilePaths().size()); + "Successfully processed {} features from {} files", + totalProcessedFeatures, + request.getFilePaths().size()); return ApiResponseDto.ok(response); } catch (Exception e) { logger.error("Failed to process batch learning model results", e); LearningModelResultDto.BatchProcessResponse response = - LearningModelResultDto.BatchProcessResponse.builder() - .success(false) - .message("일괄 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) - .totalProcessedFeatures(0) - .processedFileCount(0) - .filePaths(request.getFilePaths()) - .build(); + LearningModelResultDto.BatchProcessResponse.builder() + .success(false) + .message("일괄 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) + .totalProcessedFeatures(0) + .processedFileCount(0) + .filePaths(request.getFilePaths()) + .build(); return ApiResponseDto.ok(response); } } // @Operation(summary = "기본 학습모델 파일 처리", description = "미리 준비된 학습모델 파일을 처리합니다.") -// @ApiResponses( -// value = { -// @ApiResponse( -// responseCode = "200", -// description = "처리 성공", -// content = -// @Content( -// mediaType = "application/json", -// schema = -// @Schema( -// implementation = LearningModelResultDto.BatchProcessResponse.class))), -// @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) -// }) -// @PostMapping("/learning-model/process-default") + // @ApiResponses( + // value = { + // @ApiResponse( + // responseCode = "200", + // description = "처리 성공", + // content = + // @Content( + // mediaType = "application/json", + // schema = + // @Schema( + // implementation = + // LearningModelResultDto.BatchProcessResponse.class))), + // @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + // }) + // @PostMapping("/learning-model/process-default") public ApiResponseDto - processDefaultLearningModelResults() { + processDefaultLearningModelResults() { try { logger.info("Processing default learning model result files"); // Process the two default learning model files from upload directory List defaultFilePaths = - List.of( - "/Users/deniallee/geojson/upload/캠코_2021_2022_35813023.geojson", - "/Users/deniallee/geojson/upload/캠코_2023_2024_35810049.geojson"); + List.of( + "/Users/deniallee/geojson/upload/캠코_2021_2022_35813023.geojson", + "/Users/deniallee/geojson/upload/캠코_2023_2024_35810049.geojson"); List filePaths = new ArrayList<>(); for (String filePath : defaultFilePaths) { @@ -290,34 +294,34 @@ public class InferenceResultApiController { } int totalProcessedFeatures = - learningModelResultProcessor.processMultipleLearningModelResults(filePaths); + learningModelResultProcessor.processMultipleLearningModelResults(filePaths); LearningModelResultDto.BatchProcessResponse response = - LearningModelResultDto.BatchProcessResponse.builder() - .success(true) - .message("기본 학습모델 결과 파일 처리가 완료되었습니다.") - .totalProcessedFeatures(totalProcessedFeatures) - .processedFileCount(defaultFilePaths.size()) - .filePaths(defaultFilePaths) - .build(); + LearningModelResultDto.BatchProcessResponse.builder() + .success(true) + .message("기본 학습모델 결과 파일 처리가 완료되었습니다.") + .totalProcessedFeatures(totalProcessedFeatures) + .processedFileCount(defaultFilePaths.size()) + .filePaths(defaultFilePaths) + .build(); logger.info( - "Successfully processed {} features from {} default files", - totalProcessedFeatures, - defaultFilePaths.size()); + "Successfully processed {} features from {} default files", + totalProcessedFeatures, + defaultFilePaths.size()); return ApiResponseDto.ok(response); } catch (Exception e) { logger.error("Failed to process default learning model results", e); LearningModelResultDto.BatchProcessResponse response = - LearningModelResultDto.BatchProcessResponse.builder() - .success(false) - .message("기본 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) - .totalProcessedFeatures(0) - .processedFileCount(0) - .filePaths(List.of()) - .build(); + LearningModelResultDto.BatchProcessResponse.builder() + .success(false) + .message("기본 학습모델 결과 처리 중 오류가 발생했습니다: " + e.getMessage()) + .totalProcessedFeatures(0) + .processedFileCount(0) + .filePaths(List.of()) + .build(); return ApiResponseDto.ok(response); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java index a7e48881..e66e64c9 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java @@ -171,6 +171,9 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport ChangeDetectionDto.PolygonFeatureList polygonList = new ChangeDetectionDto.PolygonFeatureList(); polygonList.setType("FeatureCollection"); polygonList.setFeatures(result); + + list.clear(); // List 사용 참조 해제 + return polygonList; } @@ -194,25 +197,30 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport .fetch(); GeoJsonReader reader = new GeoJsonReader(); - return list.stream() - .map( - tuple -> { - String geojson = tuple.get(0, String.class); - Geometry geom; - try { - geom = reader.read(geojson); - } catch (Exception ex) { - throw new RuntimeException("GeoJSON -> Geometry 변환 실패", ex); - } + List result = + list.stream() + .map( + tuple -> { + String geojson = tuple.get(0, String.class); + Geometry geom; + try { + geom = reader.read(geojson); + } catch (Exception ex) { + throw new RuntimeException("GeoJSON -> Geometry 변환 실패", ex); + } - Long geoUid = tuple.get(mapSheetAnalDataGeomEntity.id).longValue(); - String classCd = - tuple.get(mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase()).toString(); + Long geoUid = tuple.get(mapSheetAnalDataGeomEntity.id).longValue(); + String classCd = + tuple.get(mapSheetAnalDataGeomEntity.classAfterCd.toUpperCase()).toString(); - return new ChangeDetectionDto.PointFeature( - "Feature", geom, new ChangeDetectionDto.PointProperties(geoUid, classCd)); - }) - .collect(Collectors.toList()); + return new ChangeDetectionDto.PointFeature( + "Feature", geom, new ChangeDetectionDto.PointProperties(geoUid, classCd)); + }) + .collect(Collectors.toList()); + + list.clear(); // List 사용 참조 해제 + + return result; } @Override