From 219e17e8ba2194d39086aa2520141b10a57b4820 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Tue, 7 Apr 2026 19:35:45 +0900 Subject: [PATCH] =?UTF-8?q?daniel=20file=20manager=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filemanager/FileManagerApiController.java | 36 ++-- .../filemanager/dto/FileManagerDto.java | 10 +- .../service/FileManagerService.java | 180 +++++++++++++++--- 3 files changed, 174 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java b/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java index e85dced..8be2994 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java +++ b/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java @@ -80,29 +80,29 @@ public class FileManagerApiController { name = "단일 파일 삭제", value = """ - { - "filePaths": ["/data/request/old_file.zip"], - "recursive": false - } - """), + { + "filePaths": ["/data/request/old_file.zip"], + "recursive": false + } + """), @ExampleObject( name = "여러 파일 삭제", value = """ - { - "filePaths": ["/data/file1.txt", "/data/file2.txt"], - "recursive": false - } - """), + { + "filePaths": ["/data/file1.txt", "/data/file2.txt"], + "recursive": false + } + """), @ExampleObject( name = "디렉토리 전체 삭제", value = """ - { - "filePaths": ["/data/old_folder"], - "recursive": true - } - """) + { + "filePaths": ["/data/old_folder"], + "recursive": true + } + """) }))) @ApiResponses( value = { @@ -144,7 +144,7 @@ public class FileManagerApiController { }) @GetMapping("/model-path/{modelUuid}") public ApiResponseDto getModelFilePath( - @Parameter(description = "모델 UUID", example = "123e4567-e89b-12d3-a456-426614174000") + @Parameter(description = "모델 UUID", example = "df284755-c0b7-4070-bfee-ef554e8d0fe4") @PathVariable UUID modelUuid) { @@ -170,7 +170,7 @@ public class FileManagerApiController { }) @GetMapping("/dataset-path/{datasetUuid}") public ApiResponseDto getDatasetFilePath( - @Parameter(description = "데이터셋 UUID", example = "123e4567-e89b-12d3-a456-426614174001") + @Parameter(description = "데이터셋 UUID", example = "037b09a0-b315-4e2e-b88d-b9011f9eaa15") @PathVariable UUID datasetUuid) { @@ -198,7 +198,7 @@ public class FileManagerApiController { public ApiResponseDto checkDirectoryCapacity( @Parameter( description = "디렉토리 경로", - example = "/home/kcomu/data/request/123e4567-e89b-12d3-a456-426614174001") + example = "/home/kcomu/data/request/037b09a0-b315-4e2e-b88d-b9011f9eaa15") @RequestParam String directoryPath) { diff --git a/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java b/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java index 607b171..0231640 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java +++ b/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java @@ -138,17 +138,17 @@ public class FileManagerDto { @AllArgsConstructor @Schema(description = "모델 파일 경로 정보 응답") public static class ModelFilePathRes { - @Schema(description = "모델 UUID", example = "123e4567-e89b-12d3-a456-426614174000") + @Schema(description = "모델 UUID", example = "df284755-c0b7-4070-bfee-ef554e8d0fe4") private String modelUuid; @Schema( description = "요청 경로 (심볼릭 링크 디렉토리)", - example = "/home/kcomu/data/tmp/123e4567-e89b-12d3-a456-426614174000") + example = "/home/kcomu/data/tmp/AE366F3076504FACBF12106986202AB5") private String requestPath; @Schema( description = "응답 경로 (모델 결과 저장)", - example = "/home/kcomu/data/response/123e4567-e89b-12d3-a456-426614174000") + example = "/home/kcomu/data/response/df284755-c0b7-4070-bfee-ef554e8d0fe4") private String responsePath; @Schema(description = "요청 경로 파일 목록") @@ -164,12 +164,12 @@ public class FileManagerDto { @AllArgsConstructor @Schema(description = "데이터셋 파일 경로 정보 응답") public static class DatasetFilePathRes { - @Schema(description = "데이터셋 UUID", example = "123e4567-e89b-12d3-a456-426614174001") + @Schema(description = "데이터셋 UUID", example = "037b09a0-b315-4e2e-b88d-b9011f9eaa15") private String datasetUuid; @Schema( description = "데이터셋 경로", - example = "/home/kcomu/data/request/123e4567-e89b-12d3-a456-426614174001") + example = "/home/kcomu/data/request/037b09a0-b315-4e2e-b88d-b9011f9eaa15") private String datasetPath; @Schema(description = "데이터셋 파일 목록") diff --git a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java index 708933b..f20bf93 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java +++ b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java @@ -57,15 +57,38 @@ public class FileManagerService { boolean recursive = request.getRecursive() != null && request.getRecursive(); - validatePath(targetPath); + // 경로 검증은 수행하되, 예외를 throw하지 않고 빈 데이터 반환 + try { + validatePath(targetPath); + } catch (IllegalArgumentException e) { + log.debug("유효하지 않은 경로: {}", targetPath); + return FileManagerDto.ListFilesRes.builder() + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); + } Path directory = Paths.get(targetPath); if (!Files.exists(directory)) { - throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + targetPath); + log.debug("디렉토리가 존재하지 않습니다: {}", targetPath); + return FileManagerDto.ListFilesRes.builder() + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } if (!Files.isDirectory(directory)) { - throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + targetPath); + log.debug("디렉토리 경로가 아닙니다: {}", targetPath); + return FileManagerDto.ListFilesRes.builder() + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } List files = new ArrayList<>(); @@ -106,8 +129,13 @@ public class FileManagerService { } } catch (IOException e) { - log.error("파일 목록 조회 중 오류 발생: {}", targetPath, e); - throw new RuntimeException("파일 목록 조회에 실패했습니다: " + e.getMessage()); + log.debug("파일 목록 조회 중 오류 발생: {}", targetPath, e); + return FileManagerDto.ListFilesRes.builder() + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } return FileManagerDto.ListFilesRes.builder() @@ -132,11 +160,18 @@ public class FileManagerService { for (String filePath : request.getFilePaths()) { try { - validatePath(filePath); + try { + validatePath(filePath); + } catch (IllegalArgumentException e) { + log.debug("유효하지 않은 경로: {}", filePath); + failedFiles.add(filePath + " (유효하지 않은 경로)"); + continue; + } + Path path = Paths.get(filePath); if (!Files.exists(path)) { - log.warn("삭제하려는 파일이 존재하지 않습니다: {}", filePath); + log.debug("삭제하려는 파일이 존재하지 않습니다: {}", filePath); failedFiles.add(filePath + " (파일이 존재하지 않음)"); continue; } @@ -164,7 +199,7 @@ public class FileManagerService { log.info("파일 삭제 성공: {}", filePath); } catch (Exception e) { - log.error("파일 삭제 실패: {}", filePath, e); + log.debug("파일 삭제 실패: {}", filePath, e); failedFiles.add(filePath + " (" + e.getMessage() + ")"); } } @@ -259,10 +294,18 @@ public class FileManagerService { */ public FileManagerDto.ModelFilePathRes getModelFilePath(UUID modelUuid) { // tb_model_master 테이블에서 모델 조회 - ModelMasterEntity model = - modelMngRepository - .findByUuid(modelUuid) - .orElseThrow(() -> new IllegalArgumentException("모델을 찾을 수 없습니다: " + modelUuid)); + ModelMasterEntity model = modelMngRepository.findByUuid(modelUuid).orElse(null); + + // 모델이 존재하지 않으면 빈 데이터 반환 + if (model == null) { + return FileManagerDto.ModelFilePathRes.builder() + .modelUuid(modelUuid.toString()) + .requestPath(null) + .responsePath(null) + .requestFiles(new ArrayList<>()) + .responseFiles(new ArrayList<>()) + .build(); + } // request_path: tb_model_master.request_path 컬럼 값 사용 // request_path 컬럼에는 'AE366F3076504FACBF12106986202AB5' 형태의 값이 저장되어 있음 @@ -300,10 +343,16 @@ public class FileManagerService { */ public FileManagerDto.DatasetFilePathRes getDatasetFilePath(UUID datasetUuid) { // tb_dataset 테이블에서 데이터셋 조회 - DatasetEntity dataset = - datasetRepository - .findByUuid(datasetUuid) - .orElseThrow(() -> new IllegalArgumentException("데이터셋을 찾을 수 없습니다: " + datasetUuid)); + DatasetEntity dataset = datasetRepository.findByUuid(datasetUuid).orElse(null); + + // 데이터셋이 존재하지 않으면 빈 데이터 반환 + if (dataset == null) { + return FileManagerDto.DatasetFilePathRes.builder() + .datasetUuid(datasetUuid.toString()) + .datasetPath(null) + .files(new ArrayList<>()) + .build(); + } // dataset_path 컬럼이 있으면 사용, 없으면 request_dir + uuid 사용 String datasetPath = dataset.getDatasetPath(); @@ -328,15 +377,41 @@ public class FileManagerService { * @return 디렉토리 용량 정보 */ public FileManagerDto.DirectoryCapacityRes checkDirectoryCapacity(String directoryPath) { - validatePath(directoryPath); + // 경로 검증은 수행하되, 예외를 throw하지 않고 빈 데이터 반환 + try { + validatePath(directoryPath); + } catch (IllegalArgumentException e) { + log.debug("유효하지 않은 경로: {}", directoryPath); + return FileManagerDto.DirectoryCapacityRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); + } Path directory = Paths.get(directoryPath); if (!Files.exists(directory)) { - throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + directoryPath); + log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath); + return FileManagerDto.DirectoryCapacityRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } if (!Files.isDirectory(directory)) { - throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + directoryPath); + log.debug("디렉토리 경로가 아닙니다: {}", directoryPath); + return FileManagerDto.DirectoryCapacityRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } final long[] totalSize = {0}; @@ -363,8 +438,14 @@ public class FileManagerService { } }); } catch (IOException e) { - log.error("디렉토리 용량 체크 중 오류 발생: {}", directoryPath, e); - throw new RuntimeException("디렉토리 용량 체크에 실패했습니다: " + e.getMessage()); + log.debug("디렉토리 용량 체크 중 오류 발생: {}", directoryPath, e); + return FileManagerDto.DirectoryCapacityRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } return FileManagerDto.DirectoryCapacityRes.builder() @@ -454,19 +535,19 @@ public class FileManagerService { Path directory = Paths.get(directoryPath); if (!Files.exists(directory)) { - log.warn("디렉토리가 존재하지 않습니다: {}", directoryPath); + log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath); return files; } if (!Files.isDirectory(directory)) { - log.warn("디렉토리 경로가 아닙니다: {}", directoryPath); + log.debug("디렉토리 경로가 아닙니다: {}", directoryPath); return files; } try (Stream stream = Files.list(directory)) { stream.forEach(path -> files.add(createFileInfo(path))); } catch (IOException e) { - log.error("파일 목록 조회 중 오류 발생: {}", directoryPath, e); + log.debug("파일 목록 조회 중 오류 발생: {}", directoryPath, e); } return files; @@ -496,11 +577,39 @@ public class FileManagerService { Path directory = Paths.get(directoryPath); if (!Files.exists(directory)) { - throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + directoryPath); + log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath); + return FileManagerDto.StorageSpaceRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } if (!Files.isDirectory(directory)) { - throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + directoryPath); + log.debug("디렉토리 경로가 아닙니다: {}", directoryPath); + return FileManagerDto.StorageSpaceRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } // 디렉토리 사용량 계산 (재귀적으로 모든 파일 크기 합산) @@ -528,8 +637,21 @@ public class FileManagerService { } }); } catch (IOException e) { - log.error("디렉토리 용량 계산 중 오류 발생: {}", directoryPath, e); - throw new RuntimeException("디렉토리 용량 계산에 실패했습니다: " + e.getMessage()); + log.debug("디렉토리 용량 계산 중 오류 발생: {}", directoryPath, e); + return FileManagerDto.StorageSpaceRes.builder() + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } // 디스크 공간 정보 조회 (FileStore 사용) @@ -550,7 +672,7 @@ public class FileManagerService { usagePercentage = (usedDiskSpace * 100.0) / totalDiskSpace; } } catch (IOException e) { - log.error("디스크 공간 정보 조회 중 오류 발생: {}", directoryPath, e); + log.debug("디스크 공간 정보 조회 중 오류 발생: {}", directoryPath, e); // 디스크 정보 조회 실패 시에도 디렉토리 용량은 반환 }