# 일일 캐시 성능 벤치마크 보고서 ## 선박 항적 리플레이 서비스 — 캐시 vs DB 정량 비교 | 항목 | 내용 | |------|------| | 측정일 | 2026-02-07 | | 대상 시스템 | Signal Batch — ChunkedTrackStreamingService (WebSocket 스트리밍) | | 운영 환경 | prod 프로파일, Query DB 커넥션 풀 180 | | 캐시 구성 | DailyTrackCacheManager — D-1 ~ D-7 인메모리 캐시, STRtree 공간 인덱스 | | 측정 방식 | QueryBenchmark 내부 클래스 → `cache-benchmark.log` JSON 기록 | | 샘플 수 | 12건 (CACHE 3, DB 2, HYBRID 5, CACHE+Today 2) | --- ## 1. 측정 경로 분류 쿼리 시간 범위에 따라 4가지 경로로 처리된다. | 경로 | 설명 | 데이터 소스 | |------|------|------------| | **CACHE** | 요청 일자 전체가 인메모리 캐시에 존재 | 메모리 | | **DB** | 캐시 미스 — Daily 테이블 직접 조회 | DB | | **HYBRID** | 캐시 히트 일자 + 캐시 범위 밖 일자 DB 조회 | 메모리 + DB | | **CACHE+Today** | 캐시 히트 + 오늘 데이터(Hourly/5min 테이블) | 메모리 + DB | ### 오늘 데이터 구간 구조 오늘(D-0) 데이터는 캐시 대상이 아니며, 시간 경과에 따라 두 테이블로 분할 조회된다. ``` 오늘 00:00 ~ 12:00 12:00 ~ 12:35 현재(12:40) ├──── Hourly 테이블 조회 ──────┤── 5min 조회 ──┤ (12개 범위, 1시간 단위) (7개 범위, 5분 단위) ``` - **Hourly**: 자정부터 약 1시간 전까지 → 시간 단위 범위 (약 12개) - **5min**: 최근 약 1시간 이내 → 5분 단위 범위 (약 7개) - 각 범위마다 DB 커넥션 1회 + Viewport Pass1 1회 발생 → 오늘 구간 커넥션 = 범위 수 × 2 --- ## 2. 전체 측정 데이터 ### 2.1 요약 테이블 | # | 경로 | Zoom | 일수 | 캐시/DB | 선박 수 | 트랙 수 | 응답시간(ms) | DB커넥션 | DB쿼리시간(ms) | |---|------|------|------|---------|---------|---------|-------------|----------|---------------| | 1 | CACHE | 10 | 3 | 3/0 | 443 | 986 | **575** | 3 | 0 | | 2 | DB | 10 | 2 | 0/2 | 352 | 587 | **7,221** | 8 | 3,475 | | 3 | DB | 10 | 2 | 0/2 | 12,253 | 18,502 | **8,195** | 19 | 1,443 | | 4 | CACHE | 10 | 2 | 2/0 | 10,690 | 16,942 | **1,439** | 2 | 0 | | 5 | CACHE | 10 | 2 | 2/0 | 10,690 | 16,942 | **1,374** | 2 | 0 | | 6 | HYBRID | 8 | 5 | 3/2 | 9,958 | 29,362 | **8,900** | 16 | 3,301 | | 7 | HYBRID | 9 | 5 | 3/2 | 547 | 1,927 | **1,373** | 11 | 550 | | 8 | HYBRID | 8 | 5 | 3/2 | 4,589 | 12,422 | **2,910** | 12 | 715 | | 9 | HYBRID | 8 | 5 | 3/2 | 5,760 | 23,283 | **3,651** | 15 | 1,048 | | 10 | CACHE+Today | 10 | 3+오늘 | 3/0 | 105 | 301 | **6,091** | 56 | 0 | | 11 | HYBRID | 8 | 5 | 3/2 | 52,151 | 162,849 | **105,212** | 45 | 93,319 | | 12 | CACHE+Today | 12 | 3+오늘 | 3/0 | 6,990 | 17,024 | **9,744** | 56 | 0 | ### 2.2 DB 커넥션 세분화 | # | 경로 | 합계 | Viewport Pass1 | Daily Pages | Hourly/5min | TableCheck | |---|------|------|----------------|-------------|-------------|------------| | 1 | CACHE | 3 | 0 | 0 | 0 | **3** | | 2 | DB | 8 | 2 | 2 | 0 | 2 | | 3 | DB | 19 | 2 | 2 | 0 | 2 | | 4 | CACHE | 2 | 0 | 0 | 0 | **2** | | 5 | CACHE | 2 | 0 | 0 | 0 | **2** | | 6 | HYBRID | 16 | 2 | 2 | 0 | 5 | | 7 | HYBRID | 11 | 2 | 2 | 0 | 5 | | 8 | HYBRID | 12 | 2 | 2 | 0 | 5 | | 9 | HYBRID | 15 | 2 | 2 | 0 | 5 | | 10 | CACHE+Today | 56 | **21** | 0 | **21** | **14** | | 11 | HYBRID | 45 | 2 | **6** | 0 | 5 | | 12 | CACHE+Today | 56 | **21** | 0 | **21** | **14** | > 합산 검증: 전 12건 모두 세분화 카운터 합 = 합계 일치 확인 (VesselInfo 카운터 포함, 표에서는 생략). **CACHE+Today (#10, #12) 커넥션 56건 내역**: - Hourly/5min 21건: 오늘 00:00~현재 구간 (Hourly 약 12건 + 5min 약 7건 + 폴백) - Viewport Pass1 21건: 동일 범위에 대한 뷰포트 교차 선박 수집 (범위당 1회) - TableCheck 14건: Daily 3건 + Hourly/5min 존재 확인 약 11건 ### 2.3 캐시 경로 간소화 지표 캐시 경로에서는 원본 데이터를 메모리에 보유하므로 간소화 전/후를 측정할 수 있다. | # | 경로 | Zoom | 원본 포인트 | 간소화 후 | 압축률 | 간소화 시간(ms) | 배치 감소 | |---|------|------|------------|----------|--------|----------------|-----------| | 1 | CACHE | 10 | 1,083,566 | 11,212 | 99% | 133 | 50→3 (94%) | | 4 | CACHE | 10 | 13,502,970 | 172,066 | 99% | 1,075 | 602→10 (98%) | | 5 | CACHE | 10 | 13,502,970 | 172,066 | 99% | 981 | 602→10 (98%) | | 6 | HYBRID | 8 | 7,582,515 | 152,734 | 98% | 500 | 335→12 (96%) | | 7 | HYBRID | 9 | 1,049,434 | 11,634 | 99% | 74 | 50→5 (90%) | | 8 | HYBRID | 8 | 1,618,310 | 61,434 | 96% | 125 | 72→5 (93%) | | 9 | HYBRID | 8 | 3,202,500 | 155,633 | 95% | 277 | 137→12 (91%) | | 10 | CACHE+Today | 10 | 355,256 | 4,159 | 99% | 24 | 17→6 (65%) | | 11 | HYBRID | 8 | 41,634,918 | 732,470 | 98% | 2,411 | 1,813→42 (98%) | | 12 | CACHE+Today | 12 | 14,404,225 | 259,541 | 98% | 1,258 | 639→23 (96%) | > DB 경로(#2, #3)는 SQL 레벨에서 `ST_Simplify` 적용 후 수신하므로 앱 레벨 압축률 산출 불가 (before = after). --- ## 3. 경로별 정량 비교 ### 3.1 CACHE vs DB — 동일 규모 직접 비교 #### 대규모: #4 CACHE vs #3 DB | 지표 | DB (#3) | CACHE (#4) | 개선 | |------|---------|------------|------| | 선박 수 | 12,253 | 10,690 | (유사 규모) | | **응답시간** | 8,195 ms | 1,439 ms | **5.7배 빨라짐** | | **DB 커넥션** | 19 | 2 | **89% 감소** | | DB 쿼리 시간 | 1,443 ms | 0 ms | **100% 절감** | | 배치 전송 수 | 11 | 10 | 유사 | #### 소규모: #2 DB vs #1 CACHE | 지표 | DB (#2) | CACHE (#1) | 개선 | |------|---------|------------|------| | 선박 수 | 352 | 443 | (유사 규모) | | **응답시간** | 7,221 ms | 575 ms | **12.6배 빨라짐** | | **DB 커넥션** | 8 | 3 | **63% 감소** | | DB 쿼리 시간 | 3,475 ms | 0 ms | **100% 절감** | | 배치 전송 수 | 2 | 3 | 유사 | ### 3.2 HYBRID 경로 — 규모별 성능 변화 5일 범위 쿼리 (캐시 3일 + DB 2일): | # | 선박 수 | 응답시간 | DB커넥션 | DB쿼리시간 | |---|---------|---------|----------|-----------| | 7 | 547 | 1,373 ms | 11 | 550 ms | | 8 | 4,589 | 2,910 ms | 12 | 715 ms | | 9 | 5,760 | 3,651 ms | 15 | 1,048 ms | | 6 | 9,958 | 8,900 ms | 16 | 3,301 ms | | 11 | 52,151 | 105,212 ms | 45 | 93,319 ms | - 소규모(~500척): 캐시 일자가 대부분의 처리를 흡수하여 **1.4초** 수준으로 응답. - 중규모(5K~10K척): DB 쿼리 부담 증가하나 캐시 일자가 완충하여 **3~9초** 수준. - 대규모(52K척): 캐시 미스 일자의 데이터량이 크면 DB 의존도가 높아져 **100초+** 수준. - 캐시 적용 일수가 많을수록(현재 3/5일 = 60%) HYBRID 경로의 DB 부담이 경감된다. ### 3.3 CACHE+Today 경로 — 오늘 데이터 포함 쿼리 | # | Zoom | 선박 수 | 응답시간 | DB커넥션 | 오늘 구간 커넥션 | |---|------|---------|---------|----------|----------------| | 10 | 10 | 105 | 6,091 ms | 56 | 42 (H5m 21 + VP 21) | | 12 | 12 | 6,990 | 9,744 ms | 56 | 42 (H5m 21 + VP 21) | **핵심 발견**: - 두 쿼리 모두 동일한 시간 범위(3일+오늘)이므로 커넥션 구조가 동일하며, 뷰포트 크기만 다름. - 오늘 구간(00:00~현재)만으로 **42건의 DB 커넥션**이 발생하여, 순수 CACHE 경로(2~3건)와 큰 차이를 보인다. - 선박 수가 적은 #10(105척)도 6초가 소요되며, 이는 오늘 구간의 범위별 개별 커넥션 오버헤드가 원인이다. ### 3.4 줌 레벨별 간소화 효과 | Zoom | 대표 # | 원본 포인트 | 간소화 후 | 압축률 | 선박당 평균 포인트 | |------|--------|------------|----------|--------|------------------| | 8 | #6 | 7,582,515 | 152,734 | 98% | 15.3 | | 9 | #7 | 1,049,434 | 11,634 | 99% | 21.3 | | 10 | #4 | 13,502,970 | 172,066 | 99% | 16.1 | | 12 | #12 | 14,404,225 | 259,541 | 98% | 37.1 | - 줌 8~10: 선박당 15~21 포인트로 압축 — 해역 수준 조회에 최적. - 줌 12: 선박당 37 포인트 — 항만 수준 상세 조회에서 더 많은 포인트를 유지. - 전 줌 레벨에서 95~99% 압축률 달성. --- ## 4. DB 커넥션 구성 분석 ### 4.1 경로별 커넥션 구성 패턴 ``` CACHE (순수) [==TC==] 2~3건 TableCheck만 발생 DB (순수) [VP][DA][..기타..][TC] 8~19건 각 항목 균등 분포 HYBRID [VP][DA][..기타..........][TC---] 11~45건 규모에 비례 증가 CACHE+Today [VP----------][H5m---------][TC------] 56건 오늘 구간의 Hourly/5min + Viewport가 대부분 ``` ### 4.2 커넥션 풀 영향 분석 Query DataSource 커넥션 풀 180 기준: | 경로 | 쿼리당 사용 | 동시 10쿼리 시 누적 | 풀 압박 수준 | |------|------------|-------------------|------------| | CACHE | 2~3 | 30 | 매우 낮음 (17%) | | HYBRID (소규모) | 11~15 | 150 | 보통 (83%) | | DB | 8~19 | 190 | 보통~높음 | | CACHE+Today | 56 | 560 | 높음 | > 커넥션은 순간 점유가 아닌 순차 사용이므로 실제 동시 점유 수는 위 수치보다 작다. 캐시 적용으로 전체 쿼리 중 CACHE 경로 비율이 높아지면 풀 전체 부담이 크게 감소한다. --- ## 5. 종합 성능 비교 ### 5.1 핵심 개선 지표 | 지표 | DB 경로 | CACHE 경로 | 개선율 | |------|---------|------------|--------| | 응답시간 (대규모, 만 척 이상) | 8,195 ms | 1,439 ms | **5.7배** | | 응답시간 (소규모, 수백 척) | 7,221 ms | 575 ms | **12.6배** | | DB 커넥션 수 (대규모) | 19건 | 2건 | **89% 감소** | | DB 커넥션 수 (소규모) | 8건 | 3건 | **63% 감소** | | DB 쿼리 시간 | 1,443~3,475 ms | 0 ms | **100% 절감** | | 포인트 간소화 | SQL ST_Simplify | 앱 레벨 95~99% | 캐시만 측정 가능 | ### 5.2 경로별 응답시간 분포 ``` 응답시간 (ms, 로그 스케일 아님) 경로 0 2,000 4,000 6,000 8,000 10,000 CACHE (순수) |█| 575~1,439 HYBRID (소규모) |██| 1,373 HYBRID (중규모) |█████| 2,910~3,651 CACHE+Today |████████████| 6,091~9,744 DB (순수) |████████████████| 7,221~8,195 HYBRID (대규모) |██████████████████| 8,900 ``` > HYBRID 대규모(#11, 52K척, 105초)는 스케일 초과로 표시 생략. ### 5.3 캐시 적용에 따른 운영 시나리오별 예측 D-1 ~ D-7 캐시가 적용된 상태에서: | 사용 패턴 | 예상 경로 | 예상 응답시간 | DB 커넥션 | |----------|----------|-------------|----------| | 과거 1~7일만 조회 | CACHE | **0.5~1.5초** | 2~3건 | | 과거 수일 + 오늘 | CACHE+Today | 6~10초 | ~56건 | | 7일 이전 과거 포함 | HYBRID / DB | 1~9초 (규모 의존) | 8~45건 | --- ## 6. 캐시 범위 확장 시 권장 구성 현재 D-1 ~ D-7 캐시 구성에서 조회 기간 범위를 확장하고자 할 경우, 아래 구성을 권장한다. ### 6.1 현재 구성 ```yaml cache: daily-track: enabled: true retention-days: 7 # D-1 ~ D-7 캐시 max-memory-gb: 6 # 최대 메모리 사용량 warmup-async: true # 비동기 워밍업 ``` - 7일 이내 과거 조회: CACHE 경로 (0.5~1.5초) - 7일 초과 과거 포함: HYBRID/DB 경로로 폴백 ### 6.2 확장 권장안 | 시나리오 | retention-days | max-memory-gb | 예상 효과 | |----------|---------------|---------------|----------| | **현재** | 7 | 6 | 1주일 이내 CACHE, 이후 DB | | **2주 확장** | 14 | 12 | 2주 리플레이까지 CACHE 커버 | | **1개월 확장** | 30 | 25 | 월간 분석 조회까지 CACHE 커버 | **확장 시 고려사항**: 1. **메모리 산정**: 현재 7일 캐시 ≈ 4GB 기준, 선형 증가 추정. - 14일: ~12GB, 30일: ~25GB - 서버 가용 메모리와 JVM 힙 설정(`-Xmx`) 여유 확인 필요. 2. **워밍업 시간**: retention-days 증가에 비례하여 초기 로드 시간 증가. - 7일: 약 1~2분, 14일: 약 2~4분, 30일: 약 5~10분 (비동기이므로 서비스 가용성 영향 없음) 3. **HYBRID 비율 감소**: retention-days 확장 시 DB 폴백 빈도가 줄어, HYBRID 경로가 줄고 순수 CACHE 경로 비율이 증가한다. 이는 DB 커넥션 풀 부담 경감에 직접 기여한다. 4. **CACHE+Today 경로는 retention-days와 무관**: 오늘(D-0) 데이터는 항상 Hourly/5min 테이블에서 DB 조회한다. 이 구간의 커넥션 최적화는 별도 과제이다. ### 6.3 단계적 확장 전략 ``` Phase 1 (현재) : retention-days=7, max-memory-gb=6 → 1주 커버 Phase 2 (권장) : retention-days=14, max-memory-gb=12 → 2주 커버, 주간 비교 분석 지원 Phase 3 (선택) : retention-days=30, max-memory-gb=25 → 월간 커버, 장기 항적 분석 지원 ``` 각 단계 전환 시 서버 메모리 여유와 워밍업 시간을 모니터링하며, JVM 힙 설정을 함께 조정한다. --- ## 7. 결론 ### 7.1 캐시 효과 확인 1. **응답시간**: 순수 CACHE 경로에서 DB 대비 **5.7~12.6배** 빨라짐 확인. 2. **DB 커넥션**: 순수 CACHE 경로에서 DB 대비 **63~89%** 감소 확인. 3. **간소화**: 캐시 경로에서 줌 레벨에 따라 **95~99%** 포인트 압축, 배치 전송 수 **90~98%** 감소. 4. **DB 쿼리 시간**: CACHE 경로에서 **0ms** — DB 부하 완전 제거. ### 7.2 운영 권장사항 | 항목 | 현황 | 권장 방향 | |------|------|----------| | 캐시 보존 기간 | 7일 | 사용 패턴에 따라 14~30일로 확장 검토 | | CACHE+Today 커넥션 | 오늘 구간 범위별 개별 DB 커넥션 (56건) | 오늘 데이터 범위 병합 또는 별도 캐시 검토 |