Cross-Cutting Context Objects: 여러 엔진을 거친 AI 점수의 이유를 한곳에 기록하는 설계
여러 엔진이 이어 붙은 공급망 위험 점수를, 계산하는 순간 하나의 공유 객체에 근거를 적어 UI·LLM·감사 문서가 같은 근거를 쓰게 만든 설계. 설명 스키마부터 정하는 4주 도입안을 붙였습니다.
AI 점수의 이유는 점수를 계산하는 그 순간에만 존재합니다. 나중에 로그를 뒤지거나 LLM에게 이유를 지어내게 하는 대신, 모든 엔진이 계산하면서 근거를 하나의 공유 객체에 적어 두면 화면, 코파일럿, 감사 문서가 같은 근거를 쓰게 됩니다. 이를 위해서는 엔진을 만들기 전에 근거를 적는 형식부터 정해야 합니다.
요약
공급망 위험 분석 플랫폼을 운영하는 EcoComityChain.AI가 2026년 6월 엔지니어링 블로그에 쓴 글로, “신호와 증거(The Signal and the Proof)“라는 5편짜리 연재의 첫 편입니다. 이 회사는 8단계 자재명세서(BOM) 그래프 위 약 17만 개 노드의 위험을 점수로 매기고, 그 위에 관세 컴플라이언스 계층과 Resilience Copilot이라는 LLM 도우미를 올려 둡니다. 출발점은 검증 회의에서 나온 질문 하나였습니다. 연간 조달액이 세 배나 큰 1차 조립 협력사보다 7차 희토류 광석 공급사의 위험이 왜 더 높게 나왔느냐는 것이었습니다. 팀은 점수, 위험 등급, 가장 큰 위험 벡터의 이름까지는 볼 수 있었지만, 그 공급사에서 왜 벡터 B가 벡터 D보다 무겁게 작용했는지는 설명하지 못했습니다. 그 추론은 엔진 메모리에 약 40밀리초 머물다 사라졌기 때문입니다.
팀은 로그 분석, 엔진별 설명 API, LLM 사후 요약 세 가지를 검토한 뒤 모두 버리고, 점수 파이프라인 전체를 관통하는 공유 객체 하나에 각 엔진이 계산 중에 근거를 적는 방식을 택했습니다. 이 객체를 화면, LLM 코파일럿, 감사 문서 내보내기가 함께 씁니다. 운영 중인 시스템은 전체 실행마다 17만 개 이상의 노드를 점수화하고, 모든 점수에 근거 사슬이 붙어 있으며, 노드당 근거 단계는 중앙값 12개, 최대 31개입니다. 근거를 직렬화하는 데 드는 추가 시간은 노드당 2밀리초 미만이라고 밝힙니다. 아래에서는 이 설계가 어떻게 작동하는지와, 다른 기업 시스템에 옮기는 방법을 정리합니다.
핵심 메커니즘
1. 이유는 계산하는 순간에만 존재한다
무엇인가. 점수가 나온 이유를 나중에 다시 만들어 내려 하지 말고, 계산하는 바로 그때 기록해야 한다는 원칙입니다. 저자들이 검토하고 버린 세 방식은 모두 “점수가 나온 뒤에 이유를 추론한다”는 같은 약점을 가집니다.
어떻게 작동하나. 로그는 “지리 집중도 0.87이 임계값 0.80을 넘음” 같은 줄은 남기지만, 그 요인이 위험을 올렸는지 내렸는지, 가중치가 얼마였는지, 어느 엔진이 낸 것인지는 담지 않습니다. 엔진별 설명 API는 엔진끼리 서로 의존하는 탓에 호출하는 쪽이 모든 엔진의 내부를 알아야 하고, 엔진이 하나 늘 때마다 이어 붙이는 코드를 전부 고쳐야 합니다. LLM 사후 요약은 그럴듯한 이야기를 만들지만, 실제 계산과 어긋날 수 있습니다. 예를 들어 실제로는 임계값 초과 때문에 벡터 B가 컸는데, LLM은 더 그럴듯한 지리 집중 이야기를 할 수 있습니다. 관세 당국(CBP) 감사에서 이런 불일치는 법적 부담이 됩니다.
언제 쓰고 언제 안 쓰나. 여러 단계의 엔진·규칙이 이어져 하나의 점수나 판정을 내고, 그 이유를 사람이나 규제 기관에 설명해야 하는 시스템에 씁니다. 단일 모델 하나가 끝까지 판단하고 설명 요구가 없는 내부 실험에는 과합니다.
작은 예시 (가상). 품질 판정 시스템이 “이 로트는 출하 보류”라고 내렸을 때, 보류 사유를 나중에 MES 로그에서 찾는 대신, 판정 규칙이 돌아가는 순간 “치수 편차 0.12mm가 공차 0.10mm 초과, 보류 방향, 가중치 0.5”를 기록해 두면 출하 담당과 고객 감사에 같은 사유를 보여 줄 수 있습니다.
2. ScoreContext: 모든 엔진이 함께 쓰는 근거 기록장
무엇인가. 노드 하나를 점수화하는 동안 처음부터 끝까지 모든 엔진에 참조로 넘겨지는 객체입니다. 원문은 이를 ScoreContext라고 부르고, 이 노트도 그 이름을 그대로 씁니다. 엔진들은 서로의 출력을 직접 읽지 않고, 이 객체에만 쓰고 이 객체에서만 읽습니다. 사실상 엔진 사이의 유일한 공유 상태입니다.
어떻게 작동하나. 파이프라인 첫 엔진인 파생 속성 엔진이 구조 신호를 감지해 근거 단계를 적고, 뒤이은 엔진(회복 시간 지표 계산, 위험 심각도 엔진, 관세 컴플라이언스 워크플로)은 앞 엔진들이 이미 적어 둔 내용을 읽고 자기 단계를 덧붙입니다. 마지막에는 종합 점수와 벡터별 기여도도 같은 객체에 담깁니다. 설명을 모으는 일이 호출하는 쪽의 일이 아니라 파이프라인 구조 자체에 들어가 있어서, 엔진을 하나 추가해도 다른 곳을 고칠 필요가 없습니다.
언제 쓰고 언제 안 쓰나. 엔진이 세 개 이상이고 뒤 엔진이 앞 엔진의 판단에 기대는 구조에서 효과가 큽니다. 엔진이 서로 완전히 독립이라면 엔진별 결과를 나란히 보여 주는 것으로도 충분할 수 있습니다.
3. ExplanationStep: 근거 한 줄의 구성
무엇인가. 엔진이 ScoreContext에 적는 기록 한 줄이 ExplanationStep(근거 단계)입니다. 요인 이름, 신호값, 임계값, 방향(위험을 올렸나 내렸나), 가중치, 쉬운 말 설명, 엔진 이름이 들어가고, 예시에는 시각도 함께 기록됩니다.
어떻게 작동하나. 같은 기록을 세 소비자가 서로 다른 칸을 골라 씁니다. 화면은 요인·가중치·방향·설명을 패널로 보여 주고, 코파일럿은 요인·값·방향·가중치를 근거로 문장을 만들며, 감사 문서는 엔진 이름과 시각까지 포함해 “이 점수가 어떤 데이터 신호와 어떤 임계값 비교에서 나왔는지”를 추적합니다. 칸이 정해져 있기 때문에 로그처럼 문자열을 파싱할 필요가 없습니다.
언제 쓰고 언제 안 쓰나. 방향과 가중치를 함께 적는 것이 핵심입니다. “값이 임계값을 넘었다”만 적으면 로그와 다를 바가 없습니다.
4. 엔진이 근거를 남기는 방식: diamond pattern과 가중 합산
무엇인가. 원문은 두 엔진을 예로 듭니다. DerivedPropertiesEngine은 점수에 영향을 주기 전에 구조적 전제 조건을 감지하고, RiskSeverityEngine(위험 심각도 엔진)은 여러 위험 벡터를 가중 합산합니다.
어떻게 작동하나. DerivedPropertiesEngine(파생 속성 엔진)은 diamond pattern(여러 상위 조립 경로가 한 노드로 모이는 구조), 지리 집중 군집, 재무 위기 신호를 찾습니다. 다이아몬드 패턴은 노드로 들어오는 수렴 경로의 수를 세어 임계값과 비교하고, 기준을 넘으면 그 노드를 구조적 단일 실패점으로 분류해 고정 가중치를 매기는데, 이때 점수에 반영하기 전에 근거 단계를 먼저 적습니다. 위험 심각도 엔진은 설정된 벡터마다 원점수를 계산하고 가중치를 곱해 기여도를 구한 뒤, 벡터마다 근거 단계를 하나씩 적습니다. 원점수가 0.5를 넘으면 “위험 증가”, 아니면 “중립”으로 방향을 기록하고, 모든 기여도의 합이 종합 점수가 됩니다. 원문은 실제 임계값과 가중치 값은 공개하지 않습니다.
5. 하나의 ScoreContext, 세 소비자
무엇인가. 같은 근거 객체를 화면, LLM 코파일럿, 감사 내보내기가 각자 다른 형식으로 씁니다.
어떻게 작동하나. 화면은 근거 단계를 위험 분해 패널로 그리기만 하고 점수를 다시 계산하거나 해석하지 않습니다. 코파일럿에는 원래 입력 데이터가 아니라 기록된 근거를 넘기므로, LLM은 엔진이 적은 것을 서술하는 역할만 합니다. 저자는 근거 안에서만 말하게 해서 환각 위험을 없앤다고 설명합니다. 감사 내보내기는 같은 객체를 구조화된 감사 문서로 렌더링하며, 저자의 표현으로는 계산 기록 자체가 감사 추적이 됩니다.
언제 쓰고 언제 안 쓰나. 설명을 요구하는 사람이 여럿(현업, 경영진, 감사인)이고 같은 사안을 서로 다르게 설명하면 문제가 되는 환경에 맞습니다.
통념과 다른 주장
흔히 이렇게 봅니다AI가 낸 점수의 이유는 나중에 LLM에게 입력과 결과를 주고 설명하게 하면 된다.
저자는 이렇게 봅니다사후 설명은 엔진이 실제로 계산한 것이 아니라 그럴듯한 이야기를 만들 수 있다. LLM은 계산 중에 기록된 근거를 받아 서술만 해야 한다.
근거실제로는 임계값 초과로 벡터 B가 컸는데 LLM이 지리 집중을 원인으로 설명하는 경우처럼, 그럴듯함과 정확함이 갈릴 수 있고 관세 감사에서는 이것이 부담이 된다는 설명입니다.
흔히 이렇게 봅니다설명 기능은 점수 엔진을 다 만든 뒤에 얹으면 된다.
저자는 이렇게 봅니다설명 계층은 점수 엔진보다 먼저 만들어야 한다. 첫 엔진을 짜기 전에 근거 객체부터 설계해야 한다.
근거이유는 계산하는 동안에만 존재하므로, 그때 잡는 비용이 나중에 그럴듯한 설명을 재구성하는 비용보다 훨씬 작다는 것이 저자의 설명이고, 운영 시스템의 직렬화 추가 시간은 노드당 2밀리초 미만입니다.
저자가 든 사례
검증 회의의 질문에서 운영 시스템까지
| 상황 | 한 일 | 결과 | 연결 |
|---|---|---|---|
| 관세 컴플라이언스 검증 회의에서, 조달액이 세 배 큰 1차 협력사보다 7차 희토류 공급사 위험이 높은 이유를 설명하지 못함 | 로그·엔진별 API·LLM 사후 요약을 검토 후 버리고, 파이프라인을 관통하는 근거 객체를 도입 | 실행당 17만 개 이상 노드 점수화, 모든 점수에 근거 사슬, 노드당 단계 중앙값 12·최대 31개, 직렬화 2ms 미만 | 메커니즘 1, 2 |
가장 복잡한 노드: 근거 단계 31개
| 상황 | 한 일 | 결과 | 연결 |
|---|---|---|---|
| 다이아몬드 구조, 관세, 재무 신호가 한 노드에 겹침 | 각 엔진이 자기 판단마다 근거 단계를 적음 | 노드당 최대 31개 단계로 점수의 출처를 추적 가능 | 메커니즘 3, 4 |
기술 디테일: 근거 객체를 직접 만들려면
근거 단계 하나의 형식부터 고정합니다 (메커니즘 3). 원문이 밝힌 칸을 바탕으로, 실제로 돌릴 때 필요한 칸을 더한 설계 예시입니다. 필드 이름은 예시입니다.
{
"run_id": "2026-10-24T02:00Z-full",
"node_id": "SUP-T7-0412",
"seq": 7,
"engine": "risk_severity",
"engine_version": "3.4.1",
"factor": "geo_concentration",
"factor_concept_id": "onto:GeographicConcentration",
"signal_value": 0.87,
"threshold": 0.80,
"direction": "increases",
"weight": 0.25,
"contribution": 0.2175,
"description": "핵심 원료의 87%가 한 지역에서 나와 기준 80%를 넘음",
"evidence_refs": ["supplier_master:S-12", "customs_2026Q3:row-5531"],
"ts": "2026-10-24T02:13:07.412Z"
}
direction은 increases, decreases, neutral 셋 중 하나로 제한하고, seq로 엔진이 적은 순서를 남깁니다. engine_version과 evidence_refs가 있어야 몇 달 뒤 감사에서 같은 점수를 재현하고 원천 데이터까지 거슬러 갈 수 있습니다.
쓰기 규칙을 코드로 강제합니다 (메커니즘 2). 엔진은 단계를 추가만 하고 이미 적힌 단계를 고치지 못하게 합니다. 한 실행이 끝나면 객체를 읽기 전용으로 바꾼 뒤 소비자에게 넘깁니다. 노드당 단계 상한을 정해 두고(예: 64개), 넘으면 같은 엔진의 작은 단계들을 묶은 요약 단계로 바꿉니다. 원문 운영 수치(중앙값 12, 최대 31)가 상한을 정할 때의 참고가 됩니다.
점수와 근거가 어긋나지 않게 불변식을 검사합니다 (메커니즘 4). 모든 실행에서 “벡터별 contribution의 합 = 종합 점수”를 자동으로 확인하고, 차이가 0.001을 넘으면 그 노드는 결과를 내보내지 않고 오류로 남깁니다. 엔진 단위 테스트에는 “다이아몬드 패턴이 있는 테스트 노드에는 해당 단계가 반드시 1개 있다” 같은 근거 단계 검증을 함께 넣습니다.
코파일럿은 근거 안에서만 말하게 하고, 그걸 자동으로 확인합니다 (메커니즘 5). 근거 단계를 기여도 큰 순으로 정렬해 상위 8개와 종합 점수를 넘기고, 문장마다 근거가 된 seq를 괄호로 붙이라고 지시합니다. temperature는 0~0.2로 둡니다. 답이 오면 인용된 seq가 실제로 있는지, 문장 속 숫자가 해당 단계의 값과 일치하는지 코드로 대조합니다. 하나라도 어긋나면 한 번 다시 생성하고, 그래도 어긋나면 LLM 문장 대신 근거 단계를 그대로 나열하는 템플릿 문장을 보여 줍니다.
감사 문서는 실행 단위로 묶어 보관합니다 (메커니즘 5). 노드별 근거 객체를 JSON Lines로 저장하고, 파일마다 run_id, 엔진 버전 목록, 설정(가중치·임계값) 해시를 머리에 붙입니다. 규제 보관 기간에 맞춰(예: 5년) 변경 불가능한 저장소에 둡니다.
요인 이름을 온톨로지 개념에 연결합니다 (메커니즘 3). factor_concept_id처럼 요인을 온톨로지의 개념 ID에 묶어 두면, “지리 집중이 원인인 공급사 전부”처럼 근거 자체를 지식 그래프로 질의할 수 있고, 여러 시스템이 같은 요인을 같은 이름으로 부르게 됩니다.
현업 실행 디테일: 누가, 언제, 무엇을
네 역할이 필요합니다.
| 역할 | 누가 | 맡는 일 |
|---|---|---|
| 업무 오너 | SCM 리스크(또는 품질·신용) 팀장 | “왜?” 질문 목록 확정, 설명 문구 승인 |
| 엔지니어 | 점수 엔진 담당 1~2명 | 근거 객체 구현, 엔진별 계측, 불변식 검사 |
| 컴플라이언스 | 감사·규제 대응 담당 | 감사 문서 형식과 보관 기준 확정 |
| 화면·코파일럿 | 프론트엔드 1명 | 위험 분해 패널, 코파일럿 대조 로직 |
시작 전에 모을 것. 엔진 목록과 실행 순서, 엔진별 판단 규칙과 임계값·가중치 표, 지난 1년간 현업·경영진·감사인이 실제로 물었던 “왜 이 점수냐” 질문 20건, 감사인이 요구하는 보관 항목입니다.
| 기간 | 할 일 | 산출물 |
|---|---|---|
| 1주 | 과거 “왜?” 질문 20건 정리, 근거 단계 형식 합의 | 근거 스키마 v1 |
| 2주 | 판단 비중이 큰 엔진 2개에 기록 코드 추가, 불변식 검사 | 계측된 엔진 2개, 테스트 |
| 3주 | 위험 분해 패널, 코파일럿 근거 대조 | 화면, 코파일럿 v1 |
| 4주 | 감사 문서 내보내기, 질문 20건 리허설 | 감사 문서 샘플, 판정 보고 |
확인할 질문.
- 질문 20건 각각에 대해, 근거 객체만 보고 답할 수 있나? 못 하는 질문은 어느 엔진의 어떤 판단이 기록되지 않았기 때문인가?
- 같은 노드를 화면, 코파일럿, 감사 문서로 봤을 때 설명이 서로 같은가?
- 엔진 담당자가 바뀌어도 근거 단계를 적는 규칙이 유지되도록 코드 리뷰 체크리스트에 들어갔나?
- 근거 기록 때문에 늘어난 실행 시간이 허용 범위 안인가?
진행 판정 기준 (예시). 질문 20건 중 18건 이상을 근거 객체만으로 답하고, 코파일럿 답의 숫자 불일치가 리허설에서 0건이며, 노드당 추가 시간이 5밀리초 미만이면 나머지 엔진으로 넓힙니다.
AX 프로젝트에 쓸 때. 관세·금융 심사·품질 판정처럼 규제나 고객 감사가 있는 의사결정 시스템이라면, 새 점수 엔진이나 AI 에이전트를 만들기 전에 근거 객체의 형식부터 정하는 것이 순서입니다. 요인 이름은 온톨로지 개념에 묶고, LLM은 근거를 서술하는 역할로만 둡니다. 이미 돌아가는 시스템이라면 판단 비중이 가장 큰 엔진 두 개부터 계측해 4주 안에 감사 질문 리허설을 해 보면, 설명 공백이 어디에 있는지가 바로 드러납니다.
원문 사례
| 항목 | 내용 |
|---|---|
| 글 | Cross-Cutting Context Objects (EcoComityChain.AI 블로그, 2026년 6월), 연재 “The Signal and the Proof” 5편 중 1편 |
| 회사 | EcoComityChain.AI. 8단계 BOM 그래프 약 17만 노드의 공급망 위험 점수화, 관세 컴플라이언스 계층, Resilience Copilot 운영 |
| 출발 질문 | 조달액 3배인 1차 조립 협력사보다 7차 희토류 광석 공급사의 위험이 높은 이유 |
| 버린 방식 | 로그 분석(방향·가중치·엔진 정보 없음), 엔진별 설명 API(엔진 간 의존으로 강한 결합), LLM 사후 요약(계산과 어긋날 수 있음) |
| 채택한 방식 | 파이프라인 전체에 참조로 전달되는 공유 근거 객체(ScoreContext), 엔진은 계산 중 근거 단계(ExplanationStep)를 기록 |
| 근거 단계 칸 | 요인 이름, 신호값, 임계값, 방향, 가중치, 쉬운 말 설명, 엔진 이름(예시에는 시각 포함) |
| 엔진 | 파생 속성 엔진(다이아몬드 패턴·지리 집중·재무 위기 감지, 맨 앞에서 실행), TTRPI 계산, 위험 심각도 엔진(벡터별 원점수 × 가중치, 원점수 0.5 초과 시 위험 증가), 관세 워크플로 |
| 소비자 | 위험 분해 화면, LLM 코파일럿(기록된 근거만 서술), 감사 문서 내보내기 |
| 운영 수치 | 실행당 17만+ 노드, 1~8차 공급사 노드 540+, 근거 사슬 100%, 노드당 단계 중앙값 12·최대 31, 직렬화 노드당 2ms 미만 |
| 설계 원칙 | 점수 엔진보다 설명 계층을 먼저, 첫 엔진 전에 근거 객체부터 설계 |
핵심 개념
- 설명 가능성(XAI)
- AI가 왜 그런 결과를 냈는지 사람이 이해하고 확인할 수 있게 만드는 성질.
- 자재명세서(BOM) 그래프
- 완제품을 이루는 부품·원자재와 그 공급사를 단계별로 이은 그래프. 차수가 깊을수록 원자재 쪽입니다.
- 단일 실패점
- 그 하나가 멈추면 여러 경로가 함께 멈추는 지점.
- 위험 벡터
- 지리, 재무, 구조, 관세처럼 위험을 보는 축 하나하나. 축마다 점수를 내고 가중치로 합칩니다.
- 불변식
- 시스템이 돌아가는 동안 항상 참이어야 하는 조건. 여기서는 "기여도의 합 = 종합 점수"입니다.
- JSON Lines
- 한 줄에 JSON 객체 하나씩 적는 파일 형식. 대량 기록을 순서대로 쌓고 나눠 읽기 쉽습니다.
내 메모
TODO: 내 생각 추가
원문은 EcoComityChain.AI 블로그의 「Cross-Cutting Context Objects: Threading Structured Evidence Through a Multi-Engine Pipeline」입니다. 요약·메커니즘·사례는 저자가 밝힌 내용을 AX Review가 다시 정리한 것이고, 기술·현업 실행 디테일, JSON 설계 예시, 인포그래픽, 표는 새로 작성했습니다. 원문의 코드와 도식은 원문에서 볼 수 있습니다.