-
하네스 엔지니어링 9단계 베스트 프랙티스 #7. 감사 로그IT 2026. 4. 27. 22:10
시리즈 맥락 복기
#6 HITL 정책에서 Allow/Ask/Deny 등급을 세웠습니다. 이제 그 정책이 실제로 어떻게 동작했는가를 남겨야 합니다. 감사 로그가 없으면 "한 달 전 왜 이 명령이 차단됐는가", "이 파이프라인이 하루에 몇 번 돌았는가" 같은 질문에 답할 수 없습니다.
이 단계의 의미 — 감사 로그는 하네스의 '블랙박스'
감사 로그는 말 그대로 항공기의 블랙박스에 해당합니다. 평소엔 존재감이 없지만, 사고가 나거나 개선 포인트를 찾을 때 결정적인 단서가 됩니다. 하네스 엔지니어링에서도 마찬가지로, 에이전트가 무엇을 했는지 쿼리 가능한 형태로 축적해야 이후의 측정·회고가 가능해집니다.
해결하려는 문제
- "이 명령이 언제 실행됐지?": 며칠 전 사고 원인을 추적할 수 없으면 재발 방지가 불가합니다.
- "이 차단은 뭐였지?": Deny가 걸린 이력이 없으면 정책 개선 자료가 사라집니다.
- "어떤 파이프라인이 제일 많이 도는가?": 실제 사용 빈도를 모르면 최적화 우선순위를 못 정합니다.
효과 — 로그 하나로 바뀌는 것
감사 로그가 있으면 "감"에 의존하던 의사결정이 숫자 기반으로 바뀝니다. "자주 쓰는 Skill 상위 3개는 무엇인가", "차단된 명령 중 오탐은 몇 %인가" 같은 질문에
jq한 줄로 답할 수 있게 됩니다.베스트 프랙티스 — JSONL + 자동 태깅
감사 로그의 형식은 JSONL(JSON Lines)을 권합니다. 파일에 한 줄 = 한 이벤트 구조라서, 중간에 append만 해도 파일이 망가지지 않고
jq같은 도구로 쉽게 조회할 수 있습니다.{ "ts": "2026-04-15T14:23:11+09:00", "tool": "Bash", "hook": "PostToolUse", "session": 129677, "cmd": "git push origin main", "exit_code": 0, "tags": ["git", "push"], "pipeline": "calendar_sync" }필드 설계 원칙
ts: ISO 8601 타임존 포함. 나중에 시간별 분석을 위해 필수.tool+hook: 어느 훅에서 발생한 이벤트인지 구분.session: 세션 PID로, 같은 세션의 이벤트를 묶어서 볼 수 있음.cmd: 500자까지만 저장. 긴 스크립트로 로그가 오염되는 걸 방지.exit_code: 성공/실패 판별.tags: 자동 분류 키워드 (아래 참조).pipeline: 어떤 Skill/파이프라인에 속한 작업인지.
자동 태깅 규칙 — 명령어를 분류하는 9가지 패턴
명령어에 정규식을 매칭해 태그를 자동 부여합니다. 한 번 정의해 두면 이후 쿼리가 엄청나게 쉬워집니다.
명령 패턴 태그 git commit["git", "commit"] git push["git", "push"] gh pr / gh issue["github", "api"] curl / wget["network"] pip install / npm install["install"] rm["delete"] sudo["sudo"] 차단된 명령["blocked"] 특정 파이프라인 스크립트["pipeline"] 실제 쿼리 예시
JSONL이면
jq로 이런 질문을 한 줄씩 바로 답할 수 있습니다.# 차단된 명령만 조회 jq 'select(.tags[] == "blocked")' audit.jsonl # 특정 날짜의 git 작업 jq 'select(.ts | startswith("2026-04-15")) | select(.tags[] == "git")' audit.jsonl # 파이프라인별 실행 횟수 상위 jq -r '.pipeline // "none"' audit.jsonl | sort | uniq -c | sort -rn # 세션별 명령 수 jq -r '.session' audit.jsonl | sort | uniq -cHook이 감사 로그를 남기는 구조
설계 3원칙
- 실패해도 본 작업을 막지 않는다: 로깅은
try / except: pass로 감싸세요. 로그 실패가 사용자 작업을 중단시키면 안 됩니다. - 명령어는 500자까지만 기록: 긴 스크립트가 파이프로 들어와도 로그가 비대해지지 않도록.
- 로그 파일은
.gitignore에 포함: 민감한 명령어가 들어갈 수 있으므로 Git에 올라가지 않게.
로깅 코드 — 핵심 로직은 20줄
def log_event(*, tool: str, hook: str, session=None, cmd: str = "", exit_code=None, pipeline=None, extra=None): """감사 이벤트를 JSONL로 기록. 실패해도 본 작업을 막지 않는다.""" AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True) entry = { "ts": datetime.now().astimezone().isoformat(), "tool": tool, "hook": hook, "session": session, "cmd": cmd[:500], # ← 500자 제한 "exit_code": exit_code, "tags": _classify_tags(cmd), "pipeline": pipeline, } if extra: entry.update(extra) try: with open(AUDIT_LOG, "a") as f: f.write(json.dumps(entry, ensure_ascii=False) + "\n") except Exception: pass # ← 로그 실패 무시이 20줄이 운영 중인 모든 Hook에서 공유됩니다. 한 번 만들어 두면 새 파이프라인을 추가할 때 태그 규칙 한 줄만 더하면 됩니다.
자주 빠지는 실수
- JSON 배열로 로그 만들기: 파일 전체가 배열이면 append 할 때마다 끝 괄호를 고쳐야 합니다. 반드시 JSONL을 쓰세요.
- 타임스탬프에 타임존 누락: 나중에 분석할 때 UTC/KST 혼동이 생깁니다. ISO 8601 타임존 포함 형식이 안전합니다.
- 민감 명령어를 그대로 저장: 비밀번호·API 키가 포함된 명령은 마스킹하거나 태그로만 기록.
다음 단계 예고 — Step 8 측정 + 회고
감사 로그가 쌓이면 드디어 정량 측정이 가능해집니다. 다음 편이자 마지막 편에서는 파이프라인 상태 추적, 세션 격리, 감사 로그 기반의 Before/After 측정 방법을 다룹니다.
한 줄 요약: "측정 가능한 로그 없이 개선 가능한 자동화는 없다."
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
테스트 커버리지 11개 프로젝트에 도입하기 — baseline-lock + 외부 wrapper 제외 전략 (2) 2026.04.28 mypy로 파이썬 프로젝트 5개에 타입 에러 0 만들기 — 단계적 도입과 Hook 강제 (0) 2026.04.28 shellcheck로 bash 스크립트 정리하기 — 그리고 Hook으로 재발 방지까지 (0) 2026.04.28 ruff로 10개 프로젝트 린트 통과시키기 — 246 → 0, 그리고 실제 버그 2건 발견 (1) 2026.04.28 하네스 엔지니어링 9단계 베스트 프랙티스 #8. 측정과 회고 (0) 2026.04.27 하네스 엔지니어링 9단계 베스트 프랙티스 #6. HITL 정책 (0) 2026.04.27 하네스 엔지니어링 9단계 베스트 프랙티스 #5. 자동 트리거와 완료 조건 (0) 2026.04.27 하네스 엔지니어링 9단계 베스트 프랙티스 #4. 검증 (Hook) (0) 2026.04.27 하네스 엔지니어링 9단계 베스트 프랙티스 #3. Skill 정의 (0) 2026.04.27 하네스 엔지니어링 9단계 베스트 프랙티스 #2. Code Wiki 작성 (0) 2026.04.27