AI agent에게 회사 데이터로 “음반사별 총 재생 수”를 물었는데 실제보다 2.5배 가까이 큰 숫자가 돌아올 수 있습니다. 많은 경우 원인은 모델의 hallucination(사실이 아닌 내용을 그럴듯하게 지어내는 현상)이 아니라, 여러 테이블을 join(테이블을 공통 열로 이어 붙이는 연산)하는 과정에서 같은 행이 여러 번 더해지는 데이터 중복입니다. BigQuery Graph의 measure는 이 문제를 질의마다 고치는 대신 데이터 모델에서 한 번에 막는 기능입니다. 계산 규칙을 그래프 정의 안에 넣어 두면 사람이 쓴 SQL이든 AI agent가 만든 질의든 같은 정답을 얻습니다.

오류 없이 실행되는 틀린 합계

예제는 한 음악 회사의 작은 데이터입니다. 곡 다섯 개, 그 곡을 부른 아티스트, 곡을 소유한 음반사 두 곳, 곡이 실린 외부 playlist 네 개가 있습니다. 음반사 A가 가진 곡은 네 개이고 재생 수는 다음과 같습니다.

곡 재생 수 실린 playlist 수
곡 1 20억 회 4개
곡 2 15억 회 2개
곡 3 12억 회 1개
곡 4 4억 회 1개
합계 51억 회 -

손으로 더하면 음반사 A의 재생 수는 51억 회입니다. 그런데 Google의 Agent Development Kit(ADK, AI agent를 만드는 개발 도구)로 만든 분석 도우미에게 음반사별 재생 수를 물으면 음반사 A의 값이 126억 회로 나옵니다.

더 위험한 점은 이 질의가 아무 오류 없이 실행된다는 것입니다. 문법상 문제가 없으니 SQL 엔진은 경고를 내지 않고, 수백만 행짜리 테이블에서는 숫자가 부풀었다는 사실을 눈으로 알아채기도 어렵습니다. 사용자는 틀린 숫자를 확신을 갖고 받아 들게 됩니다.

한 곡이 네 번 더해지는 과정

부풀려진 숫자는 join fan-out(하나의 행이 join 뒤 여러 행으로 불어나는 현상)에서 나옵니다. 곡 1을 따라가 보면 구조가 분명해집니다.

  1. join 전 곡 테이블에서 곡 1은 재생 수 20억 회를 가진 한 행입니다.
  2. 곡을 playlist 등록 기록과 join하면, 곡 1은 실린 playlist 네 개만큼 네 행으로 늘어나고 각 행이 20억 회라는 값을 그대로 가집니다.
  3. 이 상태에서 SUM(streams)을 실행하면 20억 회가 네 번 더해져 곡 1 하나에서만 80억 회가 됩니다.
  4. playlist 두 개에 실린 곡 2도 15억 회가 두 번 더해져 30억 회가 됩니다.
  5. playlist 하나에만 실린 곡 3과 곡 4는 그대로 12억 회와 4억 회입니다.

80억, 30억, 12억, 4억을 더한 값이 126억 회입니다. 실제 51억 회의 약 2.5배입니다. 곡과 playlist처럼 한쪽 하나에 다른 쪽 여럿이 붙는 one-to-many 관계나, 여럿과 여럿이 엮인 many-to-many 관계를 join한 뒤 합계를 내면 이런 일이 생깁니다.

한 장의 음반 카드가 기계를 거쳐 네 장으로 복제돼 저울에 쌓인 모습

▲ join 뒤 불어난 중복 행

계산 규칙을 데이터 모델에 넣는 measure

질의마다 중복을 걸러 내는 코드를 넣을 수도 있지만, 사람이든 AI agent가 쓰는 prompt든 언젠가는 그 규칙을 빠뜨립니다. 그래서 중복 제거 규칙을 질의 작성자의 기억이 아니라 데이터 모델 자체에 두는 편이 낫다는 것이 BigQuery Graph의 접근입니다. 구성 요소는 세 가지입니다.

  • 원천 테이블: BigQuery나 클라우드 저장소에 있는 기존 데이터입니다. 복사하거나 형태를 바꿀 필요가 없습니다.
  • property graph: 기존 테이블 위에 관계를 정의한 그래프입니다. 곡, 아티스트, 음반사, playlist는 node(그래프의 점) 테이블이 되고, playlist 등록 기록은 이들을 잇는 edge(그래프의 선)가 됩니다.
  • measure: 그래프 정의 안에 넣는 재사용 가능한 집계 규칙입니다. 곡 node에 MEASURE(SUM(streams)) AS total_streams처럼 적습니다. 음반사 node에 마케팅 예산 합계를 MEASURE(SUM(marketing_budget)) AS total_budget으로 두는 식으로 다른 entity에도 붙일 수 있습니다.

핵심은 measure가 entity의 key, 곧 곡이라면 song_id에 묶인다는 점입니다. node 테이블 정의에 KEY (song_id)를 지정해 두면, BigQuery는 어떤 묶음으로 집계하든 그 안에서 같은 곡을 한 번만 셉니다.

질의에서는 GRAPH_EXPAND로 그래프를 펼친 뒤 SUM(streams) 대신 AGG(Songs_total_streams)를 씁니다. 같은 조건에서 두 함수를 나란히 실행하면 SUM은 126억 회, AGG는 정확히 51억 회를 돌려줍니다.

한 번 정의하고 다른 묶음에도 그대로

measure는 정의를 고치지 않고도 다른 기준의 집계에 그대로 쓸 수 있습니다. GROUP BY와 SELECT의 기준을 음반사 이름에서 playlist 이름으로 바꾸기만 하면, 같은 AGG(Songs_total_streams) 호출이 playlist별 재생 수를 정확히 계산합니다.

AI agent 쪽 결과도 달라집니다. 처음과 똑같은 자연어 질문을 다시 던지면 분석 도우미가 음반사 A의 재생 수를 51억 회로 정확하게 답합니다. prompt를 손보지 않아도 데이터 모델이 바뀌었기 때문입니다.

합계 뒤에 숨은 의존 구조

BigQuery Graph의 쓰임은 정확한 합계에 그치지 않습니다. property graph는 node 19개와 edge 22개로 이뤄진 관계 구조 전체를 그대로 유지하므로, 숫자 뒤의 연결을 따라가며 물을 수 있습니다.

예를 들어 “음반사 A의 재생 51억 회 가운데 한 playlist에 얼마나 기대고 있나”를 물으면, 51억 회 가운데 47억 회, 곧 92%가 팔로워 3,500만 명의 가장 큰 playlist 한 곳을 거친다는 답이 나옵니다. 이 92%는 재생이 모두 그 playlist에서 일어났다는 뜻이 아니라, 음반사의 곡 목록이 한 유통 창구에 크게 노출돼 있다는 뜻입니다.

그 playlist를 그래프에서 끊어 보면 영향이 더 분명해집니다.

  • 음반사 곡의 playlist 등록 8건 가운데 3건이 사라집니다.
  • 곡 3은 어느 playlist에도 실리지 않은 상태가 됩니다.
  • 그래프의 edge는 22개에서 16개로 줄어듭니다.

합계 하나만으로는 이런 위험을 볼 수 없습니다. 평평한 SQL join이 가리는 관계를 그래프가 남겨 두기 때문에, 분석가와 AI agent가 숫자의 맥락까지 확인할 수 있는 것으로 보입니다.

여러 곡 node가 한 중심 node에 몰리고 연결 하나가 끊긴 그래프

▲ 한 playlist에 몰린 재생 의존

구현에 쓰는 도구

property graph와 measure를 만드는 방법은 여러 가지입니다.

방법 쓰임
BigQuery SQL CREATE OR REPLACE PROPERTY GRAPH 문으로 node, key, measure를 직접 정의
BigQuery Studio의 visual modeler node, edge, measure를 화면에서 구성하고 measure를 시험
Agent Development Kit BigQuery Graph를 직접 만든 AI agent에 연결
Knowledge Catalog 정의한 그래프의 메타데이터와 스키마가 자동 등록돼 조직 안에서 찾고 관리

BigQuery의 conversational analytics agent(대화로 데이터를 분석하는 내장 agent)는 property graph를 바로 질의할 수 있어, 분석 도우미를 따로 만들지 않아도 됩니다.

정리: AI agent에 데이터를 맡기기 전에 점검할 것

AI agent가 내놓는 틀린 숫자는 모델 탓만이 아닐 수 있습니다. join이 행을 반복시키면 합계가 조용히 부풀고, measure는 entity의 key를 기준으로 중복을 막으며, 한 번 정의한 measure는 어떤 질의에서든 다시 쓸 수 있습니다.

  • 곡과 playlist처럼 one-to-many 관계를 join한 뒤 합계를 내는 질의가 있는지 먼저 찾아봅니다.
  • 자주 쓰는 지표는 property graph의 node 정의에 measure로 넣고 KEY를 지정합니다.
  • 질의와 agent가 SUM 대신 GRAPH_EXPAND 안의 AGG로 measure를 부르게 합니다.
  • SQL을 직접 쓰기 부담스러우면 BigQuery Studio의 visual modeler로 그래프를 만들고 measure를 시험합니다.
  • 합계만 보지 말고, 한 창구에 지나치게 기댄 구조가 없는지 그래프로 함께 확인합니다.