. 학습 인사이트 — 하네스 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세대), OMC | Claude Code(지연로딩), 내 패턴 |
| 검증 강제력 ↔ 흐름 끊김 | gajae-code(sha256), 내 패턴(exit 2) | fable-ish(2회 후 허용), OMC(ADVISORY) |
| 모델 중립성 ↔ 수직 통합 | ouroboros(9 provider), OMC | Codex(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줄 요약
- 네 기둥(컨텍스트·툴·가드레일·검증)의 무게중심을 어디 두느냐가 “설계 결정”이고, 그 결정은 항상 무언가를 포기하는 트레이드오프다.
- 가장 성숙한 하네스일수록 모델에게 덜 맡기고 더 가둔다 — 자기보고 불신, 검증자 분리, 코드 강제가 핵심.
- “지켜지지 않으면 사고 나는 것”만 코드로 잠그고 나머지는 산문으로 — 이 균형 감각이 엔지니어의 눈이다.
[!question] 스스로 답해보기
- 에이전트가 “테스트 다 통과했습니다”라고 보고했다. 믿지 않으려면 내 하네스에 무엇을 둬야 하나? (힌트: 원칙 1·2)
- “오타 하나 고쳐줘”와 “결제 모듈 새로 만들어줘”에 같은 검증을 적용하면 안 되는 이유는? (힌트: 원칙 6)
- 문서에 “절대 rm -rf 하지 마”라고 써두면 충분할까, 아니라면 무엇으로 막아야 하나? (힌트: 원칙 5·10)
비개발자 전직 준비생을 위한 메타 교훈 5가지
- “되게 만들기”보다 “됐는지 증명하기”가 어렵다. 7종 모두 검증 루프에 가장 많은 설계를 쏟았다. 입문 시에도 “내 코드가 진짜 동작하는가”를 증거로 보는 습관을. (근거: fable-ish, gajae-code, 내 패턴)
- LLM은 동료가 아니라 “통제할 대상”이다. 똑똑하지만 거짓 보고를 한다는 전제에서 설계가 출발한다. “이 말이 사실인지 어떻게 확인하지?”를 항상 먼저 물어라.
- 제약이 자유보다 강하다. 성숙한 하네스(Codex, gajae-code, 내 패턴)일수록 모델을 덜 맡기고 더 가둔다. 입문자도 작은 범위를 명확히 정의해 시키는 쪽이 결과가 좋다.
- 회고가 설계를 만든다. 내 패턴 v2는 v1의 3대 결함(slug중복·drift·frontmatter 비대)을 진단해 다시 설계됐다. 실패를 기록하고 구조로 되먹이는 것이 진짜 엔지니어링.
- 솔직한 한계 명시가 신뢰다. fable-ish는 “우리는 보안 경계가 아니다”, gajae-code는 “beta/미입증”을 명시했다. 모르는 것·못 하는 것을 적는 정직함이 좋은 기술 문서의 조건.
연결
- 하네스엔지니어링이란 — 하네스의 정의와 네 기둥의 출발점
- _비교매트릭스 — 7종을 10축으로 비교한 원본 매트릭스
- 2_통합하네스_설계안 — 이 원칙들에서 “1등 메커니즘”만 골라 조합한 설계안
- 1_내패턴_개선백로그 — 원칙 10(코드 강제)의 자기 약점을 메우는 실행 백로그
- HOME
[!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 계약 의존”)은 원 분석에서 검증된 사실 그대로 유지했으며, 학습 흐름으로 재구성하는 과정에서 사실을 추가·변경하지 않았다.