대시보드에서 "군용기가 안 보이는데?", "그냥 이모지고 방향이 없는데?"라는 지적을 받고 실제로 파고든 기록. 방향(heading)을 파이프라인 끝까지 관통시키고 우크라이나·이란까지 조회 지역을 넘혔는데, 그 과정에서 "왜 그 두 지역은 여전히 거의 안 보이는지"까지 실측으로 확인했다.

1. heading — 원본에 있던 값을 그냥 버리고 있었다

ADS-B 원본 응답에는 track(실제 진행방향, 도 단위, 0=북/시계방향)이 이미 들어있었는데, AdsbFiPollingService가 이걸 한 번도 안 읽고 있었다. 대시보드 마커는 그냥 고정된 이모지였고 회전도 없었다.

JsonNode trackNode = ac.path("track");
Double heading = trackNode.isNumber() ? trackNode.asDouble() : null;

이 값을 TargetEvent(→TargetDto→Target 엔티티까지 전부) 새 필드로 추가해서 Kafka부터 WebSocket, REST API까지 관통시켰다. 가짜 드론 시뮬레이터는 heading을 안 채우므로 null이 그대로 남는데, 프론트에서 이 null을 "북쪽을 향한다"고 거짓으로 그리지 않고 그냥 점(dot)으로 표시하게 했다 — 모르는 걸 안다고 하지 않는 게 중요했다.

CSS 삼각형(border-bottom 트릭)은 기본이 "위쪽 = 0도"라서, transform: rotate(${heading}deg)를 그대로 걸면 CSS의 시계방향 회전과 항공 방위각(북 기준 시계방향)이 정확히 일치한다 — 별도 오프셋 계산이 필요 없었다.

2. 깨진 콜사인 — @@@@@@@@의 정체

스크린샷에서 지적받은 또 다른 문제. 이 값은 실제 항공기 ID가 아니라 트랜스폰더의 콜사인 필드가 깨져서 온 값이었다 — 고도/속도가 매번 다른데도 같은 문자열로 잡히는 걸 보고 확인했다(서로 다른 여러 항공기가 같은 깨진 콜사인을 공유하고 있었다는 뜻).

String targetId = flight.matches("[A-Za-z0-9]+") ? flight : hex;

콜사인이 영숫자로만 이뤄진 유효한 형태가 아니면 ICAO hex 코드로 대체하도록 간단히 검증을 추가했다.

3. 다중 지역 폴링 — 한국 외에 우크라이나·이란도

private static final List<Region> REGIONS = List.of(
    new Region("KOREA", "대한민국(수도권)", 37.5665, 126.9780, 100),
    new Region("UKRAINE", "우크라이나(키이우)", 50.4501, 30.5234, 250),
    new Region("IRAN", "이란(테헤란)", 35.6892, 51.3890, 250)
);

한 폴링 주기(20초) 안에서 세 지역을 순차 조회하되, adsb.fi의 "초당 1회" 제한을 지키려고 지역 사이에 1.1초씩 텀을 둔다. 프론트는 세 지역 데이터가 전부 같은 WebSocket 스트림에 섞여 들어오는 걸 받아서, 탭을 누르면 그 지역의 위경도 경계 안에 있는 것만 클라이언트에서 걸러보여준다(백엔드에 지역별 API를 새로 만들 필요가 없었다).

4. 실측 — 왜 우크라이나·이란은 여전히 거의 안 보이나

지역을 넘혀 배포했는데도 로그에 계속 "우크라이나 0대", "이란 0대"가 찍혀서, 버그인지 실제 데이터가 없는 건지 API에 직접 물어보았다.

adsb.fi 우크라이나 250nm(최대 반경): 0대
adsb.fi 이란 250nm: 0대
adsb.fi 전세계 군용기 목록: 227대

adsb.lol 우크라이나 250nm: 1대(BTI420, 에어발틱 여객기 — 군용 아님)
adsb.lol 이란 250nm: 0대
adsb.lol 전세계 군용기 목록: 190대

두 서비스(adsb.fi, adsb.lol) 다 거의 또같이 안 잡힌다. aggregator를 잘못 골라서가 아니라 ADS-B라는 기술 자체의 근본적 한계다. 그런데 우크라이나와 이란은 "0대"라는 같은 결과에도 원인이 서로 다르다.

  1. 우크라이나 — 애초에 신호를 낼 항공기 자체가 없다. 2022년부터 민간 항공 영공이 NOTAM으로 폐쇄돼 있다. 군용기는 여전히 작전 중이겠지만 ADS-B를 잘 안 켜둘 — 자기 위치를 스스로 광고하는 신호를 실전에서 켜둘 이유가 없다.
  2. 이란 — 항공기는 떠 있는데, "듣는 사람"이 없다. ADS-B 집계 서비스는 결국 자원봉사자가 물리적으로 그 지역에 수신 안테나(피더)를 세워야 데이터가 나오는 크라워드소싱 구조인데, 서방 제재·정치적 고립 때문에 이란에는 그 피더 커뮤니티 자체가 형성돼 있지 않다. 항공기가 없는 게 아니라 관측 인프라가 없는 것.

한국은 100nm 반경에서도 60여 대가 꾸준히 잡히는 것과 극명히 대비된다. 결국 ADS-B 기반 관측 가능성은 "그 지역에 얼마나 활발한 민간 항공 교통이 있는가"뿐 아니라 "그 신호를 주울 자원봉사자 커뮤니티가 그 지역에 존재하는가"라는, 기술과 무관한 사회적 변수에도 좌우된다는 뜻이다.