Merge pull request 'feat/infer_dev_260107' (#322) from feat/infer_dev_260107 into develop
Reviewed-on: https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice/pulls/322
This commit is contained in:
@@ -1,429 +0,0 @@
|
|||||||
# GeoJSON 파일 모니터링 시스템 - Daniel Lee
|
|
||||||
|
|
||||||
kamco-dabeeo-backoffice 프로젝트에 추가된 GeoJSON 파일 자동 모니터링 및 처리 시스템입니다.
|
|
||||||
|
|
||||||
## 주요 기능
|
|
||||||
|
|
||||||
### 1. 자동 파일 모니터링
|
|
||||||
- 지정된 폴더(`/data/geojson/upload`)를 주기적으로 모니터링 (기본값: 30초마다)
|
|
||||||
- 지원 압축 형식: ZIP, TAR, TAR.GZ, TGZ
|
|
||||||
- 최대 파일 크기: 100MB
|
|
||||||
|
|
||||||
### 2. 압축파일 자동 처리
|
|
||||||
- 압축파일에서 GeoJSON 파일들을 자동 추출
|
|
||||||
- GeoJSON 데이터 검증 및 파싱
|
|
||||||
- `tb_map_sheet_learn_data` 테이블에 데이터 저장
|
|
||||||
|
|
||||||
### 3. Geometry 데이터 자동 변환
|
|
||||||
- JSON 데이터에서 Geometry 정보 추출
|
|
||||||
- `tb_map_sheet_learn_data_geom` 테이블에 geometry 데이터 저장
|
|
||||||
- JTS Geometry 객체로 변환하여 PostGIS와 연동
|
|
||||||
|
|
||||||
## 시스템 구조
|
|
||||||
|
|
||||||
### 폴더 구조
|
|
||||||
```
|
|
||||||
/data/geojson/
|
|
||||||
├── upload/ # 모니터링 대상 폴더 (압축파일 업로드)
|
|
||||||
├── processed/ # 처리 완료된 파일들
|
|
||||||
├── error/ # 처리 실패한 파일들
|
|
||||||
└── /tmp/geojson_extract/ # 임시 추출 폴더
|
|
||||||
```
|
|
||||||
|
|
||||||
### 데이터베이스 테이블
|
|
||||||
|
|
||||||
#### tb_map_sheet_learn_data (학습데이터)
|
|
||||||
- `data_uid`: 식별키
|
|
||||||
- `data_name`: 파일명
|
|
||||||
- `data_path`: 파일 경로
|
|
||||||
- `data_type`: 데이터 타입 (GeoJSON)
|
|
||||||
- `data_json`: GeoJSON 원본 데이터 (JSON)
|
|
||||||
- `data_state`: 처리 상태 (PROCESSED/PENDING)
|
|
||||||
- `anal_state`: 분석 상태 (PENDING/COMPLETED/ERROR)
|
|
||||||
|
|
||||||
#### tb_map_sheet_learn_data_geom (학습데이터 Geometry)
|
|
||||||
- `geo_uid`: 식별키
|
|
||||||
- `data_uid`: 연결된 학습데이터 ID
|
|
||||||
- `geom`: Geometry 데이터 (PostGIS)
|
|
||||||
- `geo_type`: Geometry 타입 (Point, Polygon 등)
|
|
||||||
- `area`: 면적 정보
|
|
||||||
- 기타 속성 정보들
|
|
||||||
|
|
||||||
## 설정 방법
|
|
||||||
|
|
||||||
### application.yml 설정
|
|
||||||
```yaml
|
|
||||||
geojson:
|
|
||||||
monitor:
|
|
||||||
watch-directory: /data/geojson/upload
|
|
||||||
processed-directory: /data/geojson/processed
|
|
||||||
error-directory: /data/geojson/error
|
|
||||||
temp-directory: /tmp/geojson_extract
|
|
||||||
cron-expression: "0/30 * * * * *" # 매 30초
|
|
||||||
supported-extensions:
|
|
||||||
- zip
|
|
||||||
- tar
|
|
||||||
- tar.gz
|
|
||||||
- tgz
|
|
||||||
max-file-size: 104857600 # 100MB
|
|
||||||
```
|
|
||||||
|
|
||||||
## 사용 방법
|
|
||||||
|
|
||||||
### 1. 자동 모니터링
|
|
||||||
1. 시스템 시작 시 자동으로 스케줄러가 동작
|
|
||||||
2. `/data/geojson/upload` 폴더에 압축파일 업로드
|
|
||||||
3. 30초 이내에 자동으로 처리됨
|
|
||||||
4. 처리 결과는 로그에서 확인 가능
|
|
||||||
|
|
||||||
### 2. API를 통한 수동 제어
|
|
||||||
|
|
||||||
#### 모니터링 상태 확인
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/monitor/status
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 특정 파일 수동 처리
|
|
||||||
```bash
|
|
||||||
POST /api/geojson/process/file?filePath=/path/to/your/file.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 미처리 Geometry 변환
|
|
||||||
```bash
|
|
||||||
POST /api/geojson/process/geometry
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 특정 데이터 Geometry 변환
|
|
||||||
```bash
|
|
||||||
POST /api/geojson/process/geometry/convert
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
[1, 2, 3] # 학습데이터 ID 배열
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 데이터 조회 API
|
|
||||||
|
|
||||||
#### 학습 데이터 목록 조회
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/data/learn-data?page=0&size=10&dataState=PROCESSED
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 학습 데이터 상세 조회
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/data/learn-data/{id}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Geometry 데이터 조회
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/data/geometry?dataUid=123
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 시스템 통계 조회
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/data/statistics
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 상태별 카운트 조회
|
|
||||||
```bash
|
|
||||||
GET /api/geojson/data/status-counts
|
|
||||||
```
|
|
||||||
|
|
||||||
## 처리 흐름
|
|
||||||
|
|
||||||
1. **파일 모니터링**: 스케줄러가 주기적으로 upload 폴더 검사
|
|
||||||
2. **압축파일 검증**: 파일 형식, 크기 확인
|
|
||||||
3. **압축파일 추출**: GeoJSON 파일들 추출
|
|
||||||
4. **데이터 검증**: GeoJSON 형식 검증
|
|
||||||
5. **학습데이터 저장**: `tb_map_sheet_learn_data`에 저장
|
|
||||||
6. **Geometry 변환**: JSON → JTS Geometry 변환
|
|
||||||
7. **Geometry 저장**: `tb_map_sheet_learn_data_geom`에 저장
|
|
||||||
8. **파일 이동**: 처리 완료된 파일을 processed 폴더로 이동
|
|
||||||
|
|
||||||
## 오류 처리
|
|
||||||
|
|
||||||
### 처리 실패 시
|
|
||||||
- 파일은 `/data/geojson/error/` 폴더로 이동
|
|
||||||
- 오류 정보는 `.error.info` 파일에 기록
|
|
||||||
- 로그에 상세한 오류 내용 기록
|
|
||||||
|
|
||||||
### 복구 방법
|
|
||||||
- 오류 원인을 수정 후 error 폴더에서 upload 폴더로 파일 이동
|
|
||||||
- 또는 API를 통한 수동 처리 실행
|
|
||||||
|
|
||||||
## 모니터링 및 로그
|
|
||||||
|
|
||||||
### 로그 확인
|
|
||||||
```bash
|
|
||||||
# 전체 로그
|
|
||||||
tail -f logs/application.log
|
|
||||||
|
|
||||||
# GeoJSON 관련 로그만
|
|
||||||
tail -f logs/application.log | grep "geojson"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 주요 로그 레벨
|
|
||||||
- `INFO`: 파일 처리 시작/완료
|
|
||||||
- `WARN`: 비정상적이지만 처리 가능한 상황
|
|
||||||
- `ERROR`: 처리 실패 및 오류 상황
|
|
||||||
- `DEBUG`: 상세한 처리 과정
|
|
||||||
|
|
||||||
## 성능 고려사항
|
|
||||||
|
|
||||||
### 제한사항
|
|
||||||
- 최대 파일 크기: 100MB
|
|
||||||
- 한 번에 처리 가능한 GeoJSON 파일: 50개
|
|
||||||
- 메모리 사용량을 고려하여 대용량 파일 처리 시 주의
|
|
||||||
|
|
||||||
### 최적화 팁
|
|
||||||
- 압축파일 내 GeoJSON 파일 개수를 적절히 제한
|
|
||||||
- 너무 큰 GeoJSON 파일은 분할하여 처리
|
|
||||||
- 시스템 리소스에 따라 cron 표현식 조정
|
|
||||||
|
|
||||||
## 문제 해결
|
|
||||||
|
|
||||||
### 자주 발생하는 문제
|
|
||||||
|
|
||||||
1. **폴더 권한 문제**
|
|
||||||
```bash
|
|
||||||
chmod 755 /data/geojson/upload
|
|
||||||
chown -R app-user:app-group /data/geojson/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **디스크 공간 부족**
|
|
||||||
- processed 폴더의 오래된 파일들 정리
|
|
||||||
- 임시 폴더 정리
|
|
||||||
|
|
||||||
3. **메모리 부족**
|
|
||||||
- JVM 힙 크기 조정: `-Xmx2g`
|
|
||||||
- 처리할 파일 크기 제한
|
|
||||||
|
|
||||||
4. **데이터베이스 연결 문제**
|
|
||||||
- PostgreSQL 연결 상태 확인
|
|
||||||
- PostGIS 확장 설치 확인
|
|
||||||
|
|
||||||
### 디버깅 방법
|
|
||||||
|
|
||||||
1. **로그 레벨 조정**
|
|
||||||
```yaml
|
|
||||||
logging:
|
|
||||||
level:
|
|
||||||
com.kamco.cd.kamcoback.geojson: DEBUG
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **API 테스트**
|
|
||||||
```bash
|
|
||||||
# 상태 확인
|
|
||||||
curl http://localhost:8080/api/geojson/monitor/status
|
|
||||||
|
|
||||||
# 통계 확인
|
|
||||||
curl http://localhost:8080/api/geojson/data/statistics
|
|
||||||
```
|
|
||||||
|
|
||||||
## 확장 가능한 기능
|
|
||||||
|
|
||||||
1. **알림 시스템**: 처리 완료/실패 시 이메일 또는 슬랙 알림
|
|
||||||
2. **웹 UI**: 모니터링 및 관리를 위한 웹 인터페이스
|
|
||||||
3. **배치 처리**: 대용량 파일을 위한 비동기 배치 처리
|
|
||||||
4. **데이터 검증**: 더 상세한 GeoJSON 데이터 검증 룰
|
|
||||||
5. **성능 모니터링**: 처리 시간, 메모리 사용량 등 성능 지표 수집
|
|
||||||
|
|
||||||
#### 터미널 API 테스트 로그
|
|
||||||
|
|
||||||
```bash
|
|
||||||
deniallee@Denialui-MacBookPro-2 kamco-dabeeo-backoffice % curl -s "http://localhost:8080/api/geojson/monitor/status" | jq .
|
|
||||||
{
|
|
||||||
"cronExpression": "0/30 * * * * *",
|
|
||||||
"processedDirectory": "/Users/deniallee/geojson/processed",
|
|
||||||
"watchDirectory": "/Users/deniallee/geojson/upload",
|
|
||||||
"errorDirectory": "/Users/deniallee/geojson/error",
|
|
||||||
"maxFileSize": 104857600,
|
|
||||||
"maxFileSizeMB": 100,
|
|
||||||
"supportedExtensions": [
|
|
||||||
"zip",
|
|
||||||
"tar",
|
|
||||||
"tar.gz",
|
|
||||||
"tgz"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
deniallee@Denialui-MacBookPro-2 kamco-dabeeo-backoffice % curl -s "http://localhost:8080/api/geojson/monitor/stats" | jq .
|
|
||||||
{
|
|
||||||
"fileSystem": {
|
|
||||||
"processedDirectoryCount": 1,
|
|
||||||
"errorDirectoryCount": 2,
|
|
||||||
"watchDirectoryCount": 1
|
|
||||||
},
|
|
||||||
"database": {
|
|
||||||
"totalLearnData": 1,
|
|
||||||
"totalGeomData": 1,
|
|
||||||
"pendingAnalysis": 0
|
|
||||||
},
|
|
||||||
"monitoring": {
|
|
||||||
"errorDirectory": "/Users/deniallee/geojson/error",
|
|
||||||
"isActive": true,
|
|
||||||
"watchDirectory": "/Users/deniallee/geojson/upload",
|
|
||||||
"processedDirectory": "/Users/deniallee/geojson/processed",
|
|
||||||
"cronExpression": "0/30 * * * * *"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
deniallee@Denialui-MacBookPro-2 kamco-dabeeo-backoffice % curl -X POST -s "http://localhost:8080/api/geojson/monitor/init-d
|
|
||||||
irectories" | jq .
|
|
||||||
{
|
|
||||||
"status": "success",
|
|
||||||
"message": "디렉토리 초기화가 완료되었습니다."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
deniallee@Denialui-MacBookPro-2 kamco-dabeeo-backoffice % curl -X POST -s "http://localhost:8080/api/geojson/process/geomet
|
|
||||||
ry" | jq .
|
|
||||||
{
|
|
||||||
"message": "Geometry 변환이 완료되었습니다.",
|
|
||||||
"processedCount": 0,
|
|
||||||
"processedIds": [],
|
|
||||||
"status": "success"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# GeoJSON 파일 모니터링 시스템 - API 문제 해결 리스트
|
|
||||||
|
|
||||||
## 해결된 문제들
|
|
||||||
|
|
||||||
### 1. **누락된 Stats API 추가**
|
|
||||||
- **문제**: `/monitor/stats` 엔드포인트가 없어서 500 에러 발생
|
|
||||||
- **해결**: 시스템 통계 정보를 제공하는 완전한 API 구현
|
|
||||||
|
|
||||||
### 2. **Repository 메서드 누락**
|
|
||||||
- **문제**: `countByAnalState` 메서드 미구현으로 컴파일 에러
|
|
||||||
- **해결**: `MapSheetLearnDataRepository`에 메서드 추가
|
|
||||||
|
|
||||||
### 3. **Import 누락**
|
|
||||||
- **문제**: `HashMap`, Repository 클래스들 import 누락
|
|
||||||
- **해결**: 필요한 모든 import 문 추가
|
|
||||||
|
|
||||||
## **현재 사용 가능한 API 목록**
|
|
||||||
|
|
||||||
### **GET APIs**
|
|
||||||
|
|
||||||
#### 1. 모니터링 상태 조회
|
|
||||||
```bash
|
|
||||||
curl "http://localhost:8080/api/geojson/monitor/status"
|
|
||||||
```
|
|
||||||
**응답 예시:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cronExpression": "0/30 * * * * *",
|
|
||||||
"processedDirectory": "/Users/deniallee/geojson/processed",
|
|
||||||
"watchDirectory": "/Users/deniallee/geojson/upload",
|
|
||||||
"errorDirectory": "/Users/deniallee/geojson/error",
|
|
||||||
"maxFileSize": 104857600,
|
|
||||||
"maxFileSizeMB": 100,
|
|
||||||
"supportedExtensions": ["zip", "tar", "tar.gz", "tgz"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 시스템 통계 조회 **[신규 추가]**
|
|
||||||
```bash
|
|
||||||
curl "http://localhost:8080/api/geojson/monitor/stats"
|
|
||||||
```
|
|
||||||
**응답 예시:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"fileSystem": {
|
|
||||||
"processedDirectoryCount": 1,
|
|
||||||
"errorDirectoryCount": 2,
|
|
||||||
"watchDirectoryCount": 1
|
|
||||||
},
|
|
||||||
"database": {
|
|
||||||
"totalLearnData": 1,
|
|
||||||
"totalGeomData": 1,
|
|
||||||
"pendingAnalysis": 0
|
|
||||||
},
|
|
||||||
"monitoring": {
|
|
||||||
"errorDirectory": "/Users/deniallee/geojson/error",
|
|
||||||
"isActive": true,
|
|
||||||
"watchDirectory": "/Users/deniallee/geojson/upload",
|
|
||||||
"processedDirectory": "/Users/deniallee/geojson/processed",
|
|
||||||
"cronExpression": "0/30 * * * * *"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### **POST APIs**
|
|
||||||
|
|
||||||
#### 1. 디렉토리 초기화
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/api/geojson/monitor/init-directories"
|
|
||||||
```
|
|
||||||
**응답 예시:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": "success",
|
|
||||||
"message": "디렉토리 초기화가 완료되었습니다."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 수동 파일 처리
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/api/geojson/process/file?filePath=/path/to/file.zip"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 미처리 Geometry 변환
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/api/geojson/process/geometry"
|
|
||||||
```
|
|
||||||
**응답 예시:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "Geometry 변환이 완료되었습니다.",
|
|
||||||
"processedCount": 0,
|
|
||||||
"processedIds": [],
|
|
||||||
"status": "success"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. 특정 학습 데이터 Geometry 변환
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/api/geojson/process/geometry/convert" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '[1, 2, 3]'
|
|
||||||
```
|
|
||||||
|
|
||||||
## **주요 개선사항**
|
|
||||||
|
|
||||||
1. **완전한 통계 정보 제공**
|
|
||||||
- 데이터베이스 통계 (학습 데이터, Geometry 데이터 수)
|
|
||||||
- 파일 시스템 통계 (각 폴더별 파일 수)
|
|
||||||
- 모니터링 설정 정보
|
|
||||||
|
|
||||||
2. **견고한 에러 처리**
|
|
||||||
- 각 API별 적절한 에러 처리
|
|
||||||
- 상세한 에러 메시지 제공
|
|
||||||
- 로깅을 통한 디버깅 지원
|
|
||||||
|
|
||||||
3. **일관된 응답 형식**
|
|
||||||
- 성공/실패 상태 명확히 구분
|
|
||||||
- JSON 형식 통일
|
|
||||||
- 적절한 HTTP 상태 코드
|
|
||||||
|
|
||||||
## **시스템 현재 상태**
|
|
||||||
|
|
||||||
- **모니터링 시스템**: 정상 작동 (30초 간격)
|
|
||||||
- **API 서버**: http://localhost:8080 에서 실행 중
|
|
||||||
- **데이터베이스**: PostgreSQL + PostGIS 연결됨
|
|
||||||
- **파일 처리**: 자동 ZIP/TAR 처리 가능
|
|
||||||
- **통계 조회**: 실시간 시스템 상태 확인 가능
|
|
||||||
|
|
||||||
---
|
|
||||||
@@ -41,6 +41,7 @@ public class WebConfig implements WebMvcConfigurer {
|
|||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry
|
registry
|
||||||
.addInterceptor(fileDownloadInteceptor)
|
.addInterceptor(fileDownloadInteceptor)
|
||||||
.addPathPatterns("/api/inference/download/**"); // 추론 파일 다운로드 API만 //TODO 추후 추가
|
.addPathPatterns("/api/inference/download/**") // 추론 파일 다운로드
|
||||||
|
.addPathPatterns("/api/training-data/stage/download/**"); // 학습데이터 다운로드
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,9 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
|||||||
response.setStatusCode(apiResponse.getHttpStatus());
|
response.setStatusCode(apiResponse.getHttpStatus());
|
||||||
|
|
||||||
String actionType = HeaderUtil.get(servletRequest, "kamco-action-type");
|
String actionType = HeaderUtil.get(servletRequest, "kamco-action-type");
|
||||||
if (actionType == null) { // actionType 이 없으면 로그 저장하지 않기
|
// actionType 이 없으면 로그 저장하지 않기 || download 는 FileDownloadInterceptor 에서 하기
|
||||||
|
// (file down URL prefix 추가는 WebConfig.java 에 하기)
|
||||||
|
if (actionType == null || actionType.equalsIgnoreCase("download")) {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ spring:
|
|||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||||
#url: jdbc:postgresql://localhost:15432/kamco_cds
|
#url: jdbc:postgresql://localhost:15432/kamco_cds # 로컬호스트
|
||||||
username: kamco_cds
|
username: kamco_cds
|
||||||
password: kamco_cds_Q!W@E#R$
|
password: kamco_cds_Q!W@E#R$
|
||||||
hikari:
|
hikari:
|
||||||
|
|||||||
Reference in New Issue
Block a user