14 Commits

Author SHA1 Message Date
dean
6cc9b54ba9 welcome 2026-04-01 08:55:17 +09:00
dean
50ad05b53b welcome 2026-03-31 17:44:08 +09:00
dean
822dbb252f test 2026-03-31 17:15:45 +09:00
dean
5e04df73af test 2026-03-31 17:15:29 +09:00
650b1695f0 Merge pull request '미사용 목록 주석 추가, 학습데이터 삭제 테스트' (#178) from feat/training_260324 into develop
Reviewed-on: #178
2026-03-27 18:02:34 +09:00
960e4215e0 미사용 목록 주석 추가, 학습데이터 삭제 테스트 2026-03-27 18:02:13 +09:00
08a220db4d Merge pull request '미사용 목록 주석 추가, 납품데이터 폴더 벨리데이션 위치 옮김' (#177) from feat/training_260324 into develop
Reviewed-on: #177
2026-03-27 17:04:25 +09:00
a9b49faa6c 미사용 목록 주석 추가, 납품데이터 폴더 벨리데이션 위치 옮김 2026-03-27 17:03:52 +09:00
b760e9874c Merge pull request '납품데이터셋 업로드 geojson 파일 수정' (#176) from feat/training_260324 into develop
Reviewed-on: #176
2026-03-27 10:56:57 +09:00
8698bf61d1 납품데이터셋 업로드 geojson 파일 수정 2026-03-27 10:56:38 +09:00
680e137284 Merge pull request '납품데이터셋 업로드 geojson 파일 수정' (#175) from feat/training_260324 into develop
Reviewed-on: #175
2026-03-27 10:18:15 +09:00
f4a81a34d6 납품데이터셋 업로드 geojson 파일 수정 2026-03-27 10:17:58 +09:00
479ad710e0 Merge pull request '납품데이터셋 업로드 geojson 파일 수정' (#174) from feat/training_260324 into develop
Reviewed-on: #174
2026-03-27 10:15:32 +09:00
3cb9840248 납품데이터셋 업로드 geojson 파일 수정 2026-03-27 10:14:44 +09:00
58 changed files with 450 additions and 363 deletions

View File

@@ -125,6 +125,7 @@ public class CommonCodeService {
return commonCodeCoreService.getCode(parentCodeCd, childCodeCd);
}
// TODO 미사용시작
/**
* 공통코드 이름 조회
*
@@ -136,6 +137,8 @@ public class CommonCodeService {
return commonCodeCoreService.getCode(parentCodeCd, childCodeCd);
}
// TODO 미사용 끝
public List<CodeDto> getTypeCode(String type) {
return Enums.getCodes(type);
}

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.common.download;
import com.kamco.cd.training.common.download.dto.DownloadSpec;
@@ -46,3 +47,4 @@ public class DownloadExecutor {
.body(body);
}
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.common.download;
import org.springframework.util.AntPathMatcher;
@@ -17,3 +18,4 @@ public final class DownloadPaths {
return false;
}
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.common.enums;
import com.kamco.cd.training.common.utils.enums.CodeExpose;
@@ -17,3 +18,4 @@ public enum DeployTargetType implements EnumType {
private final String id;
private final String text;
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.common.enums;
import com.kamco.cd.training.common.utils.enums.CodeExpose;
@@ -25,3 +26,4 @@ public enum ModelMngStatusType implements EnumType {
return desc;
}
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.common.enums;
import com.kamco.cd.training.common.utils.enums.CodeExpose;
@@ -18,3 +19,4 @@ public enum ProcessStepType implements EnumType {
private final String id;
private final String text;
}
// TODO 미사용 끝

View File

@@ -57,7 +57,7 @@ public class StartupLogger {
"""
╔════════════════════════════════════════════════════════════════════════════════╗
║ 🚀 APPLICATION STARTUP INFORMATION 2
║ 🚀 APPLICATION STARTUP INFORMATION 3
╠════════════════════════════════════════════════════════════════════════════════╣
║ PROFILE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣

View File

@@ -288,6 +288,12 @@ public class DatasetApiController {
})
@PostMapping("/deliveries")
public ApiResponseDto<String> insertDeliveriesDataset(@RequestBody AddDeliveriesReq req) {
// 폴더 구조 검증
DatasetService.validateTrainValTestDirs(req.getFilePath());
// 파일 개수 검증
DatasetService.validateDirFileCount(req.getFilePath());
datasetAsyncService.insertDeliveriesDatasetAsync(req);
return ApiResponseDto.createOK("ok");
}

View File

@@ -145,6 +145,7 @@ public class DatasetDto {
}
}
// TODO 미사용시작
@Schema(name = "DatasetDetailReq", description = "데이터셋 상세 조회 요청")
@Getter
@Setter
@@ -157,6 +158,8 @@ public class DatasetDto {
private Long datasetId;
}
// TODO 미사용 끝
@Schema(name = "DatasetRegisterReq", description = "데이터셋 등록 요청")
@Getter
@Setter

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.dataset.dto;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
@@ -72,6 +73,7 @@ public class MapSheetDto {
private List<Long> itemIds;
}
// TODO 미사용시작
@Schema(name = "MapSheetCheckReq", description = "도엽 번호 유효성 검증 요청")
@Getter
@Setter
@@ -101,3 +103,4 @@ public class MapSheetDto {
private boolean duplicate;
}
}
// TODO 미사용 끝

View File

@@ -44,21 +44,11 @@ public class DatasetAsyncService {
try {
// ===== 1. 폴더/파일 검증 =====
long validateStart = System.currentTimeMillis();
// 폴더 구조 검증
DatasetService.validateTrainValTestDirs(req.getFilePath());
// 파일 개수 검증
DatasetService.validateDirFileCount(req.getFilePath());
log.info("{} 데이터셋 검증 완료. ({} ms)", LOG_PREFIX, System.currentTimeMillis() - validateStart);
// ===== 2. UID 생성 =====
// ===== 1. UID 생성 =====
String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
log.info("{} 생성된 UID: {}", LOG_PREFIX, uid);
// ===== 3. 마스터 데이터 생성 =====
// ===== 2. 마스터 데이터 생성 =====
String title = req.getTitle();
if (title == null || title.isBlank()) {
@@ -87,11 +77,11 @@ public class DatasetAsyncService {
log.info("{} 마스터 저장 완료. datasetUid={}", LOG_PREFIX, datasetUid);
// ===== 4. 상태 변경 (업로드중) =====
// ===== 3. 상태 변경 (업로드중) =====
datasetCoreService.updateDatasetUploadStatus(datasetUid, LearnDataRegister.UPLOADING);
log.info("{} 상태 변경 → UPLOADING. datasetUid={}", LOG_PREFIX, datasetUid);
// ===== 5. 데이터 등록 =====
// ===== 4. 데이터 등록 =====
long insertStart = System.currentTimeMillis();
// 납품 데이터 obj 등록
@@ -103,7 +93,7 @@ public class DatasetAsyncService {
datasetUid,
System.currentTimeMillis() - insertStart);
// ===== 6. 상태 변경 (완료) =====
// ===== 5. 상태 변경 (완료) =====
datasetCoreService.updateDatasetUploadStatus(datasetUid, LearnDataRegister.COMPLETED);
log.info("{} 상태 변경 → COMPLETED. datasetUid={}", LOG_PREFIX, datasetUid);

View File

@@ -30,7 +30,12 @@ public class DatasetBatchService {
@Transactional
public void saveBatch(List<Map<String, Object>> batch, Long datasetUid, String type) {
for (Map<String, Object> map : batch) {
try {
insertTrainTestData(map, datasetUid, type);
} catch (Exception e) {
log.error("파일 단위 실패. skip. file={}", batch, e);
continue;
}
}
}
@@ -52,6 +57,10 @@ public class DatasetBatchService {
JsonNode json;
try {
json = parseJson(labelJson);
if (json == null) {
log.warn("json null. skip. file={}", labelJson);
return;
}
} catch (Exception e) {
// 실패하면 skip, 다음 진행
log.error("GeoJSON 파싱 실패. skip. file={}", geojsonPath, e);
@@ -64,16 +73,31 @@ public class DatasetBatchService {
if (fileNameStr.length < 4) {
log.error("파일명 파싱 실패: {}", fileName);
throw new IllegalArgumentException("잘못된 파일명 형식: " + fileName);
return;
// throw new IllegalArgumentException("잘못된 파일명 형식: " + fileName);
}
int compareYyyy = 0;
int targetYyyy = 0;
try {
compareYyyy = parseInt(fileNameStr[1], "compareYyyy", fileName);
targetYyyy = parseInt(fileNameStr[2], "targetYyyy", fileName);
} catch (Exception e) {
log.error("기준년도 파싱 실패: {}", fileName);
return;
}
int compareYyyy = parseInt(fileNameStr[1], "compareYyyy", fileName);
int targetYyyy = parseInt(fileNameStr[2], "targetYyyy", fileName);
String mapSheetNum = fileNameStr[3];
// JSON 유효성 체크
JsonNode featuresNode = json.path("features");
// 2. 비어있는지 확인
if (featuresNode.isEmpty()) {
log.warn("features empty. skip. file={}", geojsonPath);
return;
}
if (!featuresNode.isArray()) {
log.warn("features array 아님. skip. file={}", geojsonPath);
return; // skip
@@ -155,7 +179,7 @@ public class DatasetBatchService {
return mapper.readTree(labelJson.toString());
} catch (Exception e) {
log.error("label_json parse error: {}", labelJson, e);
throw new RuntimeException("label_json parse error", e);
return null;
}
}

View File

@@ -87,6 +87,7 @@ public class DatasetService {
return datasetCoreService.getOneByUuid(id);
}
// TODO 미사용시작
/**
* 데이터셋 등록
*
@@ -101,6 +102,7 @@ public class DatasetService {
return saved.getId();
}
// TODO 미사용 끝
/**
* 데이터셋 수정
*
@@ -665,7 +667,6 @@ public class DatasetService {
i + batch.size(),
datasetUid,
e);
throw e;
}
}

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.dataset.service;
import com.kamco.cd.training.dataset.dto.MapSheetDto;
@@ -39,3 +40,4 @@ public class MapSheetService {
log.info("도엽 삭제 완료 - 개수: {}", deleteReq.getItemIds().size());
}
}
// TODO 미사용 끝

View File

@@ -14,7 +14,6 @@ import com.kamco.cd.training.model.dto.ModelTrainMngDto.Basic;
import com.kamco.cd.training.model.dto.ModelTrainMngDto.CleanupResult;
import com.kamco.cd.training.model.dto.ModelTrainMngDto.ModelProgressStepDto;
import com.kamco.cd.training.model.service.ModelTrainDetailService;
import com.kamco.cd.training.model.service.ModelTrainMngService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
@@ -47,10 +46,9 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/models")
public class ModelTrainDetailApiController {
private final ModelTrainDetailService modelTrainDetailService;
private final ModelTrainMngService modelTrainMngService;
private final RangeDownloadResponder rangeDownloadResponder;
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
@Operation(summary = "모델학습관리> 모델관리 > 상세정보탭 > 학습 진행정보", description = "학습 진행정보, 모델학습 정보 API")

View File

@@ -47,6 +47,7 @@ public class FileDto {
private Integer endPos;
}
// TODO 미사용시작
@Getter
@Setter
@NoArgsConstructor
@@ -89,6 +90,8 @@ public class FileDto {
}
}
// TODO 미사용 끝
@Schema(name = "FoldersDto", description = "폴더목록 정보")
@Getter
public static class FoldersDto {

View File

@@ -53,7 +53,7 @@ public class ModelTrainDetailService {
private final ModelTrainDetailCoreService modelTrainDetailCoreService;
private final ModelTrainMngCoreService mngCoreService;
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
/**
@@ -84,6 +84,7 @@ public class ModelTrainDetailService {
return modelTrainDetailCoreService.findByModelByUUID(uuid);
}
// TODO 미사용시작
/**
* 전이학습 모델선택 정보
*
@@ -150,6 +151,8 @@ public class ModelTrainDetailService {
return transferDetailDto;
}
// TODO 미사용 끝
public List<ModelTrainMetrics> getModelTrainMetricResult(UUID uuid) {
return modelTrainDetailCoreService.getModelTrainMetricResult(uuid);
}

View File

@@ -46,11 +46,14 @@ public class ModelTrainMngService {
private final TrainJobService trainJobService;
private final ModelTrainDetailService modelTrainDetailService;
@Value("${train.docker.basePath}")
@Value("${train.docker.base_path}")
private String basePath;
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
@Value("${train.docker.symbolic_link_dir}")
private String symbolicDir;
/**
* 모델학습 조회
@@ -80,7 +83,7 @@ public class ModelTrainMngService {
}
// ===== 2. 경로 생성 =====
Path tmpBase = Path.of(basePath, "tmp").toAbsolutePath().normalize();
Path tmpBase = Path.of(symbolicDir).toAbsolutePath().normalize();
Path tmp = tmpBase.resolve(model.getRequestPath()).normalize();
Path responseBase = Paths.get(responseDir).toAbsolutePath().normalize();
@@ -232,12 +235,7 @@ public class ModelTrainMngService {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
if (!Files.isSymbolicLink(file)) {
log.error("tmp 내부에 일반 파일 존재: {}", file);
throw new CustomApiException(
"BAD_REQUEST", HttpStatus.BAD_REQUEST, "tmp 내부는 symlink만 허용");
}
// 파일은 전부 허용 (일반 + symlink)
return FileVisitResult.CONTINUE;
}
@@ -245,10 +243,11 @@ public class ModelTrainMngService {
public FileVisitResult preVisitDirectory(Path directory, BasicFileAttributes attrs)
throws IOException {
// 루트 제외 + symlink 디렉토리 금지
if (!directory.equals(dir) && Files.isSymbolicLink(directory)) {
log.error("tmp 내부에 symlink 디렉토리 존재: {}", directory);
throw new CustomApiException(
"BAD_REQUEST", HttpStatus.BAD_REQUEST, "tmp 내부에 symlink 디렉토리 금지");
"BAD_REQUEST", HttpStatus.BAD_REQUEST, "tmp 내부에 symlink 디렉토리는 허용되지 않습니다.");
}
return FileVisitResult.CONTINUE;

View File

@@ -95,6 +95,7 @@ public class DatasetCoreService
return search(searchReq);
}
// TODO 미사용시작
/**
* 학습데이터 등록
*
@@ -129,6 +130,7 @@ public class DatasetCoreService
return savedEntity.toDto();
}
// TODO 미사용 끝
/**
* 학습 데이터 수정
*

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.core;
import com.kamco.cd.training.common.exception.NotFoundException;
@@ -70,3 +71,4 @@ public class MapSheetCoreService
}
}
}
// TODO 미사용 끝

View File

@@ -67,10 +67,13 @@ public class ModelTrainDetailCoreService {
return modelDetailRepository.getByModelHyperParamSummary(uuid);
}
// TODO 미사용시작
public TransferHyperSummary getTransferHyperSummary(UUID uuid) {
return modelDetailRepository.getByModelTransferHyperParamSummary(uuid);
}
// TODO 미사용 끝
public List<MappingDataset> getByModelMappingDataset(UUID uuid) {
return modelDetailRepository.getByModelMappingDataset(uuid);
}
@@ -80,6 +83,7 @@ public class ModelTrainDetailCoreService {
return entity.toDto();
}
// TODO 미사용시작
/**
* 모델 학습별 config 정보 조회
*
@@ -90,6 +94,7 @@ public class ModelTrainDetailCoreService {
return modelConfigRepository.findModelConfigByModelId(modelId).orElse(null);
}
// TODO 미사용 끝
public List<ModelTrainMetrics> getModelTrainMetricResult(UUID uuid) {
return modelDetailRepository.getModelTrainMetricResult(uuid);
}

View File

@@ -219,6 +219,7 @@ public class ModelTrainMngCoreService {
modelConfigRepository.save(entity);
}
// TODO 미사용시작
/**
* 데이터셋 매핑 생성
*
@@ -235,6 +236,8 @@ public class ModelTrainMngCoreService {
}
}
// TODO 미사용 끝
/**
* UUID로 모델 조회
*
@@ -278,6 +281,7 @@ public class ModelTrainMngCoreService {
.orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND));
}
// TODO 미사용시작
public ModelConfigDto.TransferBasic findModelTransferConfigByModelId(UUID uuid) {
ModelMasterEntity modelEntity = findByUuid(uuid);
return modelConfigRepository
@@ -285,6 +289,8 @@ public class ModelTrainMngCoreService {
.orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND));
}
// TODO 미사용 끝
/**
* 데이터셋 G1 목록
*
@@ -295,6 +301,7 @@ public class ModelTrainMngCoreService {
return datasetRepository.getDatasetSelectG1List(req);
}
// TODO 미사용시작
/**
* 전이학습 데이터셋 G1 목록
*
@@ -305,6 +312,8 @@ public class ModelTrainMngCoreService {
return datasetRepository.getDatasetTransferSelectG1List(modelId);
}
// TODO 미사용 끝
/**
* 데이터셋 G2, G3 목록
*
@@ -315,6 +324,7 @@ public class ModelTrainMngCoreService {
return datasetRepository.getDatasetSelectG2G3List(req);
}
// TODO 미사용시작
/**
* 전이학습 데이터셋 G2, G3 목록
*
@@ -327,6 +337,8 @@ public class ModelTrainMngCoreService {
return datasetRepository.getDatasetTransferSelectG2G3List(modelId, modelNo);
}
// TODO 미사용 끝
/**
* 모델관리 조회
*

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.core;
import com.kamco.cd.training.postgres.entity.SystemMetricsEntity;
@@ -64,3 +65,4 @@ public class SystemMetricsCoreService {
return isAvailable;
}
}
// TODO 미사용 끝

View File

@@ -117,10 +117,12 @@ public class DatasetEntity {
@Column(name = "dataset_path", length = 1000)
private String datasetPath;
// TODO 미사용시작
@Column(name = "class_counts")
@JdbcTypeCode(SqlTypes.JSON)
private Map<String, Integer> classCounts;
// TODO 미사용 끝
@Size(max = 32)
@Column(name = "uid")
private String uid;

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.entity;
import com.kamco.cd.training.dataset.dto.MapSheetDto;
@@ -103,3 +104,4 @@ public class MapSheetEntity {
return dto;
}
}
// TODO 미사용 끝

View File

@@ -32,10 +32,13 @@ public class ModelDatasetMappEntity {
@Column(name = "dataset_uid", nullable = false)
private Long datasetUid;
// TODO 미사용시작
@Size(max = 20)
@Column(name = "dataset_type", length = 20)
private String datasetType;
// TODO 미사용 끝
@Getter
@Setter
@NoArgsConstructor

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.entity;
import jakarta.persistence.Column;
@@ -92,3 +93,4 @@ public class ModelMngEntity {
return this.uuid != null ? this.uuid.toString() : null;
}
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.entity;
import jakarta.persistence.Column;
@@ -53,3 +54,4 @@ public class SystemMetricsEntity {
@Column(name = "memused")
private Float memused;
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.repository;
import com.kamco.cd.training.postgres.entity.SystemMetricsEntity;
@@ -17,3 +18,4 @@ public interface SystemMetricsRepository extends JpaRepository<SystemMetricsEnti
@Query("SELECT s FROM SystemMetricsEntity s ORDER BY s.timestamp DESC LIMIT 1")
Optional<SystemMetricsEntity> findLatestMetrics();
}
// TODO 미사용 끝

View File

@@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface DatasetRepository
extends JpaRepository<DatasetEntity, Long>, DatasetRepositoryCustom {
// TODO 미사용시작
List<DatasetEntity> findByDeletedOrderByCreatedDttmDesc(Boolean deleted);
// TODO 미사용 끝
}

View File

@@ -18,10 +18,13 @@ public interface DatasetRepositoryCustom {
List<SelectDataSet> getDatasetSelectG1List(DatasetReq req);
// TODO 미사용시작
public List<SelectTransferDataSet> getDatasetTransferSelectG1List(Long modelId);
public List<SelectTransferDataSet> getDatasetTransferSelectG2G3List(Long modelId, String modelNo);
// TODO 미사용 끝
List<SelectDataSet> getDatasetSelectG2G3List(DatasetReq req);
Long getDatasetMaxStage(int compareYyyy, int targetYyyy);

View File

@@ -150,6 +150,7 @@ public class DatasetRepositoryImpl implements DatasetRepositoryCustom {
.fetch();
}
// TODO 미사용시작
@Override
public List<SelectTransferDataSet> getDatasetTransferSelectG1List(Long modelId) {
@@ -247,6 +248,7 @@ public class DatasetRepositoryImpl implements DatasetRepositoryCustom {
.fetch();
}
// TODO 미사용 끝
@Override
public List<SelectDataSet> getDatasetSelectG2G3List(DatasetReq req) {
@@ -311,6 +313,7 @@ public class DatasetRepositoryImpl implements DatasetRepositoryCustom {
.fetch();
}
// TODO 미사용시작
@Override
public List<SelectTransferDataSet> getDatasetTransferSelectG2G3List(
Long modelId, String modelNo) {
@@ -421,6 +424,8 @@ public class DatasetRepositoryImpl implements DatasetRepositoryCustom {
.fetch();
}
// TODO 미사용 끝
@Override
public Long getDatasetMaxStage(int compareYyyy, int targetYyyy) {
return queryFactory

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.postgres.entity.MapSheetEntity;
@@ -11,3 +12,4 @@ public interface MapSheetRepository
long countByDatasetIdAndDeletedFalse(Long datasetId);
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.dataset.dto.MapSheetDto;
@@ -7,3 +8,4 @@ import org.springframework.data.domain.Page;
public interface MapSheetRepositoryCustom {
Page<MapSheetEntity> findMapSheetList(MapSheetDto.SearchReq searchReq);
}
// TODO 미사용 끝

View File

@@ -1,3 +1,4 @@
// TODO 미사용시작
package com.kamco.cd.training.postgres.repository.dataset;
import com.kamco.cd.training.dataset.dto.MapSheetDto;
@@ -52,3 +53,4 @@ public class MapSheetRepositoryImpl implements MapSheetRepositoryCustom {
return new PageImpl<>(content, pageable, total);
}
}
// TODO 미사용 끝

View File

@@ -8,5 +8,7 @@ import org.springframework.stereotype.Repository;
@Repository
public interface HyperParamRepository
extends JpaRepository<ModelHyperParamEntity, Long>, HyperParamRepositoryCustom {
// TODO 미사용시작
Optional<ModelHyperParamEntity> findByHyperVer(String hyperVer);
// TODO 미사용 끝
}

View File

@@ -11,6 +11,7 @@ import org.springframework.data.domain.Page;
public interface HyperParamRepositoryCustom {
// TODO 미사용시작
/**
* 마지막 버전 조회
*
@@ -19,6 +20,8 @@ public interface HyperParamRepositoryCustom {
@Deprecated
Optional<ModelHyperParamEntity> findHyperParamVer();
// TODO 미사용 끝
/**
* 모델 타입별 마지막 버전 조회
*
@@ -27,8 +30,11 @@ public interface HyperParamRepositoryCustom {
*/
Optional<ModelHyperParamEntity> findHyperParamVerByModelType(ModelType modelType);
// TODO 미사용시작
Optional<ModelHyperParamEntity> findHyperParamByHyperVer(String hyperVer);
// TODO 미사용 끝
/**
* 하이퍼 파라미터 상세조회
*

View File

@@ -29,6 +29,7 @@ public class HyperParamRepositoryImpl implements HyperParamRepositoryCustom {
private final JPAQueryFactory queryFactory;
// TODO 미사용시작
@Override
public Optional<ModelHyperParamEntity> findHyperParamVer() {
@@ -42,6 +43,8 @@ public class HyperParamRepositoryImpl implements HyperParamRepositoryCustom {
.fetchOne());
}
// TODO 미사용 끝
@Override
public Optional<ModelHyperParamEntity> findHyperParamVerByModelType(ModelType modelType) {
@@ -59,6 +62,7 @@ public class HyperParamRepositoryImpl implements HyperParamRepositoryCustom {
.fetchOne());
}
// TODO 미사용시작
@Override
public Optional<ModelHyperParamEntity> findHyperParamByHyperVer(String hyperVer) {
@@ -75,6 +79,8 @@ public class HyperParamRepositoryImpl implements HyperParamRepositoryCustom {
.fetchOne());
}
// TODO 미사용 끝
@Override
public Optional<ModelHyperParamEntity> findHyperParamByUuid(UUID uuid) {
return Optional.ofNullable(

View File

@@ -7,14 +7,18 @@ import java.util.UUID;
import org.springframework.data.domain.Page;
public interface MembersRepositoryCustom {
// TODO 미사용시작
boolean existsByUserId(String userId);
// TODO 미사용 끝
boolean existsByEmployeeNo(String employeeNo);
Optional<MemberEntity> findByEmployeeNo(String employeeNo);
// TODO 미사용시작
Optional<MemberEntity> findByUserId(String userId);
// TODO 미사용 끝
Optional<MemberEntity> findByUUID(UUID uuid);
Page<MemberEntity> findByMembers(MembersDto.SearchReq searchReq);

View File

@@ -27,6 +27,7 @@ public class MembersRepositoryImpl extends QuerydslRepositorySupport
this.queryFactory = queryFactory;
}
// TODO 미사용시작
/**
* 사용자 ID 조회
*
@@ -43,6 +44,8 @@ public class MembersRepositoryImpl extends QuerydslRepositorySupport
!= null;
}
// TODO 미사용 끝
/**
* 사용자 사번 조회
*
@@ -59,6 +62,7 @@ public class MembersRepositoryImpl extends QuerydslRepositorySupport
!= null;
}
// TODO 미사용시작
/**
* 사용자 조회 user id
*
@@ -71,6 +75,8 @@ public class MembersRepositoryImpl extends QuerydslRepositorySupport
queryFactory.selectFrom(memberEntity).where(memberEntity.userId.eq(userId)).fetchOne());
}
// TODO 미사용 끝
/**
* 사용자 조회 employeed no
*

View File

@@ -6,5 +6,7 @@ import java.util.Optional;
public interface ModelConfigRepositoryCustom {
Optional<ModelConfigDto.Basic> findModelConfigByModelId(Long modelId);
// TODO 미사용시작
Optional<ModelConfigDto.TransferBasic> findModelTransferConfigByModelId(Long modelId);
// TODO 미사용 끝
}

View File

@@ -39,6 +39,7 @@ public class ModelConfigRepositoryImpl implements ModelConfigRepositoryCustom {
.fetchOne());
}
// TODO 미사용시작
@Override
public Optional<TransferBasic> findModelTransferConfigByModelId(Long modelId) {
QModelConfigEntity beforeConfig = new QModelConfigEntity("beforeConfig");
@@ -78,4 +79,5 @@ public class ModelConfigRepositoryImpl implements ModelConfigRepositoryCustom {
.where(modelMasterEntity.id.eq(modelId))
.fetchOne());
}
// TODO 미사용 끝
}

View File

@@ -23,8 +23,11 @@ public interface ModelDetailRepositoryCustom {
HyperSummary getByModelHyperParamSummary(UUID uuid);
// TODO 미사용시작
TransferHyperSummary getByModelTransferHyperParamSummary(UUID uuid);
// TODO 미사용 끝
List<MappingDataset> getByModelMappingDataset(UUID uuid);
ModelMasterEntity findByModelByUUID(UUID uuid);

View File

@@ -20,8 +20,11 @@ public interface ModelMngRepositoryCustom {
Optional<ModelMasterEntity> findByUuid(UUID uuid);
// TODO 미사용시작
Optional<ModelMasterEntity> findFirstByStatusCdAndDelYn(String statusCd, Boolean delYn);
// TODO 미사용 끝
TrainRunRequest findTrainRunRequest(Long modelId);
Long findModelStep1InProgressCnt();

View File

@@ -133,11 +133,14 @@ public class ModelMngRepositoryImpl implements ModelMngRepositoryCustom {
.fetchOne());
}
// TODO 미사용시작
@Override
public Optional<ModelMasterEntity> findFirstByStatusCdAndDelYn(String statusCd, Boolean delYn) {
return Optional.empty();
}
// TODO 미사용 끝
@Override
public TrainRunRequest findTrainRunRequest(Long modelId) {
return queryFactory

View File

@@ -23,11 +23,11 @@ import org.springframework.stereotype.Service;
public class DataSetCountersService {
private final ModelTrainMngCoreService modelTrainMngCoreService;
@Value("${train.docker.requestDir}")
@Value("${train.docker.request_dir}")
private String requestDir;
@Value("${train.docker.basePath}")
private String trainBaseDir;
@Value("${train.docker.symbolic_link_dir}")
private String symbolicDir;
public String getCount(Long modelId) {
ModelTrainMngDto.Basic basic = modelTrainMngCoreService.findModelById(modelId);
@@ -45,7 +45,7 @@ public class DataSetCountersService {
}
// tmp
Path tmpPath = Path.of(trainBaseDir, "tmp", basic.getRequestPath());
Path tmpPath = Path.of(symbolicDir, basic.getRequestPath());
// 차이나는거
diffMergedRequestsVsTmp(uids, tmpPath);

View File

@@ -31,27 +31,26 @@ public class DockerTrainService {
private String image;
// 학습 요청 데이터가 위치한 호스트 디렉토리
@Value("${train.docker.requestDir}")
@Value("${train.docker.request_dir}")
private String requestDir;
// 학습 결과가 저장될 호스트 디렉토리
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
// 컨테이너 이름 prefix
@Value("${train.docker.containerPrefix}")
private String containerPrefix;
// 공유메모리 사이즈 설정 (대용량 학습시 필요)
@Value("${train.docker.shmSize:16g}")
@Value("${train.docker.shm_size:16g}")
private String shmSize;
// data 경로 request,response 상위 폴더
@Value("${train.docker.basePath}")
@Value("${train.docker.base_path}")
private String basePath;
@Value("${train.docker.symbolic_link_dir}")
private String symbolicDir;
// IPC host 사용 여부
@Value("${train.docker.ipcHost:true}")
@Value("${train.docker.ipc_host:true}")
private boolean ipcHost;
@Value("${spring.profiles.active}")
@@ -263,9 +262,9 @@ public class DockerTrainService {
c.add("-v");
c.add(basePath + ":" + basePath); // 심볼릭 링크와 연결되는 실제 파일 경로도 마운트를 해줘야 함
c.add("-v");
c.add(basePath + "/tmp:/data");
c.add(symbolicDir + ":/data"); //요청할경로
c.add("-v");
c.add(responseDir + ":/checkpoints");
c.add(responseDir + ":/checkpoints"); //저장될경로
// 표준입력 유지 (-it 대신 -i만 사용)
c.add("-i");

View File

@@ -50,7 +50,7 @@ public class JobRecoveryOnStartupService {
*
* <p>컨테이너가 --rm 으로 삭제된 경우에도 이 경로에 val.csv / *.pth 등이 남아있으면 정상 종료 여부를 "파일 기반"으로 판정합니다.
*/
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
/**

View File

@@ -42,7 +42,7 @@ public class ModelTestMetricsJobService {
private String profile;
// 학습 결과가 저장될 호스트 디렉토리
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
@Value("${file.pt-path}")

View File

@@ -33,7 +33,7 @@ public class ModelTrainMetricsJobService {
private String profile;
// 학습 결과가 저장될 호스트 디렉토리
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
/** 결과 csv 파일 정보 등록 */

View File

@@ -14,12 +14,11 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class TmpDatasetService {
@Value("${train.docker.requestDir}")
@Value("${train.docker.request_dir}")
private String requestDir;
@Value("${train.docker.basePath}")
private String trainBaseDir;
@Value("${train.docker.symbolic_link_dir}")
private String symbolicDir;
/**
* train, val, test 폴더별로 link
*
@@ -36,7 +35,7 @@ public class TmpDatasetService {
throw new IOException("links is empty");
}
Path tmp = Path.of(trainBaseDir, "tmp", uid);
Path tmp = Path.of(symbolicDir, uid);
long linksMade = 0;
@@ -98,6 +97,7 @@ public class TmpDatasetService {
return 1;
}
// TODO 미사용시작
/**
* request 전체 폴더 link
*
@@ -114,7 +114,7 @@ public class TmpDatasetService {
log.info("requestDir(raw)={}", requestDir);
Path BASE = toPath(requestDir);
Path tmp = Path.of(trainBaseDir, "tmp", uid);
Path tmp = Path.of(symbolicDir, uid);
log.info("BASE={}", BASE);
log.info("BASE exists? {}", Files.isDirectory(BASE));
@@ -210,4 +210,5 @@ public class TmpDatasetService {
}
return Paths.get(p).toAbsolutePath().normalize();
}
// TODO 미사용 끝
}

View File

@@ -40,7 +40,7 @@ public class TrainJobService {
private final DataSetCountersService dataSetCounters;
// 학습 결과가 저장될 호스트 디렉토리
@Value("${train.docker.responseDir}")
@Value("${train.docker.response_dir}")
private String responseDir;
public Long getModelIdByUuid(UUID uuid) {

View File

@@ -83,6 +83,7 @@ public class UploadDto {
private UUID uuid;
}
// TODO 미사용시작
@Schema(name = "UploadCompleteReq", description = "업로드 완료 요청")
@Getter
@Setter
@@ -126,12 +127,15 @@ public class UploadDto {
@Schema(description = "상태", example = "UPLOADING")
private String status;
// TODO 미사용시작
@Schema(description = "총 청크 수", example = "100")
private Integer totalChunks;
@Schema(description = "업로드된 청크 수", example = "50")
private Integer uploadedChunks;
// TODO 미사용 끝
@Schema(description = "진행률 (%)", example = "50.0")
private Double progress;
@@ -139,6 +143,8 @@ public class UploadDto {
private String errorMessage;
}
// TODO 미사용 끝
@Schema(name = "UploadAddReq", description = "업로드 요청")
@Getter
@Setter

View File

@@ -26,27 +26,21 @@ public class UploadService {
private final UploadSessionCoreService uploadSessionCoreService;
@Value("${file.sync-root-dir}")
private String syncRootDir;
@Value("${file.sync-tmp-dir}")
private String syncTmpDir;
@Value("${file.sync-file-extention}")
private String syncFileExtention;
@Value("${file.dataset-dir}")
private String datasetDir;
@Value("${file.dataset-tmp-dir}")
private String datasetTmpDir;
// TODO 미사용시작
@Transactional
public DmlReturn initUpload(UploadDto.InitReq initReq) {
return new DmlReturn("success", "UPLOAD CHUNK INIT");
}
// TODO 미사용 끝
@Transactional
public UploadDto.UploadRes uploadChunk(UploadDto.UploadAddReq upAddReqDto, MultipartFile file) {

View File

@@ -5,12 +5,8 @@ spring:
jpa:
show-sql: true
hibernate:
ddl-auto: validate
properties:
hibernate:
default_batch_fetch_size: 100 # ✅ 성능 - N+1 쿼리 방지
order_updates: true # ✅ 성능 - 업데이트 순서 정렬로 데드락 방지
use_sql_comments: true # ⚠️ 선택 - SQL에 주석 추가 (디버깅용)
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
@@ -21,14 +17,6 @@ spring:
hikari:
minimum-idle: 10
maximum-pool-size: 20
connection-timeout: 60000 # 60초 연결 타임아웃
idle-timeout: 300000 # 5분 유휴 타임아웃
max-lifetime: 1800000 # 30분 최대 수명
leak-detection-threshold: 60000 # 연결 누수 감지
transaction:
default-timeout: 300 # 5분 트랜잭션 타임아웃
jwt:
secret: "kamco_token_dev_dfc6446d-68fc-4eba-a2ff-c80a14a0bf3a"
@@ -39,21 +27,10 @@ token:
refresh-cookie-name: kamco-dev # 개발용 쿠키 이름
refresh-cookie-secure: false # 로컬 http 테스트면 false
springdoc:
swagger-ui:
persist-authorization: true # 스웨거 새로고침해도 토큰 유지, 로컬스토리지에 저장
member:
init_password: kamco1234!
swagger:
local-port: 8080
file:
sync-root-dir: /app/original-images/
sync-tmp-dir: ${file.sync-root-dir}tmp/
sync-file-extention: tfw,tif
dataset-dir: /home/kcomu/data/request/
dataset-tmp-dir: ${file.dataset-dir}tmp/
@@ -63,10 +40,10 @@ file:
train:
docker:
image: kamco-cd-train:latest
requestDir: /home/kcomu/data/request
responseDir: /home/kcomu/data/response
basePath: /home/kcomu/data
containerPrefix: kamco-cd-train
shmSize: 16g
ipcHost: true
base_path: /home/kcomu/data
request_dir: ${train.docker.base_path}/request
response_dir: ${train.docker.base_path}/response
symbolic_link_dir: ${train.docker.base_path}/tmp
container_prefix: kamco-cd-train
shm_size: 16g
ipc_host: true

View File

@@ -3,15 +3,6 @@ spring:
activate:
on-profile: prod
jpa:
show-sql: false # 운영 환경에서는 성능을 위해 비활성화
hibernate:
ddl-auto: validate
properties:
hibernate:
default_batch_fetch_size: 100 # N+1 쿼리 방지
order_updates: true # 업데이트 순서 정렬로 데드락 방지
datasource:
url: jdbc:postgresql://kamco-cd-train-db:5432/kamco_training_db
username: kamco_training_user
@@ -19,13 +10,6 @@ spring:
hikari:
minimum-idle: 10
maximum-pool-size: 20
connection-timeout: 60000 # 60초 연결 타임아웃
idle-timeout: 300000 # 5분 유휴 타임아웃
max-lifetime: 1800000 # 30분 최대 수명
leak-detection-threshold: 60000 # 연결 누수 감지
transaction:
default-timeout: 300 # 5분 트랜잭션 타임아웃
jwt:
# ⚠️ 운영 환경에서는 반드시 별도의 강력한 시크릿 키를 사용하세요
@@ -37,36 +21,23 @@ token:
refresh-cookie-name: kamco
refresh-cookie-secure: true # HTTPS 환경에서 필수
springdoc:
swagger-ui:
persist-authorization: true # 스웨거 새로고침해도 토큰 유지, 로컬스토리지에 저장
member:
init_password: kamco1234!
swagger:
local-port: 9080
file:
sync-root-dir: /app/original-images/
sync-tmp-dir: ${file.sync-root-dir}tmp/
sync-file-extention: tfw,tif
dataset-dir: /home/kcomu/data/request/
dataset-dir: /data/training/request/
dataset-tmp-dir: ${file.dataset-dir}tmp/
pt-path: /home/kcomu/data/response/v6-cls-checkpoints/
pt-path: /data/training/response/v6-cls-checkpoints/
pt-FileName: yolov8_6th-6m.pt
train:
docker:
image: kamco-cd-train:latest
requestDir: /home/kcomu/data/request
responseDir: /home/kcomu/data/response
basePath: /home/kcomu/data
containerPrefix: kamco-cd-train
shmSize: 16g
ipcHost: true
base_path: /data/training
request_dir: ${train.docker.base_path}/request
response_dir: ${train.docker.base_path}/response
symbolic_link_dir: ${train.docker.base_path}/tmp
container_prefix: kamco-cd-train
shm_size: 16g
ipc_host: true

View File

@@ -10,25 +10,25 @@ spring:
datasource:
driver-class-name: org.postgresql.Driver
hikari:
minimum-idle: 2
maximum-pool-size: 2
connection-timeout: 20000
idle-timeout: 300000
max-lifetime: 1800000
leak-detection-threshold: 60000
connection-timeout: 60000 # 60초 연결 타임아웃
idle-timeout: 300000 # 5분 유휴 타임아웃
max-lifetime: 1800000 # 30분 최대 수명
leak-detection-threshold: 60000 # 연결 누수 감지
# minimum-idle, maximum-pool-size 는 프로파일별 설정
jpa:
hibernate:
ddl-auto: update # 스키마 자동 관리 활성화
ddl-auto: validate
properties:
hibernate:
javax:
jakarta:
persistence:
validation:
mode: none
jdbc:
batch_size: 50
default_batch_fetch_size: 100
order_updates: true
show-sql: false
servlet:
@@ -36,6 +36,10 @@ spring:
enabled: true
max-file-size: 10GB
max-request-size: 10GB
transaction:
default-timeout: 300 # 5분 트랜잭션 타임아웃
logging:
level:
org:
@@ -44,7 +48,12 @@ logging:
security: INFO
root: INFO
springdoc:
swagger-ui:
persist-authorization: true # 스웨거 새로고침해도 토큰 유지
member:
init_password: kamco1234!
# actuator
management:

View File

@@ -23,9 +23,7 @@ spring:
ddl-auto: none # 테스트 환경에서는 DDL 자동 생성/수정 비활성화
properties:
hibernate:
hbm2ddl:
auto: none
javax:
jakarta:
persistence:
validation:
mode: none
@@ -74,4 +72,3 @@ token:
member:
init_password: test1234!