ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 하네스 엔지니어링 9단계 베스트 프랙티스 #6. HITL 정책
    IT 2026. 4. 27. 22:00
    하네스 엔지니어링 9단계 베스트 프랙티스 #6. HITL 정책

    시리즈 맥락 복기

    Step 5에서 루프가 자율적으로 시작되고 끝날 수 있게 됐습니다. 자율성이 높아질수록 "사람이 개입할 지점"을 잘 정해야 합니다. 너무 많이 개입하면 자동화의 의미가 없고, 너무 적게 개입하면 사고가 납니다. Step 6의 HITL(Human-in-the-Loop) 정책이 바로 이 균형을 설계하는 단계입니다.

    1. #0 ~ #5 (이전 단계)
    2. #6 HITL 정책 ← 이번 편
    3. #7 감사 로그
    4. #8 측정 + 회고

    이 단계의 의미 — HITL은 하네스의 '브레이크 강도' 설정

    Step 4의 Hook이 "비상 브레이크"였다면, Step 6의 HITL은 "브레이크 강도 조절"입니다. 어떤 명령은 묻지 않고 지나가고, 어떤 명령은 확인 후 지나가고, 어떤 명령은 아예 막습니다. 이 등급 체계를 코드로 구현한 것이 Allow / Ask / Deny입니다.

    해결하려는 문제

    • "모두 Ask" 지옥: 안전 우선으로 설정하면 매 명령마다 물어봐서 자동화 효과가 사라집니다.
    • "모두 Allow" 사고: 반대로 다 허용하면 rm -rf 같은 사고가 터집니다.
    • 예외 없는 일률 정책: 모든 상황을 같은 기준으로 보면, 가벼운 작업조차 승인 버튼 노가다가 됩니다.

    효과 — HITL을 제대로 설계하면

    개인 경험상 HITL 정책을 제대로 쓰기 전과 후의 가장 큰 차이는 "승인 버튼 피로도"입니다. 카테고리 기반으로 Allow를 깔고, 위험한 패턴만 Deny로 막으면, 하루에 누르는 승인 버튼이 수십 번 → 거의 0이 됩니다. 사고도 안 나고요.

    베스트 프랙티스 1 — 위험도 공식으로 분류하라

    분류의 핵심은 공식 하나입니다.

    위험도 = 비가역성 × 영향 범위
    

    이 공식 하나면 새로운 명령이 나와도 어디에 배정할지 바로 결정됩니다.

    등급 기준 예시
    Allow 부작용 없거나 쉽게 되돌림 파일 읽기, git commit/push, 패키지 설치, 서비스 재시작
    Ask 되돌리기 비용 있음 rm 개별 파일, pip uninstall, 메타 파일 변경
    Deny 복구 불가 rm -rf /, git reset --hard, git push --force

    베스트 프랙티스 2 — 이중 방어로 변형을 잡아라

    단일 방어선은 우회되기 쉽습니다. 예컨대 rm -rf *를 막아도 rm --recursive --force ~/는 통과해 버립니다. 문자열 매칭(settings.json) + 정규식 매칭(safety.py) 두 겹으로 방어합니다.

    1계층 — settings.json deny

    "deny": [
      "Bash(rm -rf *)",
      "Bash(git reset --hard*)",
      "Bash(git push --force*)",
      "Bash(chmod -R 777*)"
    ]
    

    2계층 — safety.py 정규식

    DENY_PATTERNS = [
        (r"rm\s+.*(-r\s.*-f|-f\s.*-r|-rf|-fr)\s+(/\s|~/?\s|/home)",
         "시스템/홈 디렉토리 대량 삭제 차단"),
        (r"git\s+push\s+.*(-f|--force)",
         "git push --force 차단"),
        (r"chmod\s+(-R\s+)?777\s+(/\s|~/?\s|/home)",
         "넓은 범위 권한 해제 차단"),
        # ... 총 8개 패턴
    ]
    

    settings.json은 rm -rf *라는 문자열만 잡지만, safety.py는 rm -f -r /home 같은 변형까지 잡습니다. 차단 시 감사 로그(#7 단계)에 기록하고 sys.exit(2)로 즉시 중단합니다.

    베스트 프랙티스 3 — 정책 개선 루프를 문서에 명시

    HITL 정책은 완성품이 아니라 진화하는 것입니다. 운영하면서 나오는 피드백을 받아 등급을 승격·강등합니다.

    diagram

    피드백을 정책에 매핑하기

    • 서버 코드 수정 후 재시작 → Allow (묻지 않고 바로 재시작)
    • 설치 작업 → Allow (묻지 않고 진행)
    • GPU 작업 → Hook으로 강제 (스케줄러 필수)
    • 메타 파일 변경 → Ask (PR 생성 필수)
    • rm 명령 → Ask (개별 파일도 확인, 대량 삭제는 Deny)

    화이트리스트 vs 블랙리스트 — 어느 쪽을 택할까

    오래 운용해 보면 결론은 명확합니다.

    방식 장점 단점
    화이트리스트 (허용한 것만) 이론적으로 가장 안전 허용 목록이 수백 줄로 폭발. 결국 불편해서 * 와일드카드 남발
    블랙리스트 (위험한 것만 차단) 목록 관리가 간결 · 워크플로우 방해 최소 Deny 패턴을 꼼꼼히 짜야 함

    개인적으로는 카테고리 기반 Allow(Bash(git *) 같은 와일드카드) + 정규식 Deny 조합을 권합니다. 실질적으로는 블랙리스트 방식이죠.

    자주 빠지는 실수

    • Deny 패턴을 대충 짜기: 변형까지 생각하지 않으면 우회당합니다. 정규식을 최소 5개 변형에 대해 테스트해 보세요.
    • Allow 목록에 rm 넣기: 쉬워 보여도 돌이킬 수 없는 사고를 유발합니다. 절대 Allow에 넣지 않습니다.
    • 정책과 settings.json 동기화 누락: CLAUDE.md 문서와 실제 설정이 다르면 혼란만 쌓입니다. 변경 시 항상 같이 업데이트.

    다음 단계 예고 — Step 7 감사 로그

    HITL 정책이 등급을 정의했다면, Step 7의 감사 로그는 그 정책이 실제로 어떻게 동작했는지 기록하는 단계입니다. 무엇이 허용됐고, 무엇이 차단됐고, 어떤 파이프라인이 돌아갔는지 JSONL로 남깁니다.

    한 줄 요약: "HITL은 '자동화의 속도'와 '사고의 비용' 사이의 다이얼이다. 공식과 이중 방어로 조절하라."


    이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.

Designed by Tistory.