발행 사고를 막는 다섯 겹 — 실수는 막고 작정은 못 막는다

한 줄 요약

GUI 커밋까지 걸리는 게이트를 만들고, 차단 키워드 목록을 두 개로 쪼갰다.

본문

겹쳐야 하는 이유

개인 사이트에서 오타는 고치면 된다. 올리면 안 되는 걸 올리는 것은 고칠 수 없다. 검색 캐시와 남의 사본에 남는다. 되돌릴 수 없는 사고는 확률을 낮추는 게 아니라 여러 겹으로 막아야 한다. 한 겹이 뚫려도 다음 겹이 남게.

지금 다섯 겹이다.

  1. 레포 비공개 — 레포 자체가 비공개고 사이트만 공개된다
  2. 볼트 분리 — 공개하면 안 되는 내용이 애초에 이 폴더에 없다
  3. drafts/ gitignore — 초안은 구조적으로 git에 들어갈 수 없다
  4. 커밋 전 검사 — publish 필드, 차단 키워드, 개인정보 패턴, drafts/ 추적 여부
  5. 신원 키워드 검사 — 실명·계정명이 어느 파일에든 있으면 커밋이 멈춘다

13은 구조고 45는 검사다. 구조가 더 세다. 검사는 내가 켜둬야 돌지만, 구조는 내가 뭘 하든 그대로 있다.

GUI로 커밋하면 게이트가 비는 문제

검사 스크립트를 pre-commit 훅으로 걸었는데, 여기 함정이 하나 있었다. .git/hooks/ 에 둔 훅은 git에 추적되지 않는다. 기기를 옮기면 사라지고, 무엇보다 다른 사람(또는 미래의 나)이 레포를 받아도 게이트가 없는 상태가 된다.

그래서 훅을 레포 안에 두고 git이 그걸 보게 했다.

git config core.hooksPath scripts/hooks

이게 중요한 이유는 따로 있다. 나는 Obsidian에서 obsidian-git 플러그인으로 커밋하는 일이 많다. GUI 커밋이 터미널 커밋과 다른 경로를 타서 게이트를 건너뛰는 것이 흔한 사고 지점인데, hooksPath 로 걸면 플러그인으로 커밋해도 똑같이 걸린다. 확인해보니 실제로 걸렸다.

차단 키워드를 두 개로 쪼갠 이유

차단 키워드 목록을 만들다가 이상한 걸 깨달았다. 실명과 계정명을 목록에 적으면 그 목록 파일이 레포에 올라가면서 가리려던 걸 내 손으로 발행한다.

그래서 두 개로 나눴다.

  • blocklist.txt — 공개돼도 되는 일반 키워드. 레포에 올라간다
  • blocklist.local.txt — 실명·계정명. .gitignore 대상이라 올라가지 않는다

검사 범위도 달리했다. 일반 키워드는 발행 폴더만 보지만, 신원 키워드는 추적되는 모든 파일을 본다. 실명이 README에 들어가는 건 본문에 들어가는 것과 똑같이 치명적이기 때문이다.

실제로 이 검사가 바로 일을 했다. 결정 기록 문서에 내 GitHub 계정명을 그대로 적었다가 커밋이 막혔다.

찾은 버그 하나

검사 스크립트가 발행 폴더가 비어 있으면 “검사할 게 없다”며 조기 종료하고 있었다. 즉 글이 한 편도 없는 지금, 신원 키워드 검사가 아예 돌지 않았다. 가장 중요한 검사가 가장 조용히 꺼져 있었던 셈이다. 순서를 바꿨다.

독자가 가져갈 것

  • git config core.hooksPath scripts/hooks — 훅을 레포에서 추적해 GUI 커밋도 걸리게
  • 차단 키워드에 실명을 넣으려면 목록 파일이 공개되는지 먼저 확인하라
  • 조기 종료(exit 0)가 있는 검사 스크립트는 아무것도 안 하는 상태를 통과로 보고하는지 확인하라

안 맞다고 본 지점

  • --no-verify 로 우회된다. 이 장치는 실수만 막고 작정한 행동은 못 막는다. 그 이상을 원하면 CI에서 다시 검사해야 하는데, 지금 규모에 비해 과하다고 봤다.
  • 계좌번호 패턴이 휴대폰번호와 겹쳐 중복 경고가 난다. 일부러 느슨하게 잡았다. 놓치는 쪽보다 과하게 잡는 쪽이 싸다고 판단했지만, 경고가 잦으면 사람이 경고를 무시하게 된다는 점에서 이게 옳은 균형인지는 아직 모르겠다.
  • blocklist.local.txt 는 커밋되지 않으므로 기기를 옮기면 사라진다. 없으면 검사가 경고만 내고 통과한다 — 가장 약한 고리다.

참고


체크리스트 (발행 전)

  • publish: true 로 변경했는가
  • tags 를 태그 체계에서 골랐는가 — ai tooling automation workstyle career personal 중 최대 2개
  • description 을 한 문장으로 채웠는가 (목록 페이지에 노출됨)
  • 회사·부서·동료·내부 자료 관련 내용이 섞이지 않았는가
  • scripts/check-publish.sh 를 통과하는가