Compare commits

..

61 커밋

작성자 SHA1 메시지 날짜
77f881a7c1 Merge pull request 'release: 2026-03-27.3 (7건 커밋)' (#121) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m13s
2026-03-27 08:14:56 +09:00
ce55cdd115 docs: 릴리즈 노트 정리 (2026-03-27) 2026-03-27 08:12:44 +09:00
83cd865363 Merge pull request 'feat(batch): 비정상 궤적 포함 저장 플래그 추가 — 강화학습 데이터 수집용' (#120) from feature/include-abnormal-tracks-flag-v2 into develop 2026-03-27 08:07:32 +09:00
44cd532d52 docs: 릴리즈 노트 업데이트 2026-03-27 08:06:53 +09:00
8f784de358 feat(batch): 비정상 궤적 포함 저장 플래그 추가 — 강화학습 데이터 수집용
GPS 스푸핑 등 비정상 운항 패턴의 강화학습 분류기 고도화를 위해,
비정상 궤적을 정상 테이블(5min/hourly/daily)과 캐시(L1/L2)에도
포함 저장하는 설정 플래그 추가.

- vessel.batch.track.include-abnormal-in-tracks 플래그 (기본 false)
- 5min: isAbnormal 시에도 filteredTracks에 포함 (플래그 true)
- Hourly/Daily: correctedTrack null 시에도 originalTrack 포함 (플래그 true)
- 비정상 검출 + t_abnormal_tracks 기록은 플래그와 무관하게 항상 유지
- prod 환경 true 설정 (강화학습 데이터 수집)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 08:06:29 +09:00
6a597958e1 Merge pull request 'fix(metrics): REST API 경로 client_id 수집 누락 수정' (#119) from fix/client-id-rest-api into develop 2026-03-27 08:06:20 +09:00
74aace919b docs: 릴리즈 노트 업데이트 2026-03-27 08:05:47 +09:00
df957be2fe fix(metrics): REST API 경로 client_id 수집 누락 수정
- JWT 쿠키 파싱을 WebSocketStompConfig.extractClientIdFromRequest() static 메서드로 추출
- GisControllerV2 → GisServiceV2 → enqueueRestMetric에 clientId 전달 추가
- WebSocket 경로는 이미 정상 (htlee@gcsc.co.kr 수집 확인)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 08:01:43 +09:00
573f4ff70d Merge pull request 'release: 2026-03-27.2 (4건 커밋)' (#118) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m14s
2026-03-27 07:17:51 +09:00
99a7f607f7 Merge pull request 'release: 2026-03-27 (5건 커밋)' (#116) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m4s
2026-03-27 06:40:38 +09:00
22710068d8 Merge pull request 'release: 2026-03-19 (9건 커밋)' (#114) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m8s
2026-03-19 07:48:19 +09:00
444430d272 Merge pull request 'release: 2026-03-18 (4건 커밋)' (#112) from develop into main
Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 28m38s
2026-03-18 17:09:13 +09:00
796bd09f29 Merge pull request 'release: 2026-03-17.3 (2건 커밋)' (#110) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m44s
2026-03-17 10:02:39 +09:00
75d3919410 Merge pull request 'release: 2026-03-17.2 (2건 커밋)' (#108) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m32s
2026-03-17 09:29:58 +09:00
e571a571df Merge pull request 'release: 2026-03-17 (2건 커밋)' (#106) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 9m38s
2026-03-17 08:41:57 +09:00
fa03c7d80d Merge pull request 'release: 2026-03-13 (4건 커밋)' (#104) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m46s
2026-03-13 10:20:40 +09:00
9bd2135337 Merge pull request 'release: 2026-03-10.2 (4건 커밋)' (#102) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m30s
2026-03-10 11:20:19 +09:00
7539441d95 Merge pull request 'release: 2026-03-10 (4건 커밋)' (#100) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m33s
2026-03-10 09:21:05 +09:00
fb1076ac11 Merge pull request 'release: 2026-03-09.2 (4건 커밋)' (#98) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m24s
2026-03-09 11:27:08 +09:00
9d6e5ca408 Merge pull request 'release: 2026-03-09 (119건 커밋)' (#96) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m12s
2026-03-09 06:51:51 +09:00
882c07a7c6 Merge pull request 'release: 2026-03-08 (115건 커밋)' (#94) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 8m12s
2026-03-08 09:33:03 +09:00
2434b3ddb2 Merge pull request 'release: 2026-03-02.3 (109건 커밋)' (#92) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m42s
2026-03-02 16:52:33 +09:00
7a21d5b8b0 Merge pull request 'release: 2026-03-02.2 (105건 커밋)' (#90) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m29s
2026-03-02 15:40:24 +09:00
bbd14fab8c Merge pull request 'release: 2026-03-02 (98건 커밋)' (#87) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m22s
2026-03-02 00:21:39 +09:00
77613af4be Merge pull request 'perf: API 응답 크기 최적화 + Swagger 최신화' (#84) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m16s
2026-03-01 22:55:52 +09:00
57226ef2a9 Merge pull request 'feat: DataPipeline 일별 차트 시각화 개선 — Stacked Bar + Duration Bar' (#82) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m49s
2026-02-21 12:29:12 +09:00
8c1cfdd6b5 Merge pull request 'fix: ST_AsText WKT 공백 불일치로 인한 daily merge 전량 필터 수정' (#80) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 4m12s
2026-02-21 01:17:02 +09:00
51780b80bb Merge pull request 'fix: L2 워밍업 범위 확장 — Daily Job 전 기동 시 어제 데이터 포함' (#78) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m8s
2026-02-21 00:43:44 +09:00
e16aa2d645 Merge pull request 'chore: L2 HourlyTrackCache maxSize 3.5M→7M 상향' (#76) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 4m33s
2026-02-21 00:36:48 +09:00
893a54ec8e Merge pull request 'chore: L2 HourlyTrackCache maxSize 3.5M→5M 상향' (#74) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m25s
2026-02-21 00:28:28 +09:00
a0963a1332 Merge pull request 'fix: html2canvas oklch/oklab 색상 파싱 에러 수정' (#72) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m8s
2026-02-20 20:50:42 +09:00
3f55f80d2b Merge pull request 'feat: UI 레이아웃 수정 + 구역분석/STS 보고서 모달 + 이미지 저장' (#70) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 5m10s
2026-02-20 18:46:55 +09:00
d3520a6fd8 Merge pull request 'feat: 다중구역이동 항적 분석 + STS 접촉 분석 프론트엔드 이관' (#68) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m47s
2026-02-20 17:08:13 +09:00
a7b9e76d51 Merge pull request 'feat: 항적/리플레이 선종 아이콘 + Raw Data 패널' (#66) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m41s
2026-02-20 16:00:18 +09:00
9ae56f5517 Merge pull request 'fix: 항적 조회 500 에러 + 리플레이 쿼리 무반응 수정' (#64) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m35s
2026-02-20 15:37:39 +09:00
137a22a411 Merge pull request 'feat: Ship-GIS 기능 이관 — 최근위치/선박항적/뷰포트 리플레이' (#62) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 4m0s
2026-02-20 15:22:11 +09:00
14e61e6bd0 Merge pull request 'perf: Daily Job 인메모리 캐시 기반 최적화 — N+1 SQL 제거' (#60) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m52s
2026-02-20 11:39:54 +09:00
9a1d4b7b2e Merge pull request 'feat: recent-positions IMO + 선박사진 enrichment' (#57) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m46s
2026-02-20 02:18:23 +09:00
0caea9c766 Merge pull request 'fix: UTC 타임존 변환 + Daily 캐시 부분 fallback 추가' (#53) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m20s
2026-02-20 00:47:45 +09:00
e9aa0302cd Merge pull request 'feat: 중국허가선박 최신 위치 조회 API' (#51) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m34s
2026-02-19 23:04:28 +09:00
9f98682347 Merge pull request 'fix: V2 캐시 조회 시 누락 MMSI DB fallback 추가' (#49) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m48s
2026-02-19 22:53:19 +09:00
e6cb152d29 Merge pull request 'feat: ChnPrmShip 전용 DB 이력 + API enrichment + ShipImage V2' (#47) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m35s
2026-02-19 22:38:17 +09:00
85c8b5b28e Merge pull request 'docs: Swagger UI 현행화' (#45) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m34s
2026-02-19 21:30:31 +09:00
b581233240 Merge pull request 'fix: 캐시 maxSize 설정 경로 수정' (#43) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m36s
2026-02-19 21:00:42 +09:00
a237648fe7 Merge pull request 'fix: L1/L2 캐시 maxSize 상향 + AisTarget hitRate 타입 수정' (#41) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m10s
2026-02-19 20:47:46 +09:00
5cf6e32d71 Merge pull request 'perf: API 응답 최적화 + 점진적 렌더링 + 해구 choropleth 지도' (#39) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m35s
2026-02-19 20:26:23 +09:00
c3d0b15f97 Merge pull request 'feat: Phase 4 — 비정상 항적 + 시스템 메트릭 (7/7 완성)' (#37) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m40s
2026-02-19 19:20:31 +09:00
6f17006811 Merge pull request 'feat: Phase 3 — API Explorer 지도 스캐폴딩' (#35) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m35s
2026-02-19 19:14:40 +09:00
f49f1ac4e4 Merge pull request 'perf: L1/L2 캐시 maxSize 상향 (실측 기반)' (#33) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m45s
2026-02-19 19:10:05 +09:00
eabeee1bb7 Merge pull request 'fix: 해구 통계 ROUND 함수 타입 캐스팅 오류 수정' (#31) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m31s
2026-02-19 19:01:28 +09:00
ec20dc8e76 Merge pull request 'fix: 해구 조회 바운딩 박스 간소화' (#29) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m36s
2026-02-19 18:54:44 +09:00
e2a692a5e2 Merge pull request 'fix: 해구 통계 디버그 로깅' (#27) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m31s
2026-02-19 18:50:25 +09:00
86f0c457e3 Merge pull request 'fix: toLocalDateTime 변환 강화' (#23) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m29s
2026-02-19 18:39:54 +09:00
1c963b3d75 Merge pull request 'fix: Timestamp 캐스팅 오류 수정' (#21) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m31s
2026-02-19 18:36:19 +09:00
065f14ede4 Merge pull request 'fix: MonitoringController 레거시 타일 쿼리 전환 + 해구 통계 수정' (#19) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m45s
2026-02-19 18:30:55 +09:00
e70def6611 Merge pull request 'chore: AIS API 인증 정보 추가 (prod)' (#17) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m32s
2026-02-19 18:08:56 +09:00
318d2aefbb Merge pull request 'Release: Phase 2 — DataPipeline + AreaStats' (#15) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m31s
2026-02-19 17:56:58 +09:00
478aa44e59 Merge pull request 'Release: Dashboard API 연동 오류 수정 + Phase 1 안정화' (#13) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m31s
2026-02-19 17:35:31 +09:00
997dad8117 Merge pull request 'feat: React 19 SPA Dashboard Phase 1 + 안전 배포 시스템' (#11) from feature/dashboard-phase-1 into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m30s
Reviewed-on: #11
2026-02-19 17:09:18 +09:00
941fb3cf4a Merge pull request 'release: Gitea Actions CI/CD 파이프라인 + systemd 서비스 구성' (#9) from develop into main
Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 3m6s
Reviewed-on: #9
2026-02-19 14:32:05 +09:00
b9ace1681c Merge pull request 'release: SNP API 전환 + 인메모리 캐시 최적화 + 다계층 캐시 조회 통합' (#7) from develop into main
Reviewed-on: #7
2026-02-19 14:26:30 +09:00
4개의 변경된 파일48개의 추가작업 그리고 33개의 파일을 삭제

파일 보기

@ -4,6 +4,14 @@
## [Unreleased]
## [2026-03-27.3]
### 추가
- 비정상 궤적 포함 저장 플래그 (`include-abnormal-in-tracks`) — 강화학습 데이터 수집용
### 수정
- REST API 경로 client_id 수집 누락 수정 — JWT 쿠키 파싱 공용 메서드 추출
## [2026-03-27.2]
### 수정

파일 보기

@ -191,7 +191,11 @@ public class GisControllerV2 {
)
@RequestBody VesselTracksRequest request,
HttpServletRequest httpRequest) {
return gisServiceV2.getVesselTracksV2(request, getClientIp(httpRequest));
return gisServiceV2.getVesselTracksV2(request, getClientIp(httpRequest), getClientId(httpRequest));
}
private String getClientId(HttpServletRequest request) {
return gc.mda.signal_batch.global.config.WebSocketStompConfig.extractClientIdFromRequest(request);
}
private String getClientIp(HttpServletRequest request) {

파일 보기

@ -285,7 +285,7 @@ public class GisServiceV2 {
/**
* 선박별 항적 조회 V2 (캐시 + Semaphore + 간소화 + ChnPrmShip enrichment)
*/
public List<CompactVesselTrack> getVesselTracksV2(VesselTracksRequest request, String clientIp) {
public List<CompactVesselTrack> getVesselTracksV2(VesselTracksRequest request, String clientIp, String clientId) {
String queryId = "rest-vessels-" + UUID.randomUUID().toString().substring(0, 8);
long startMs = System.currentTimeMillis();
boolean slotAcquired = false;
@ -329,7 +329,7 @@ public class GisServiceV2 {
result.size(), request.getVessels().size(),
dailyTrackCacheManager.isEnabled(), request.isIncludeChnPrmShip());
enqueueRestMetric(queryId, request, result, startMs, clientIp);
enqueueRestMetric(queryId, request, result, startMs, clientIp, clientId);
return result;
@ -347,7 +347,7 @@ public class GisServiceV2 {
}
private void enqueueRestMetric(String queryId, VesselTracksRequest request,
List<CompactVesselTrack> result, long startMs, String clientIp) {
List<CompactVesselTrack> result, long startMs, String clientIp, String clientId) {
try {
int totalPoints = result.stream().mapToInt(CompactVesselTrack::getPointCount).sum();
long responseBytes = (long) result.size() * 200 + (long) totalPoints * 40;
@ -367,6 +367,7 @@ public class GisServiceV2 {
.elapsedMs(System.currentTimeMillis() - startMs)
.status("COMPLETED")
.clientIp(clientIp)
.clientId(clientId)
.build());
} catch (Exception e) {
log.debug("Failed to enqueue REST metric: {}", e.getMessage());

파일 보기

@ -235,42 +235,44 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
return "unknown";
}
/**
* GC_SESSION 쿠키에서 JWT payload의 email 클레임 추출.
* JWT 검증은 nginx auth_request에서 이미 완료 여기서는 payload 디코딩만 수행.
*/
private String extractEmailFromJwtCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies == null) return null;
return extractClientIdFromRequest(request);
}
}
String token = null;
for (Cookie cookie : cookies) {
if ("GC_SESSION".equals(cookie.getName())) {
token = cookie.getValue();
break;
}
/**
* GC_SESSION 쿠키에서 JWT payload의 email 클레임 추출 (REST/WebSocket 공용).
* JWT 검증은 nginx auth_request에서 이미 완료 여기서는 payload 디코딩만 수행.
*/
public static String extractClientIdFromRequest(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies == null) return null;
String token = null;
for (Cookie cookie : cookies) {
if ("GC_SESSION".equals(cookie.getName())) {
token = cookie.getValue();
break;
}
if (token == null || token.isEmpty()) return null;
}
if (token == null || token.isEmpty()) return null;
try {
// JWT: header.payload.signature payload만 Base64URL 디코딩
String[] parts = token.split("\\.");
if (parts.length < 2) return null;
try {
String[] parts = token.split("\\.");
if (parts.length < 2) return null;
String payload = new String(Base64.getUrlDecoder().decode(parts[1]));
// 간단한 JSON 파싱 (Jackson 의존 없이): "email":"value" 추출
int emailIdx = payload.indexOf("\"email\"");
if (emailIdx < 0) return null;
String payload = new String(Base64.getUrlDecoder().decode(parts[1]));
int emailIdx = payload.indexOf("\"email\"");
if (emailIdx < 0) return null;
int colonIdx = payload.indexOf(':', emailIdx);
int quoteStart = payload.indexOf('"', colonIdx + 1);
int quoteEnd = payload.indexOf('"', quoteStart + 1);
if (quoteStart < 0 || quoteEnd < 0) return null;
int colonIdx = payload.indexOf(':', emailIdx);
int quoteStart = payload.indexOf('"', colonIdx + 1);
int quoteEnd = payload.indexOf('"', quoteStart + 1);
if (quoteStart < 0 || quoteEnd < 0) return null;
return payload.substring(quoteStart + 1, quoteEnd);
} catch (Exception e) {
return null;
}
return payload.substring(quoteStart + 1, quoteEnd);
} catch (Exception e) {
return null;
}
}
}