관측 가능성이 운영자의 눈이라면, 감사 가능성은 외부 심사자에게 내미는 영수증이다. 둘 다 기록을 다루지만 목적은 다르다. 운영자는 "어디서 느려졌나"를 묻고, 감사자는 "누가, 어떤 권한으로, 무엇을, 왜 실행했나"를 묻는다. 그리고 기업 환경에서는 바로 이 두 번째 질문에 답할 수 있을 때 비로소 신뢰가 생긴다.
AI 에이전트가 프로덕션에 들어오면 성능 그래프만으로는 부족하다. 응답이 빨랐는지보다 더 중요한 것은, 그 응답과 행동이 통제된 절차 안에서 일어났는지다. 특히 고객 데이터, 금전, 권한, 문서, 배포, 의료 정보처럼 민감한 영역에 닿기 시작하면, 잘 작동하는 것만으로는 채택되지 않는다. 나중에 설명할 수 있어야 채택된다.

감사 로그는 운영 로그보다 더 무겁다
많은 팀이 처음에는 "로그는 이미 남기고 있는데요?"라고 말한다. 틀린 말은 아니다. 하지만 일반 애플리케이션 로그와 감사 기록은 같은 물건이 아니다. 일반 로그는 주로 장애를 고치기 위해 남기고, 감사 기록은 책임을 입증하기 위해 남긴다.1
이 차이는 생각보다 크다. 애플리케이션 로그는 200 OK, 지연 시간, 에러 메시지 정도로도 쓸모가 있다. 반면 감사 기록은 그걸로 부족하다. AI 에이전트는 같은 프롬프트에도 다른 결과를 낼 수 있고, 도구를 조건부로 호출하며, 실행 도중 계획을 바꾼다. 그래서 나중에 코드를 읽는 것만으로는 당시 행동을 복원하기 어렵다. 실제로 그 시점에 무엇이 입력되었고, 어떤 정책이 적용되었고, 어떤 결과가 나왔는지를 당시 기준으로 남겨야 한다.2
쉽게 말해 운영 로그가 CCTV 화면이라면, 감사 기록은 봉인된 증거 봉투에 가깝다. 둘 다 필요하지만, 법정에 제출하는 것은 보통 두 번째다.
감사자가 실제로 알고 싶은 것
감사 가능성의 핵심 질문은 복잡해 보이지만 결국 몇 가지로 줄어든다.
누가 이 실행을 시작했는가
어떤 에이전트가 어떤 권한으로 행동했는가
무엇을 읽고, 무엇을 바꾸고, 무엇을 외부로 보냈는가
왜 그 행동이 허용되었는가
사람 승인이 필요했다면 누가 언제 무엇을 보고 승인했는가
같은 사건을 나중에 다시 검토하거나 재현할 수 있는가
이 질문들 중 하나라도 답이 흐리면, 시스템은 똑똑할 수는 있어도 감사 가능하다고 말하기 어렵다. 특히 기업 환경에서는 "API 키 하나로 다 했습니다" 같은 설명이 가장 위험하다. 그 기록은 기술적으로는 맞아도, 책임 관점에서는 거의 무의미하다. 감사는 공유 키가 아니라 행위 주체와 위임 관계를 원한다.3
최소한의 감사 레코드는 무엇을 담아야 하는가
좋은 감사 시스템은 "나중에 필요할 것 같은 것"을 감으로 모으지 않는다. 애초에 한 사건의 최소 스키마를 정해 둔다. 실무에서는 보통 한 실행 전체를 run_id로 묶고, 그 안의 각 사건을 event_id로 분리해 기록한다. 그리고 모든 사건이 같은 시간선 위에서 이어지도록 만든다.4
최소한 다음 정보는 있어야 한다.
사건 식별자:
event_id,run_id,trace_id, 시간행위 주체: 에이전트 ID, 에이전트 종류, 버전, 테넌트
위임 관계: 실행을 시작한 사용자 또는 시스템, 세션, 역할
행동 정보: 어떤 도구를 어떤 인자로 호출했는지, 어떤 리소스를 읽거나 썼는지
정책 정보: 어떤 규칙이 매칭되었고 결과가 허용, 거부, 승인 요구 중 무엇이었는지
승인 정보: 승인 필요 여부, 승인자, 승인 시각, 수정 여부
결과 정보: 성공, 실패, 차단, 재시도, 부작용, 생성된 아티팩트
무결성 정보: 이전 레코드 해시, 현재 레코드 해시, 서명 정보
실무 감각으로 표현하면, 감사 레코드는 "이벤트 메모"가 아니라 실행 영수증이다. 나중에 타인이 봐도 이야기가 이어져야 한다.
예를 들면 이런 식이다.
{
"event_id": "evt_01J...",
"run_id": "run_9ac...",
"timestamp": "2026-04-30T10:41:12Z",
"actor": {
"type": "agent",
"id": "ops-agent-prod",
"version": "2.4.1"
},
"delegation": {
"user_id": "pm_kim",
"session_id": "sess_73d...",
"role": "project_manager"
},
"action": {
"type": "tool.call",
"tool": "crm.update",
"target": "lead_1842"
},
"policy": {
"decision": "REQUIRE_APPROVAL",
"matched_rule": "crm_write_high_risk",
"policy_snapshot": "pol_2026_04_01"
},
"approval": {
"required": true,
"status": "approved",
"approver": "sales_ops_lee",
"approved_at": "2026-04-30T10:41:32Z"
},
"result": {
"status": "success",
"duration_ms": 842
},
"integrity": {
"prev_hash": "sha256:...",
"hash": "sha256:..."
}
}중요한 것은 필드 수가 아니라 연결성이다. 정책, 승인, 실행, 결과가 하나의 사건 사슬로 이어져야 한다.4
"누가"를 증명하지 못하면 나머지도 흔들린다
감사 가능성에서 가장 먼저 무너지는 것이 정체성이다. 인간 사용자는 회사 계정으로 로그인했는데, 실제 API 호출은 공용 서비스 키로 나가고, 도구 호출은 또 다른 백엔드 계정으로 처리되면 기록은 남아도 책임은 흐려진다. 그 상태에서는 "누가 했다"가 아니라 "시스템 어딘가가 했다"만 남는다.3
그래서 에이전트에는 고유한 신원이 필요하다. 그리고 그 신원은 사람의 신원과 따로 기록되어야 한다. 즉, 다음이 분리되어야 한다.
실행을 시작한 사람 또는 상위 시스템
실제 행동을 수행한 에이전트
권한을 발급하거나 제한한 정책 계층
최종적으로 변경을 반영한 백엔드 서비스
이 분리가 중요한 이유는 책임을 떠넘기기 위해서가 아니라, 책임을 분해해서 설명하기 위해서다. 예를 들어 "사용자 김PM이 보고서 초안 작성을 요청했고, 리서치 에이전트 v1.8이 검색 도구를 사용했으며, 메일 발송은 승인 부족으로 차단되었다"는 식으로 말할 수 있어야 한다.
조직 차원에서는 이것이 에이전트 레지스트리와 연결된다. 어떤 에이전트가 존재하는지, 누가 소유자인지, 어떤 데이터와 도구에 접근할 수 있는지, 수명 주기가 어떻게 되는지를 중앙에서 관리해야 한다. 그래야 에이전트가 사람처럼 조직의 관리 대상이 된다.10
"왜 허용되었는가"를 남기는 것이 진짜 컴플라이언스다
감사에서 자주 놓치는 것이 결과만 남기고 이유를 남기지 않는 것이다. 하지만 감사자는 단순히 "실행됐다"보다 "왜 실행이 허용됐나"를 더 중요하게 본다. 허용의 근거가 없으면 통제가 실제로 작동했는지 증명할 수 없기 때문이다.4
그래서 정책 판정은 로그의 부가 정보가 아니라 핵심 데이터여야 한다. 적어도 다음은 남겨야 한다.
정책 판정 결과: 허용, 거부, 승인 필요, 격리 등
매칭된 규칙 이름 또는 정책 ID
적용 당시 정책 버전 또는 스냅샷
위험도 점수나 분류 이유
예외 허용 여부와 그 근거
여기서 특히 중요한 것이 정책 스냅샷이다. 나중에 정책 파일이 바뀌면 "그때 왜 허용됐는가"를 현재 규칙으로는 설명할 수 없기 때문이다. 감사는 현재의 정의가 아니라 당시의 정의를 요구한다.4
또 하나 중요한 것은 이유를 자유문장 한 줄로만 남기지 않는 일이다. "위험이 낮아서 허용"이라고 쓰는 것보다, risk_level=LOW, matched_rule=document_read_only, approval_required=false처럼 구조화된 이유 코드와 메타데이터를 남기는 편이 훨씬 낫다. 나중에 검색, 집계, 비교가 가능해지기 때문이다.
인간 승인은 버튼 클릭이 아니라 별도 사건이다
많은 팀이 승인 절차를 붙였다고 안심한다. 하지만 감사 관점에서 중요한 것은 "승인 버튼이 있었다"가 아니다. 누가, 무엇을 보고, 어떤 범위의 행동을 승인했는가다.2
즉, 사람 승인도 에이전트 실행처럼 하나의 독립 사건으로 다뤄야 한다. 좋은 승인 기록에는 다음이 들어간다.
에이전트가 제안한 원래 행동
검토한 사람의 인증된 신원
승인, 거부, 수정 중 무엇을 선택했는지
수정했다면 무엇을 어떻게 바꿨는지
승인 시각과 만료 시각
검토자가 참고한 문맥과 근거
이 지점이 중요한 이유는, 사람 개입이 있다고 해서 자동으로 안전해지지 않기 때문이다. 아무도 내용을 보지 않고 계속 승인만 누르면 그건 감독이 아니라 도장 기계다. 그래서 감사 가능성은 사람이 개입했는지뿐 아니라, 의미 있게 개입했는지까지 보여줘야 한다.25
실무적으로는 승인 레코드를 에이전트 사건과 분리해 저장하되, 반드시 같은 run_id나 approval_id로 엮어야 한다. 승인 시스템과 실행 시스템이 서로 딴소리를 하면 감사 추적이 끊어진다.
입력과 출력은 그대로 두되, 저장 방식은 똑똑해야 한다
감사를 위해 당시 입력과 출력을 남겨야 한다고 해서, 모든 원문을 모든 로그에 그대로 박아 넣으라는 뜻은 아니다. 그렇게 하면 금방 개인정보 창고가 된다. 좋은 시스템은 사실은 보존하되, 노출은 최소화한다.26
그래서 보통은 두 층으로 나눈다.
첫째, 감사 이벤트 자체에는 핵심 메타데이터와 포인터를 둔다. 문서 ID, 해시, 버전, 길이, 민감도, 저장 위치 같은 것이다.
둘째, 실제 원문과 결과물은 별도의 보호 저장소에 두고 접근 통제를 건다. 이벤트 레코드는 그 저장소를 가리키는 참조를 가진다.
이 구조의 장점은 분명하다. 감사자는 "무엇이 참조되었는지"를 볼 수 있고, 필요할 때 권한 있는 사람만 원문을 열람할 수 있다. 또한 비밀값, 토큰, 메일 본문 같은 민감 정보는 자동 마스킹하거나 아예 본문 저장을 제한할 수 있다. 실제로 실무 도구들은 명령 인자나 요청 메타데이터는 남기되 민감 값은 자동으로 가리는 방식을 많이 쓴다.6
여기서 기억할 점은 하나다. 감사 기록은 풍부해야 하지만, 무절제하면 안 된다. 설명 가능성과 데이터 최소화는 함께 설계해야 한다.
감사 가능성은 하나의 타임라인으로 묶여야 한다
감사에서 가장 괴로운 상황은 기록은 많은데 서로 연결되지 않는 경우다. 인증 시스템엔 로그인 기록이 있고, 에이전트 런타임엔 모델 호출 기록이 있고, 도구 서버엔 API 로그가 있고, 승인 시스템엔 클릭 기록이 있는데, 이 넷이 서로 이어지지 않으면 사건은 계속 조각난다.
그래서 좋은 감사 설계는 한 실행의 처음부터 끝까지 끊기지 않는 시간선을 만든다. 요청 접수, 정책 판정, 컨텍스트 구성, 도구 호출, 승인 요청, 재시도, 결과 반영, 사용자 응답, 사후 차단까지 모두 같은 실행 문맥에 묶여야 한다.4
이 타임라인이 중요한 이유는 AI 에이전트가 생각보다 자주 우회로를 타기 때문이다. 계획을 바꾸고, 다른 도구를 선택하고, 실패 후 재시도하고, 사람에게 넘기고, 다시 돌아온다. 따라서 감사 시스템은 "성공했다" 한 줄이 아니라 어떤 길을 거쳐 성공 또는 실패에 도달했는지를 보여줘야 한다.
특히 멀티에이전트에서는 더 그렇다. 기획 에이전트가 작업을 쪼개고, 실행 에이전트가 행동하고, 검토 에이전트가 결과를 정리했다면, 최종 결과만 보고 책임을 말할 수는 없다. 어느 단계에서 정책이 적용되었고, 어느 에이전트가 어떤 컨텍스트를 넘겼는지까지 이어져야 한다.
수정 가능한 로그는 감사 로그가 아니다
감사 가능성의 바닥은 무결성이다. 기록이 남아도 나중에 고칠 수 있다면, 그것은 증거가 아니라 소감문이다. 그래서 감사 레이어는 기본적으로 append-only, 즉 추가만 가능하고 수정·삭제는 제한되는 구조를 가져야 한다.27
실무에서는 보통 세 층을 함께 쓴다.
애플리케이션 레벨: 감사 API에 update와 delete 경로를 두지 않는다.
저장소 레벨: WORM 스토리지나 보존 잠금이 있는 객체 저장소를 사용한다.
암호학 레벨: 각 레코드에 이전 해시를 넣어 체인을 만들고, 필요하면 서명까지 붙인다.
해시 체인은 특히 유용하다. 중간 레코드 하나만 바뀌어도 그 뒤의 해시가 전부 달라지기 때문이다. 더 강한 요구가 있다면 머클 트리 기반 무결성 검증이나 외부 검증용 루트 해시 공개 방식도 쓸 수 있다.78
여기서 중요한 것은 "변조를 막는 것"과 "변조를 들키게 하는 것"을 함께 생각하는 일이다. 현실에서는 100% 방어보다, 누가 봐도 손댄 흔적이 남게 만드는 편이 더 강력할 때가 많다.
재현 가능한 실행 기록은 감사의 두 번째 축이다
감사 가능성은 기록만 잘 남기는 것으로 끝나지 않는다. 어느 시점에서는 반드시 이런 질문이 나온다.
"좋다. 그날 이런 실행이 있었다는 것은 알겠다. 그런데 그 결과를 다시 검토하거나 재생할 수 있는가?"
여기서 필요한 것이 재현 가능성이다. 물론 LLM 기반 시스템은 완전한 결정성을 보장하기 어렵다. 같은 프롬프트라도 모델 버전, 샘플링 설정, 컨텍스트, 도구 응답, 하드웨어 차이 때문에 결과가 달라질 수 있다.29 그래서 실무 목표는 "매번 한 글자도 다르지 않게 재생"보다 당시 실행 조건을 충분히 복원할 수 있게 만드는 것에 가깝다.
이를 위해 남겨야 할 것은 생각보다 많다.
모델 이름과 정확한 버전
시스템 프롬프트, 정책 번들, 워크플로 버전의 해시
사용한 도구와 도구 버전
입력 문서와 검색 결과의 버전 또는 콘텐츠 해시
샘플링 설정, 시드가 있으면 시드
실행 환경 정보와 주요 설정값
생성된 아티팩트의 해시
코딩 에이전트나 워크플로 에이전트라면 여기에 더해, 실제 LLM 요청과 응답을 추적 파일로 저장하고 나중에 같은 코드 경로를 재생하는 방식도 유용하다. 이런 방식은 장애 조사, 회귀 테스트, 신뢰도 점검에 특히 강하다.9 반대로 결과 증명이 중요한 분야에서는 실행 영수증이나 검증 가능한 receipt를 만들어, 다른 환경에서 같은 입력과 설정으로 다시 확인할 수 있게 하는 접근도 점점 중요해지고 있다.8
핵심은 이것이다. 감사 로그는 "있었다"를 증명하고, 재현 기록은 "왜 그 결과였는지 다시 확인할 수 있다"를 돕는다.
보존 기간과 내보내기 형식도 설계의 일부다
감사 시스템을 만들 때 의외로 늦게 생각하는 것이 보존이다. 하지만 감사는 남기는 기술이면서 동시에 얼마나 오래, 어떤 형식으로, 누구에게 보여줄 수 있는가의 문제다.2
보통은 다음처럼 계층을 나눈다.
최근 30~90일: 상세 원문과 메타데이터를 빠르게 조회할 수 있는 온스토리지
그 이후: 아카이브 중심의 저비용 스토리지
장기 보관: 규제와 법적 보존 요구에 맞춘 잠금 저장소
중요한 것은 단순히 오래 보관하는 것이 아니다. 분기별 감사, 사고 대응, 규제 제출, 내부 조사에 맞게 내보낼 수 있어야 한다. JSON이나 NDJSON은 기계 처리에 좋고, CSV는 감사팀과 레거시 도구에 여전히 유용하다. SIEM 연계를 위해 구조화된 내보내기 경로를 마련해 두는 것도 중요하다.2611
또 하나 빼먹기 쉬운 것이 법적 보존 조치다. 평소 보존 기간이 끝났더라도 분쟁이나 조사 중인 사건은 삭제하면 안 된다. 따라서 감사 저장소는 일반 보존 정책과 별도로 legal hold를 걸 수 있어야 한다.
컴플라이언스는 런타임 바깥에서 시작된다
감사 가능성은 런타임 로그만 잘 남긴다고 갑자기 완성되지 않는다. 그 앞단에 이미 조직 구조가 필요하다. 어떤 에이전트가 존재하는지 모르면 감사도 못 한다. 누가 소유자인지 모르면 수정도 못 한다. 어디서 배포됐는지 모르면 사고 범위도 모른다.10
그래서 조직 차원에서는 다음 세 가지가 필요하다.
중앙 에이전트 인벤토리 또는 레지스트리
에이전트별 고유 신원과 권한 수명 주기
공통 정책과 공통 감사 스키마를 강제하는 제어면
여기서 제어면이라는 말이 어렵게 들릴 수 있지만, 뜻은 단순하다. 모델이 바뀌고 프레임워크가 달라져도, 정체성·정책·감사 형식은 조직이 공통으로 관리한다는 뜻이다. 이렇게 해야 팀마다 제멋대로 로그를 남기지 않고, 나중에 하나의 언어로 질문할 수 있다.1011
실무적으로는 게이트웨이나 오케스트레이션 계층에서 감사 레코드를 집중 수집하는 방식이 유리하다. 특히 MCP나 외부 도구를 많이 쓰는 구조라면, 개별 도구 서버마다 제각각 남기는 것보다 중앙 경유 지점에서 누가 어떤 도구를 어떤 인자로 호출했는지 통일된 형식으로 남기는 편이 훨씬 낫다.11
작은 팀이 먼저 해야 할 다섯 가지
거대한 규제 플랫폼이 없어도, 감사 가능성은 지금 당장 시작할 수 있다. 특히 작은 팀이라면 다음 다섯 가지부터 해 두는 것이 좋다.
모든 실행에
run_id와trace_id를 붙인다.모든 에이전트에 고유 ID와 버전을 부여한다.
정책 판정과 승인 기록을 실행 기록과 같은 타임라인에 묶는다.
감사 이벤트를 append-only 저장소에 보내고 민감값은 마스킹한다.
분기별로 한 번씩 실제 사건을 골라 재구성 연습을 한다.
마지막 항목이 중요하다. 감사 가능성은 문서로 선언해서 생기지 않는다. 실제로 "지난달 이 실행을 다시 설명해 보라"는 훈련을 해 보면, 빠진 필드와 끊긴 링크가 바로 드러난다.4
성능보다 먼저 증명해야 할 것은 통제 가능성이다
AI 에이전트 제품을 도입할 때 팀은 자꾸 정확도와 속도를 먼저 묻는다. 물론 중요하다. 하지만 조직이 결국 돈을 내고 책임을 지는 것은 성능 그 자체가 아니라 통제 가능한 자동화다.
통제 가능성은 이렇게 증명된다. 어떤 에이전트가 있었고, 누가 불렀고, 무엇을 봤고, 어떤 정책이 적용되었고, 누가 승인했고, 무엇이 바뀌었고, 그 기록이 나중에 바뀌지 않았으며, 필요하면 다시 검토할 수 있다는 사실로 증명된다.35
이것이 바로 감사 가능성이다. 그리고 기업 환경에서는 이 능력이 성능만큼이나, 때로는 성능보다 더 중요하다. 아주 똑똑하지만 나중에 아무 설명도 못 하는 에이전트보다, 조금 덜 화려해도 기록과 책임이 분명한 에이전트가 훨씬 더 빨리 조직 안으로 들어간다.
좋은 하네스는 에이전트에게 도구를 주는 데서 끝나지 않는다. 그 도구 사용의 영수증까지 남긴다. 그래야 자동화가 마술이 아니라 시스템이 된다.
참고
1AI Agent Audit Logs: What to Record When Production Needs Receipts
2AI Agent Audit Trails: Compliance-Ready Activity Logging
3AI Agent Audit Trails: What CISOs Actually Need to Know
4AI Agent Audit Trails: Complete Compliance Guide
5Building trustworthy AI agents for compliance: The challenge of auditability and explainability
6AI Agent Audit Logs from the CLI
7Tutorial 04 — Audit Logging & Compliance
8Right to History: A Sovereignty Kernel for Verifiable AI Agent Execution
9GitHub - rylinjames/litmus: Record and deterministically replay AI agent executions
10Governance and security for AI agents across the organization
11MCP Audit Logs: Ensuring Compliance in Enterprise AI Applications
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.