From 254db5108aa00523ae122b4d400aabb77c800f61 Mon Sep 17 00:00:00 2001 From: bjkim Date: Mon, 13 Apr 2026 11:21:16 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20StorageStaticConfig=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EB=A1=9C=EC=BB=AC=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20HTTP?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=A4=ED=95=91,=20FileSystemStorageProvider=20U?= =?UTF-8?q?RL=20=ED=8F=AC=EB=A7=B7=20=EB=B3=80=EA=B2=BD,=20Kubernetes=20PV?= =?UTF-8?q?C=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80,=20MinIO=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=EC=9D=84=20=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kubernetes-aws.yaml | 19 ++++++++++ .../autoflow/config/StorageStaticConfig.java | 36 +++++++++++++++++++ .../controllers/PipelineUploadController.java | 2 +- .../StorageAttachmentController.java | 10 +++--- .../storage/FileSystemStorageProvider.java | 7 ++-- src/main/resources/application-aws.properties | 3 ++ .../resources/application-prod.properties | 3 ++ src/main/resources/application.properties | 2 +- 8 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 src/main/java/kr/re/etri/autoflow/config/StorageStaticConfig.java diff --git a/kubernetes-aws.yaml b/kubernetes-aws.yaml index 2f4d727..c74033e 100644 --- a/kubernetes-aws.yaml +++ b/kubernetes-aws.yaml @@ -40,6 +40,25 @@ spec: - name: S3_BUCKET_NAME # [수정 필요] Outpost 내 생성한 S3 버킷 명을 입력하세요. value: "autoflow-outpost-bucket" + volumeMounts: + - name: storage-volume + mountPath: /app/storage + volumes: + - name: storage-volume + persistentVolumeClaim: + claimName: autoflow-storage-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: autoflow-storage-pvc + namespace: autoflow +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi --- apiVersion: v1 kind: Service diff --git a/src/main/java/kr/re/etri/autoflow/config/StorageStaticConfig.java b/src/main/java/kr/re/etri/autoflow/config/StorageStaticConfig.java new file mode 100644 index 0000000..f29d0af --- /dev/null +++ b/src/main/java/kr/re/etri/autoflow/config/StorageStaticConfig.java @@ -0,0 +1,36 @@ +package kr.re.etri.autoflow.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.io.File; + +@Configuration +public class StorageStaticConfig implements WebMvcConfigurer { + + @Value("${storage.local.base-path:/app/storage}") + private String basePath; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // PVC 마운트 경로를 HTTP로 접근 가능하도록 설정 + // 예: /api/storage/mlpipeline/test.txt -> /app/storage/mlpipeline/test.txt 호출 + + String location = basePath; + if (!location.endsWith("/")) { + location += "/"; + } + + // Windows 환경 고려 (C:/... 형식일 경우 file:///C:/...) + if (!location.startsWith("/") && location.contains(":")) { + location = "file:///" + location; + } else { + location = "file:" + location; + } + + registry.addResourceHandler("/api/storage/**") + .addResourceLocations(location); + } +} diff --git a/src/main/java/kr/re/etri/autoflow/controllers/PipelineUploadController.java b/src/main/java/kr/re/etri/autoflow/controllers/PipelineUploadController.java index d63f289..44e205f 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/PipelineUploadController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/PipelineUploadController.java @@ -92,7 +92,7 @@ public class PipelineUploadController { response.put("pipeline", result); response.put("workflow", workflow); response.put("attachment", attachment); - response.put("minioUrl", minioUrl); + response.put("storageUrl", minioUrl); return ResponseEntity.ok(response); diff --git a/src/main/java/kr/re/etri/autoflow/controllers/StorageAttachmentController.java b/src/main/java/kr/re/etri/autoflow/controllers/StorageAttachmentController.java index 66576e6..85e811c 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/StorageAttachmentController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/StorageAttachmentController.java @@ -38,7 +38,7 @@ import java.util.*; @RequestMapping("/api/attachments") @RequiredArgsConstructor @Slf4j -@Tag(name = "첨부파일", description = "MinIO 첨부파일 관리 API") +@Tag(name = "첨부파일", description = "첨부파일 관리 API") public class StorageAttachmentController { private final StorageAttachmentService storageAttachmentService; @@ -87,7 +87,7 @@ public class StorageAttachmentController { return ResponseEntity.notFound().build(); } - @Operation(summary = "파일 다운로드", description = "MinIO에서 파일을 다운로드합니다.") + @Operation(summary = "파일 다운로드", description = "스토리지에서 파일을 다운로드합니다.") @GetMapping("/download") public ResponseEntity downloadFile(@RequestParam String objectName) { try { @@ -135,7 +135,7 @@ public class StorageAttachmentController { // } - @Operation(summary = "MinIO YAML 파일 읽기", description = "MinIO에서 YAML 파일을 다운로드하여 텍스트로 반환합니다.") + @Operation(summary = "YAML 파일 읽기", description = "스토리지에서 YAML 파일을 다운로드하여 텍스트로 반환합니다.") @GetMapping(value = "/readYamlText", produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity readYamlTextFromMinio(@RequestParam String objectName) { try { @@ -169,7 +169,7 @@ public class StorageAttachmentController { Map response = new HashMap<>(); response.put("attachment", saved); - response.put("minioUrl", storageAttachmentService.getFileUrl(saved.getStoragePath())); + response.put("storageUrl", storageAttachmentService.getFileUrl(saved.getStoragePath())); return ResponseEntity.ok(response); @@ -199,7 +199,7 @@ public class StorageAttachmentController { Map response = new HashMap<>(); response.put("attachment", updated); - response.put("minioUrl", storageAttachmentService.getFileUrl(updated.getStoragePath())); + response.put("storageUrl", storageAttachmentService.getFileUrl(updated.getStoragePath())); return ResponseEntity.ok(response); diff --git a/src/main/java/kr/re/etri/autoflow/service/storage/FileSystemStorageProvider.java b/src/main/java/kr/re/etri/autoflow/service/storage/FileSystemStorageProvider.java index 4bf6a3c..791f3ee 100644 --- a/src/main/java/kr/re/etri/autoflow/service/storage/FileSystemStorageProvider.java +++ b/src/main/java/kr/re/etri/autoflow/service/storage/FileSystemStorageProvider.java @@ -97,9 +97,8 @@ public class FileSystemStorageProvider implements StorageProvider { @Override public String getFileUrl(String bucketName, String objectName, String type) { - // 로컬 파일 경로를 URL로 반환하거나 상대 경로로 반환 - // 프론트엔드에서 접근 가능한 경로여야 할 경우 추가적인 서블릿 설정이 필요할 수 있음 - String targetDir = getTargetDir(bucketName); - return Paths.get(targetDir, objectName).toAbsolutePath().toUri().toString(); + String bucket = (bucketName == null || bucketName.isEmpty()) ? defaultBucket : bucketName; + // /api/storage/bucket/object_name 형식으로 반환하여 프론트엔드에서 편리하게 접근 가능하게 함 + return String.format("/api/storage/%s/%s", bucket, objectName); } } diff --git a/src/main/resources/application-aws.properties b/src/main/resources/application-aws.properties index f1b9b9d..bce0d70 100644 --- a/src/main/resources/application-aws.properties +++ b/src/main/resources/application-aws.properties @@ -38,3 +38,6 @@ springdoc.swagger-ui.disable-swagger-default-url=true # Multipart limit spring.servlet.multipart.max-file-size=500MB spring.servlet.multipart.max-request-size=500MB + +# ALB / Forwarded Headers +server.forward-headers-strategy=native diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index f9e724e..fb59cf1 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -7,3 +7,6 @@ springdoc.swagger-ui.doc-expansion=none springdoc.swagger-ui.disable-swagger-default-url=true spring.jpa.hibernate.ddl-auto=none spring.sql.init.mode=never + +# ALB / Forwarded Headers +server.forward-headers-strategy=native diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6f51392..98e6c66 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -54,7 +54,7 @@ springdoc.swagger-ui.tags-sorter=alpha storage.provider=minio # Local FileSystem ?? -storage.local.base-path=./storage +storage.local.base-path=/app/storage storage.local.default-bucket=mlpipeline # MinIO ??