"비행기가 20초마다 순간이동하는데, 폴링 주기를 줄이면 부드러워지지 않을까?"라는 질문에서 시작한 조사. 결론: 폴링 주기는 그대로 두고, 프론트에서 좌표 보간 애니메이션을 추가했다.
target-tracking-service/docs/concepts/04-adsb-fi-live-feed-integration.md에 이미 실측이 있다. adsb.fi 이용약관상 한도는 초당 최대 1회. 지금 반경 조회는 20초마다(=초당 0.05회) 나가므로 한도 대비 20배 여유다. 즉 adsb.fi 쪽 제약만 보면 1~2초로 줄여도 약관 위반이 아니다.
target-tracking이라는 Kafka 토픽 하나를 서로 다른 두 서비스가 각자의 consumer group으로 전체 스트림을 다 받는다:
| 서비스 | 매 이벤트마다 하는 일 | 게이트 플래그 |
|---|---|---|
target-tracking-service (Java) |
DB 저장, WebSocket 브로드캐스트, (옵션) SITREP 생성 | ai.auto-analysis.enabled (기본 false) |
threat-intel-ai-service (Python) |
(옵션) Qdrant 이력 색인 — upsert_target_event() |
settings.auto_index_enabled (기본 false) |
threat-intel-ai-service/app/kafka/consumer.py에 이 사고가 코드 주석으로 그대로 남아있다:
"""
Gated behind settings.auto_index_enabled (default False) -- with no
filtering this consumed the Gemini free-tier daily embedding quota (1000/day)
in well under an hour once the ADS-B feed was flowing.
"""
한 폴링 주기(20초)에 60~100대가 잡히는데, 필터링 없이 이벤트마다 Qdrant에 색인하면서 매번 Gemini 임베딩 API를 불렀더니 하루 한도(1000회)를 한 시간도 안 돼서 소진했다는 기록. k3s-msa-infrastructure/apps/threat-intel-ai-service/deployment.yaml에도 "복구 완료 — 자동 색인/자동분석을 둘 다 기본 OFF로 고친 새 이미지 배포"라는 주석이 남아있어, 이게 한 번 실제로 터졌던 사고라는 걸 확인했다.
두 플래그 다 코드 기본값이 false이고, k3s-msa-infrastructure의 매니페스트 어디에도 이걸 다시 켜는 환경변수 오버라이드가 없다. 즉 지금은 폴링 주기를 줄여도 Gemini 호출량에는 영향이 없다 — 그 경로 자체가 꺼져 있어서.
Gemini 쪽은 안전하지만, TargetConsumer.java를 보면 AI 플래그와 무관하게 이벤트마다 무조건 실행되는 부분이 있다:
targetService.saveTarget(request); // PostgreSQL 저장
messagingTemplate.convertAndSend("/topic/targets", event); // WebSocket 브로드캐스트
폴링 주기를 줄이면 이 DB 쓰기 + WebSocket 브로드캐스트 빈도가 그대로 배로 늘어난다. ax-portfolio-roadmap.md에 2026-09-16 실측이 있는데, k3s worker 노드가 이미 메모리 70%대, load average가 vCPU 수를 넘는 상태였다. 여유가 없는 3노드 홈랩 클러스터에 쓰기/브로드캐스트 빈도를 4~5배 늘리는 건 얻는 것(마커가 좀 더 자주 갱신되는 체감) 대비 리스크가 크다고 판단해서, 백엔드 폴링 주기는 그대로 뒀다.
서버 부하를 하나도 안 늘리면서 "부드럽게 움직이는" 체감만 얻는 방법 — 새 좌표가 오면 그 자리로 순간이동하는 대신, 마지막으로 받은 좌표에서 새 좌표까지 짧은 시간 동안 선형보간(lerp)해서 그린다.
transition: transformLeaflet은 마커 위치를 .leaflet-marker-icon에 transform: translate3d(...)로 적용한다. 이 클래스에 전역으로 transition: transform 1s만 걸면 라이브러리 코드를 하나도 안 건드리고 "공짜로" 움직임이 부드러워진다 — 실제로 흔히 쓰이는 트릭이다.
하지만 이 트릭은 Leaflet이 지도 자체를 pan/zoom할 때도 마커에 같은 transform을 건드린다는 문제가 있다. MapView.tsx의 MapRecenter가 지역 탭을 바꿀 때 map.flyTo()로 지도를 이동시키는데, 이 순간에도 마커 위치가 같은 CSS transition을 타면서 지도는 이미 다 이동했는데 마커들이 뒤늦게 스멀스멀 따라오는 부자연스러운 지연이 생긴다. 데이터 갱신으로 인한 이동과 지도 조작으로 인한 이동을 CSS 레벨에서 구분할 방법이 마땅치 않아서 이 방법은 버렸다.