지식위키

. 학습 인사이트 — 하네스 7종의 '설계 결정과 그 이유'

3. 학습 인사이트 — 하네스 7종의 “설계 결정과 그 이유”

비개발자 → 개발자 전직 준비생용 하네스 엔지니어링 학습 노트. “무엇을 만들었나”가 아니라 “왜 그렇게 결정했고, 무엇을 포기했나(트레이드오프)” 를 읽는 훈련용. 대상: Claude Code · Codex · oh-my-claudecode(OMC) · gajae-code · ouroboros · fable-ish · 내 패턴.


한 줄 요약

하네스 설계의 절반은 “똑똑하지만 거짓 보고하는 모델을 어떻게 못 믿을 것인가”를 코드로 못박는 일이다. 7종을 가로지르는 10개 원칙·8개 트레이드오프를 익히면 “기능을 더한다”가 아니라 “위험과 비용을 어디에 쓸지 고른다”는 엔지니어의 눈이 생긴다.

왜 배우나: “AI에게 다 맡기기”의 함정을 피하고 “됐는지 증명하기”를 습관으로 만드는 사고 틀을 얻기 위해.


그림

하네스의 네 기둥과, 그 위에서 7종이 서로 다른 무게중심으로 내리는 설계 결정의 흐름.

flowchart TD
    M["언어모델<br/>(다음 토큰만 예측, 자기보고는 못 믿음)"]
    M --> C["① 컨텍스트<br/>무엇을 보여줄지"]
    M --> T["② 툴<br/>읽기·쓰기·실행"]
    M --> G["③ 가드레일<br/>위험한 짓 차단"]
    M --> V["④ 검증 루프<br/>진짜 됐는지 확인"]

    C --> D["설계 결정<br/>= 네 기둥의 무게중심을<br/>어디에 둘 것인가"]
    T --> D
    G --> D
    V --> D

    D --> TO["트레이드오프<br/>무엇을 얻으면 무엇을 잃나"]
    TO --> H["7종 하네스의 서로 다른 선택"]
flowchart LR
    A["모호한 요청"] -->|① 모호성 게이트| B["명확한 작업"]
    B -->|② 위험도 분류| C["작업 실행"]
    C -->|"③ 컨텍스트=예산"| D["변경 산출물"]
    D -->|④ 다층 가드레일| E["안전 통과"]
    E -->|"⑤ 검증자=작업자 분리"| F["완료 증명<br/>(코드로 강제)"]
    F -->|⑥ 세션 넘는 영속화| G["다음 세션 재주입"]
    G -.같은 실수 반복 금지.-> A

쉽게 풀기

”하네스(harness)“가 뭔가

하네스 = 언어모델을 실제로 일하게 만드는 바깥 껍데기다. 모델은 “속독·암산 천재이지만 책상 밖으로 나가본 적 없는 사람”이라, 혼자서는 다음 단어만 맞힐 뿐 파일을 열거나 코드를 실행하지 못한다. 이 천재를 코딩 직원으로 바꾸려면 옆에서 ① 컨텍스트를 골라 책상에 올려주고, ② 툴을 쥐어주고, ③ 가드레일로 막고, ④ 검증 루프로 “진짜 됐는지” 확인해야 한다. 이 네 가지를 묶는 보조기구가 하네스다(말의 멍에·안전벨트 harness에서 온 말).

이 네 기둥을 누가 어떻게 짜느냐가 하네스의 정체성이고, 7종은 같은 문제를 서로 다른 무게중심으로 푼다. 그 차이가 곧 “설계 결정”이다.

[!important] 모든 설계의 출발점 LLM은 똑똑하지만 거짓말(자기보고)을 한다. 그래서 좋은 하네스의 절반은 “모델을 어떻게 못 믿을 것인가”를 설계하는 일이다.

10개 원칙 — “상황 → 결정 → 이유”

외우지 말고 “나라면 어떤 트레이드오프를 고를까”를 상상하며 읽어라. 원칙들은 결국 아래 한 축으로 수렴한다 — 모델을 덜 믿고 더 가두기.

flowchart LR
    subgraph 신뢰[모델을 못 믿는다]
        P1["1 완료 코드강제"]
        P2["2 검증자 분리"]
        P10["10 코드>산문"]
    end
    subgraph 절약["비용·복잡도 관리"]
        P4["4 컨텍스트=예산"]
        P6["6 위험 비례"]
        P8["8 표면 좁히기"]
    end
    subgraph 통제[변동성 가두기]
        P3["3 모호성 게이트"]
        P9["9 제한된 변환기"]
    end
    subgraph 축적[지식 살리기]
        P5["5 다층 방어"]
        P7["7 세션 영속"]
    end
  • 원칙 1 — “다 했다”는 말을 믿지 마라. 종료 시점에 검증 게이트를 놓고, 미검증이면 종료 자체를 막는다. 자기보고는 비용이 싸서 모델이 남발하니 관찰 가능한 증거(테스트 통과·diff·체크섬)만 믿는다.
    • 비유: “다 풀었어요”라 해도 답안지로 채점하기 전엔 시험 끝을 인정 안 하는 감독관.
  • 원칙 2 — 검증자와 작업자를 분리하라. 같은 에이전트가 짜고 스스로 승인하면 거짓 합격(false approval)이 난다. 검증을 독립 에이전트·세션·스크립트로 떼어 자기승인을 구조적으로 막는다.
    • 비유: 출제자=채점자면 안 되는 이유. OMC는 거짓 합격 비용을 “정상 대비 10~100배”로 본다.
  • 원칙 3 — 시작 전에 모호성을 없애라. “쇼핑몰 만들어줘”로 바로 들어가면 모델이 멋대로 가정하고 다 짠 뒤 “이게 아닌데”가 된다. 인터뷰로 모호성을 수치화해 임계값 아래로 떨어질 때까지 실행을 막는다. 앞에서 막는 게 압도적으로 싸다.
  • 원칙 4 — 컨텍스트는 예산이다. 많이 넣을수록 비싸고, 핵심이 묻히고, 캐시가 깨진다. “지연 로딩”, “매니페스트만 반환”, “1태스크=1단위 fresh 실행”으로 아낀다.
    • 비유: 회의 자료를 다 쌓기보다 안건에 필요한 한 장만 그때 꺼내는 것.
  • 원칙 5 — 위험한 권한은 여러 겹으로 막아라. 정규식 한 줄은 우회된다(fable-ish 자체 측정: 위험 패턴 16개 중 4개만 잡힘). OS 샌드박스 + 실행 정책 + 정적 판정 + LLM 검토를 독립적으로 겹겹이 쌓아 한 겹이 뚫려도 다음이 잡게 한다(defense in depth).
  • 원칙 6 — 안전·검증은 위험에 비례시켜라. 오타 수정에도 풀 검증을 돌리면 느려서 사용자가 하네스를 꺼버린다. quick/normal/deep/blocked로 분류해 검증 깊이를 차등한다.
  • 원칙 7 — 상태를 세션 너머로 살려라. 결정·함정·관계를 디스크(마크다운/jsonl/SQLite/이벤트스토어)에 영속화하고 다음 세션에 재주입해 지식이 복리로 쌓이게 한다(Karpathy식 누적).
  • 원칙 8 — 표면을 좁혀라. 스킬·모드·에이전트를 자꾸 더하면 모델이 일관되게 못 따르고 프롬프트 예산이 새고 라우팅이 복잡해진다. 의도적으로 수를 제한하고 좁은 워크플로우를 테스트로 못박는 게 낫다.
  • 원칙 9 — 모델은 “제한된 변환기”로 써라. “알아서”라고 열어두면 매번 다른 결과(비결정성). 결정적 파이프라인의 양 끝(입력 준비·출력 검증)을 코드로 봉인하고 가운데의 LLM은 “정해진 변환”만 하게 가둔다.
    • 비유: 요리사에게 “맛있게”가 아니라 “이 레시피대로 이 단계로”.
  • 원칙 10 — 자동 강제와 산문 규칙을 구별하라. “런타임이 강제하지 않으면 규칙은 권고일 뿐” 이다. 정말 막아야 하는 건 훅·exit code·샌드박스로 코드 강제하고, 산문은 가이드로만.

핵심 정리

10개 원칙 한눈에

#원칙한 줄 핵심
1완료를 코드로 강제자기보고 대신 관찰 가능한 증거만 신뢰
2검증자/작업자 분리자기승인 금지 — 거짓 합격은 비대칭적으로 비쌈
3모호성 게이팅막연하면 실행 차단, 앞에서 막는 게 쌈
4컨텍스트는 예산풍부함보다 경제성을 1급 제약으로
5다층 가드레일정규식 한 겹 불신, 독립 방어선 중첩
6위험 비례 차등안전은 위험 있는 곳에만
7세션 넘는 영속성지식을 복리로 누적
8표면 좁히기기능 난립보다 방법론 못박기
9제한된 변환기비결정성을 좁은 구간에 가두기
10코드 강제 vs 산문코드만이 진짜 잠근다

모든 원칙은 “무언가를 얻으면 무언가를 잃는” 교환이다 — 아래에 원칙별로 “포기한 것”을 모았다.

[!note]- 펼쳐보기: 원칙별 “포기한 것”

  • 1: 게이트가 빡빡할수록 안전하지만, 검증 불가능한 작업(디자인 토론 등)에서 흐름이 끊긴다. fable-ish는 “2회 차단 후 무조건 허용”으로 타협 → 대가로 deep 작업이 미검증 통과 가능.
  • 2: 검증 에이전트를 한 번 더 돌리면 비용·지연 2배. 모든 작업에 적용하면 느리고 비싸다.
  • 3: 게이트가 빡빡하면 “그냥 빨리 해줘”가 안 된다. 간단한 작업까지 심문당하는 마찰 → 위험도별 차등(원칙 6) 필요.
  • 4: 아끼면 싸고 빠르지만 모델이 “전체 그림”을 못 봐 국소적 결정만. 풍부함 ↔ 비용/정밀도의 정면 교환.
  • 5: 겹이 많을수록 안전하나 설치·디버깅·유지보수가 무거워진다(Codex 120+ 크레이트의 대가). 경량 도구(fable-ish)는 “우리는 보안 경계가 아니다”라고 솔직히 포기.
  • 6: 분류가 휴리스틱이라 오분류 위험. “위험한데 quick으로 분류”되면 그대로 통과.
  • 7: 파일은 단순·이식 쉬움 vs 구조화 쿼리·대규모 누적엔 약함. SQLite/이벤트소싱은 강력 vs 복잡·학습곡선·디버깅 부담.
  • 8: 좁히면 일관·강제 쉬움 vs “이건 못 해요”가 늚. 넓히면 만능 vs 복잡도·파괴적 변경 빈발.
  • 9: 봉인할수록 재현성·신뢰 ↑ vs 창의적 문제해결 여지 ↓. 정형 작업엔 최적, 탐색적 작업엔 족쇄.
  • 10: 코드 강제는 진짜 잠그지만 만들기 어렵고 유연성 없음. 산문은 쉽고 유연하나 안 지켜짐. 핵심 규율만 코드로, 나머지는 산문이 현실적 균형.

반복 등장한 8개 트레이드오프 축

각 축은 7종이 양 극단 사이 어디쯤에 자리잡았는지를 보여준다.

flowchart LR
    L["자율·풍부·유연<br/>ouroboros, 내 패턴"] <-->|어디에 설까| R["통제·경제·강제<br/>Codex, gajae-code"]
    L -.. "자율↔안전 / 컨텍스트↔비용 / 산문↔코드강제" ..-> R
한쪽 끝 (대표)반대쪽 끝 (대표)
자율성 ↔ 안전ouroboros, 내 패턴Codex(4중·fail-closed), gajae-code
컨텍스트 ↔ 비용/지연ouroboros(30세대), OMCClaude Code(지연로딩), 내 패턴
검증 강제력 ↔ 흐름 끊김gajae-code(sha256), 내 패턴(exit 2)fable-ish(2회 후 허용), OMC(ADVISORY)
모델 중립성 ↔ 수직 통합ouroboros(9 provider), OMCCodex(OpenAI 종속), Claude Code
단일 강력 ↔ 조합 가능Codex(단일), ouroboros(926py)Claude Code(플러그인·MCP), fable-ish
표면 넓힘 ↔ 좁힘OMC(만능·라우팅 복잡)gajae-code, fable-ish
영속성 단순(파일) ↔ 강력(DB)내 패턴·Claude Code(마크다운)ouroboros(이벤트소싱·감사)
코드 강제 ↔ 산문 유연Codex(Starlark·샌드박스)내 패턴·gajae·OMC(자기인정 약점)

[!tip]- 펼쳐보기: 각 축의 교훈

  • 자율성↔안전: “되돌릴 수 없는 행동(rm -rf, git push —force)“에만 게이트를 집중하는 게 효율적.
  • 컨텍스트: “넣을 수 있다”와 “넣어야 한다”는 다르다. 기본 최소, 필요 시 끌어오기(lazy).
  • 검증 강제력: 무한 차단은 사용자가 하네스를 꺼버리게 만든다. “탈출구 있는 압박”이 현실적.
  • 모델 중립성: 중립성=벤더 락인 회피 보험, 통합=최신 모델·기능 우선 속도. 정답 없음.
  • 단일↔조합: 확장 표면을 표준화하면 생태계가 자란다. 단, 표준이 블랙박스면 검증 불가라는 대가.
  • 표면: 초기엔 좁게 시작해 방법론을 굳히고, 검증된 패턴만 표면으로 승격.
  • 영속성: 학습용·소규모는 마크다운으로 충분. 감사·재현이 핵심이면 이벤트소싱.
  • 코드↔산문: “지켜지지 않으면 사고 나는 것”만 코드로. 나머지는 산문으로 모델 판단에 맡기는 게 비용 효율적.

실제 예시

각 원칙이 7종에서 어떤 메커니즘으로 구현됐는지 — 근거(프레임워크/메커니즘)를 그대로 보존한 매핑이다. 분량이 크므로 접어 둔다.

[!note]- 펼쳐보기: 전체 설계 결정 → 근거 프레임워크(메커니즘) 매핑

완료를 코드로 강제 (Stop 게이트)
  fable-ish   : "관찰 가능한 검증 통과 전엔 완료 금지"를 Stop 훅으로 block
  gajae-code  : sha256 영수증으로 완료를 fail-closed 증명
  내 패턴      : gate.mjs exit 2 물리 게이트

검증자/작업자 분리 (자기승인 금지)
  OMC         : critic 적대적 리뷰 + self-approve 금지
  Codex       : Guardian 전용 LLM 세션이 승인 담당
  내 패턴      : Claude=적대검증 / Codex=워커, 모델 경계 분리 (validate.mjs 코드 강제)
  ouroboros   : 구현=UNRESTRICTED vs 평가=READ_ONLY 권한 분리

모호성 게이팅 (실행 전 차단)
  ouroboros   : ambiguity = 1 − Σ(clarity·weight), ≤0.2 게이트 통과해야 Seed 생성
  gajae-code  : deep-interview 가중 차원 점수, Round 0 토폴로지 락
  OMC         : deep-interview, ralplan이 막연한 요청 자동 게이팅

컨텍스트 = 예산 (지연로딩/캐시)
  Claude Code : 서브에이전트·스킬 지연로딩 = 컨텍스트 경제학
  gajae-code  : append-only StablePrefix로 prefix-cache 적중 극대화
  Codex       : diff 기반 최소 업데이트 = 프롬프트 캐시 친화
  내 패턴      : 매니페스트만 반환·fresh exec로 누적 0

다층 가드레일 (defense in depth)
  Codex       : 4중(OS샌드박스 3종 + Starlark 정책 + 정적 패치판정 + LLM Guardian), 각각 독립 작동
  gajae-code  : plan-mode-guard + bash 화이트리스트 + bridge fail-closed + PAT 격리
  fable-ish   : 역설적 근거 — 정규식 한계 인정, 하드차단을 permissions.deny에 위임

위험 비례 차등
  fable-ish   : 위험비례 동적 탈출조건
  Claude Code : 모델 티어별 비용/정밀도 분배 (싼 모델=잡일, 비싼 모델=핵심)
  OMC         : haiku/sonnet/opus 에이전트 frontmatter 명시
  Codex       : PermissionProfile 단일 권한 계약

세션 간 영속성
  Codex       : jsonl rollout + SQLite state + memories + thread-store
  OMC         : 멀티레포·워크트리·다층 메모리, PreCompact 훅으로 압축 직전 flush
              : 구조화 git trailers로 의사결정을 git 히스토리에 영속화
  ouroboros   : 이벤트소싱 → replay/resume/lineage 1급, 재부팅 후 lineage 재구성
  내 패턴      : LLM Wiki MEMORY.md 인덱스

표면 좁히기
  gajae-code  : 4스킬 + 4에이전트만, 테스트·검증으로 강제 → 스킬 난립 차단
  fable-ish   : 훅 3개 + 스킬 1개 단일 플러그인
  [반례]OMC   : "zero learning curve" 표방하나 19에이전트·40스킬·11훅 →
                라우팅 복잡, 별도 mode-selection-guide 필요

LLM = 제한된 변환기
  내 패턴      : prepare→runner→admit→validate→build 결정적 파이프라인,
                edge-map으로 타깃 미리 주입 후 "타깃 추가/삭제 금지" (창작 아닌 변환)
  ouroboros   : 결정적 router로 9개 provider 동일 실행
  Codex       : code-mode로 도구를 타입드 JS 실행면으로 노출

코드 강제 vs 산문
  Codex       : Starlark 정책 · OS 샌드박스 = 코드 강제
  내 패턴      : (약점 인정) PreToolUse 차단 등 hooks가 settings.json에 전무, 규율이 산문 의존
  gajae-code  : (약점) 자연어 .md 계약 의존, 모델이 게이트 건너뛰면 일부만 커버
  OMC         : (약점) verify-deliverables가 ADVISORY 비차단 → 검증 강제력 구멍

요약 & 셀프체크

3줄 요약

  1. 네 기둥(컨텍스트·툴·가드레일·검증)의 무게중심을 어디 두느냐가 “설계 결정”이고, 그 결정은 항상 무언가를 포기하는 트레이드오프다.
  2. 가장 성숙한 하네스일수록 모델에게 맡기고 가둔다 — 자기보고 불신, 검증자 분리, 코드 강제가 핵심.
  3. “지켜지지 않으면 사고 나는 것”만 코드로 잠그고 나머지는 산문으로 — 이 균형 감각이 엔지니어의 눈이다.

[!question] 스스로 답해보기

  1. 에이전트가 “테스트 다 통과했습니다”라고 보고했다. 믿지 않으려면 내 하네스에 무엇을 둬야 하나? (힌트: 원칙 1·2)
  2. “오타 하나 고쳐줘”와 “결제 모듈 새로 만들어줘”에 같은 검증을 적용하면 안 되는 이유는? (힌트: 원칙 6)
  3. 문서에 “절대 rm -rf 하지 마”라고 써두면 충분할까, 아니라면 무엇으로 막아야 하나? (힌트: 원칙 5·10)

비개발자 전직 준비생을 위한 메타 교훈 5가지

  1. “되게 만들기”보다 “됐는지 증명하기”가 어렵다. 7종 모두 검증 루프에 가장 많은 설계를 쏟았다. 입문 시에도 “내 코드가 진짜 동작하는가”를 증거로 보는 습관을. (근거: fable-ish, gajae-code, 내 패턴)
  2. LLM은 동료가 아니라 “통제할 대상”이다. 똑똑하지만 거짓 보고를 한다는 전제에서 설계가 출발한다. “이 말이 사실인지 어떻게 확인하지?”를 항상 먼저 물어라.
  3. 제약이 자유보다 강하다. 성숙한 하네스(Codex, gajae-code, 내 패턴)일수록 모델을 맡기고 가둔다. 입문자도 작은 범위를 명확히 정의해 시키는 쪽이 결과가 좋다.
  4. 회고가 설계를 만든다. 내 패턴 v2는 v1의 3대 결함(slug중복·drift·frontmatter 비대)을 진단해 다시 설계됐다. 실패를 기록하고 구조로 되먹이는 것이 진짜 엔지니어링.
  5. 솔직한 한계 명시가 신뢰다. fable-ish는 “우리는 보안 경계가 아니다”, gajae-code는 “beta/미입증”을 명시했다. 모르는 것·못 하는 것을 적는 정직함이 좋은 기술 문서의 조건.

연결

[!tip] Codex 교차검증 보존 본 노트의 원칙·트레이드오프 분류와 근거 매핑은 7종 프레임워크 분석(Claude Code · Codex · oh-my-claudecode · gajae-code · ouroboros · fable-ish · 내 패턴) 결과를 종합한 것이다. 각 근거의 메커니즘(sha256 영수증, exit 2 게이트, ambiguity ≤0.2, StablePrefix, 4중 가드레일, 이벤트소싱 등)과 자기인정 약점(내 패턴의 “규율이 산문 의존”, OMC의 verify-deliverables ADVISORY 비차단, gajae-code의 “.md 계약 의존”)은 원 분석에서 검증된 사실 그대로 유지했으며, 학습 흐름으로 재구성하는 과정에서 사실을 추가·변경하지 않았다.