하네스 엔지니어링(Harness Engineering)
AI가 실수를 못하게 하기위해 규칙과 울타리를 설계하는 기술 — 제어의 기술
- 하네스(Harness)는 원래 말에 채우는 마구(馬具)에서 유래한 단어로, AI 맥락에서는 AI 모델을 안전하고 제어 가능하게 “장착”하는 구조적 틀을 의미
- 강력한 것을 제어하여 유익하게 활용한다는 의미로 쓰이며, AI에서는 올바른 방향으로 제어하면서 최대한 활용하기 위한 구조를 일컫는 표현
[말을 비유로 이해]
AI 에이전트를 거대한 짐말(draft horse)이라고 생각
- 에이전틱 엔지니어링 = 말 훈련
- 추론 루프 설계, 멀티 에이전트 조율, 도구 사용법 교육 → 말 자체를 더 강하게 만드는 것
- 하네스 엔지니어링 = 마구 제작
- 가죽 끈, 고삐, 수레를 만드는 것 → 말이 밭을 갈 수 있도록 방향과 한계를 정해주는 장비
말을 아무리 잘 훈련시켜도, 마구 없이는 밭을 갈 수 없음
하네스란 AI 에이전트가 가장 안전하고 예측 가능한 방식으로 작동하도록 설계된 제어 구조의 전체
- AI의 불확실성(환각, 편향 등)을 억제하고 비즈니스 로직 안에서만 작동하게 만드는 울타리
- 가드레일(Guardrails) 설정, 출력 형식의 강제(JSON 등), 에러 핸들링, 그리고 결과물이 정확한지 검증하는 Evals(평가) 체계 구축
- 아무리 똑똑한 에이전트라도 하네스(안전장치)가 없다면 실제 서비스로 출시하기 어려움
AI에게 잘 일할 수 있는 환경을 설계하는 것 - [팀원처럼 위임하는 방식]
- 규칙, 작업구조를 미리 합의
- 검증 기준을 사전에 정의
- 실행 루프로 반복 개선
- 일관된 고품질 결과물
하네스의 역할
하네스는 단순히 AI 에이전트를 동작시키는 데 그치지 않고, 3가지 기능을 통합적으로 담당
- 제어(Control) : 에이전트가 허용된 범위 밖의 행동을 하지 않도록 제안하는 구조
- 감시(Monitoring) : 에이전트 동작 상태와 출력 결과를 실시간으로 추적 및 기록하는 구조
- 개선(Feedback) : 오류나 이상 동작을 감지하고 다음 동작에 반영하는 피드백 루프
하네스 엔지니어링의 4가지 구성 요소
AI - 새로 들어온 팀원
“나는 바쁜 팀장이에요. AI한테 일을 위임하고 싶어요.”
1. 규칙, 헌법, 가드레일(Rule, Constitution, Guardrails) -- 의도를 잘 전달하기 위해 규칙을 적어놓은 문서(소통)
[Rule, Constitution] — 우리팀은 이렇게 일해
- 에이전트가 적시에 적절한 정보(아키텍처 사양, 스타일 가이드, 프로젝트 규칙 등)를 갖도록 보장하는 것으로, 정적 파일(CLAUDE.md, AGENTS.md)을 활용하여 에이전트에게 필요한 컨텍스트를 구조화하여 주입
[예시] CLAUDE.md에 "새로운 라이브러리를 도입하지 마세요. DB 쿼리는 반드시 ORM을 통해서만 해주세요”라고 작성하면, AI 에이전트는 이 규칙을 자신의 행동 제약으로 인식. 매번 프롬프트에 반복할 필요가 없다.
- [Guardrails] — AI가 입력을 받거나 답변을 내보내기 직전에 필터링하는 단계
- Input Guardrail: 유해한 질문, 개인정보 유출 시도(Prompt Injection), 범위를 벗어난 요청을 차단
- Output Guardrail: 모델이 욕설, 편향된 발언, 혹은 기업 비밀을 답변에 포함하는지 실시간으로 감시하고 차단
- 컨텍스트 엔지니어링 (Context Engineering / Structured Context)을 작성
- 에이전트에게 필요한 정보를 적시에 제공하는 기술. 단, 모든 지침을 하나의 파일에 몰아넣는 것은 지양
- 거대한 AGENTS.md 피하기: 하나의 거대한 지침 파일은 에이전트에게 혼란을 주고, 금방 유지보수가 안 되는 '낡은 규칙들의 무덤'이 되버림
- 점진적 정보 제공 (Progressive Disclosure): 메인 지침 파일은 100줄 이내의 '목차' 역할만 하도록 유지하고, 상세한 내용은 docs/ 하위 디렉터리에 구조화하여 에이전트가 필요할 때 깊이 탐색하게 만든다.
- 단일 진실 공급원 (SSOT): Slack 스레드나 개발자의 머릿속에 있는 지식은 에이전트에게 존재하지 않는 것과 같으므로, 모든 계획과 설계 내역은 리포지터리 내부에 아티팩트(Artifact)로 저장해야 한다.
- 에이전트에게 필요한 정보를 적시에 제공하는 기술. 단, 모든 지침을 하나의 파일에 몰아넣는 것은 지양
2. 아키텍처 제약 조건 및 스캐폴딩(Architectural Constraints & Scaffolding) — 어떤 정보를 참조하게 할 것인가(지식)
규칙은 문서로 남기는 것이 아니라, 코드로 강제해야 한다. 에이전트의 자유도를 제한할수록 오히려 올바른 결과물에 더 빨리 도달한다.
- [작업 구조(Task Structure)] - 무엇을 어떻게 만드는지 정의하는 작업 지시서
- 이건 꼭 지켜야 해(Linter)
- 이건 하면 안돼(제약)
- 수정 지침 주입: 린터 에러 메시지에 '해결 방법'을 포함시켜 작성. 에러 발생 시 에이전트가 메시지를 읽고 즉시 자체 수정할 수 있는 피드백 루프를 형성
- AI에게 "좋은 코드를 짜라"고 말하는 대신, 구조적으로 실수할 수 없는 환경을 만든다.
- 화이트리스트 방식을 통해 필요한 최소한의 도구 권한만 부여하거나, 작업 공간을 완전히 격리하여 외부 영향을 차단
- [출력 검증 및 구조화 (Output Parsing & Validation)]
- AI의 답변이 프로그램이 이해할 수 있는 형태인지 확인하고 강제
- Schema Enforcement: 답변이 반드시 정해진 JSON 형식을 따르도록 정의. 형식이 틀리면 에이전트가 스스로 수정하게 하거나 에러 처리
- ex) 반드시 {"status": "success", "data": ...} 형식으로 답해줘. 아니면 에러야.
- Hallucination Check: 답변 내용이 제공된 컨텍스트(Context)에 실제로 존재하는 내용인지 사실 관계를 교차 검증
- AI가 "A는 B다"라고 답하면, 시스템이 컨텍스트 문서에서 "A"와 "B"의 관계를 재검색하여 일치 여부 확인
- [CI/CD Gate]
- 코드 린터, 구조 테스트, pre-commit hook 등을 통해 규칙을 시스템이 자동으로 강제
- 린터(Linter) — 코드가 규칙을 어기면 자동으로 에러를 띄움
- 구조 테스트 — 의존성 규칙을 테스트로 강제
- Pre-commit Hook — 코드를 커밋하기 전에 자동으로 검사
- 코드 린터, 구조 테스트, pre-commit hook 등을 통해 규칙을 시스템이 자동으로 강제
CI가 실패하면 에이전트가 스스로 수정하고 사람이 개입하지 않음
3. 검증 및 피드백 루프 (Verification & Feedback Loops / Hooks) — 어떤 구조와 제약 속에서 움직이게 할 것인가(규칙)
에이전트가 자신이 작성한 코드를 스스로 평가하게 하면 편향이 발생하므로, AI가 생성한 결과물을 코드로 자동 검증하는 장치이다. 오류가 발생하면 3단계 검사(오류 식별 -> 관련 테스트 실행 -> 자동 수정)를 수행하고, 성공할 때까지 반복하거나 사람에게 보고
- [검증(Validation)]
- 결과물이 괜찮은지 기준을 미리 정의해두는 것
- 이런 결과물이 나와야 해
- 작업 지시서와 검증 기준 합의
- 결과물이 괜찮은지 기준을 미리 정의해두는 것
- [평가 체계 (Evaluations, Evals)]
- "이 프롬프트가 이전보다 나아졌는가?"라는 질문에 데이터로 답하는 과정
- LLM-as-a-Judge: 더 똑똑한 모델(예: GPT-4o)을 심판으로 세워, 서비스 모델의 답변 품질을 점수로 매긴다.
- Regression Testing: 프롬프트를 수정했을 때, 기존에 잘 되던 답변들이 망가지지 않았는지 수백 개의 테스트 케이스를 돌려 확인
- Ground Truth: 정답셋을 만들어 놓고 AI의 답변과 유사도를 비교
- 회의적인(Skeptical) 평가자 구성: 코드를 생성한 에이전트와 독립된 평가용 인스턴스를 두어, "이 PR의 문제점만 찾아라"와 같은 회의적인 프롬프트로 리뷰를 요청
- 무한 루프 방지 및 해결: 에이전트가 리뷰 코멘트를 반영하고, 수정하고, 다시 평가받는 과정을 루프(Ralph Wiggum Loop)로 구축하여 사람의 개입 없이 기준을 통과할 때까지 반복
- "이 프롬프트가 이전보다 나아졌는가?"라는 질문에 데이터로 답하는 과정
- [명시적 도구 경계]
- AI 에이전트가 어떤 도구를 쓸 수 있고, 어디까지 접근할 수 있는지를 명확하게 제한
- 파일 시스템: src/ 읽기·쓰기 가능, config/ 읽기만 가능
- API: 내부 API 호출 가능, 외부 서비스 호출 불가
- 데이터베이스: SELECT 가능, DROP TABLE 절대 불가
- AI 에이전트가 어떤 도구를 쓸 수 있고, 어디까지 접근할 수 있는지를 명확하게 제한
프롬프트는 부탁이고, 도구 경계는 물리적 차단
4. 엔트로피 관리 및 가비지 컬렉션 (Entropy Management / Garbage Collection) — 결과물을 어떻게 신뢰할 것인가(품질)
AI가 작업을 수행하면서 발생하는 기술 부채나 불필요한 데이터를 정리하는 과정입니다. 이전 단계에서 쌓인 오정보나 중복된 코드를 에이전트가 직접 정리하여 효율성을 유지
- [관측성 및 로깅 (Observability & Monitoring)]
- 실제 서비스 중 AI가 어떻게 작동하는지 추적하는 'CCTV'와 같다.
- Traceability: 에이전트가 어떤 도구를 써서 어떤 답변을 냈는지 전체 경로를 추적
- Token & Cost Control: 예상치 못한 무한 루프나 과도한 토큰 사용으로 인한 '비용 폭탄'을 방지하기 위한 한계선(Threshold)을 설정
- Feedback Loop: 사용자의 '좋아요/싫어요' 데이터를 수집하여 다시 프롬프트나 컨텍스트 개선에 활용
- 실제 서비스 중 AI가 어떻게 작동하는지 추적하는 'CCTV'와 같다.
- [지속적 피드백 루프]
- AI가 만든 코드를 주기적으로 점검하고 품질이 떨어지는 부분을 자동으로 감지 및 정리
- 실행루프(Agent Loop)
- 수정 → 검증 → 수정 → 확인 을 만족할 때까지 반복
- workflow 반복
- 코딩 규칙 위반 자동 감지
- 중복 코드 발견 및 리팩토링 PR 자동 생성
- 사용하지 않는 코드 자동 제거
- 실행루프(Agent Loop)
- AI가 만든 코드를 주기적으로 점검하고 품질이 떨어지는 부분을 자동으로 감지 및 정리
에이전트가 실수할 때마다, 그 실수는 새로운 규칙이 된다. 린터 규칙이 추가되고, 테스트가 추가되고, 제약이 추가되고, 마구가 점점 더 정교해짐
에이전트의 위임 범위
제대로 구축된 하네스 환경에서 에이전트는 단순한 코드 스니펫을 넘어 다음과 같은 광범위한 작업을 수행할 수 있다.
- 제품 코드 및 테스트 작성
- CI/CD 파이프라인 구성 및 릴리스 툴링
- 내부 개발자 도구 및 리포지터리 관리 스크립트 작성
- 문서화 및 설계 내역 정리
- PR 리뷰 코멘트 작성 및 응답
- 생산 대시보드 및 관측성(Observability) 정의 파일 설정
4대 축의 상호작용 (The Synergy)
하네스 엔지니어링이 완성되면 비로소 다른 축들이 빛을 발한다.
- Prompt(프롬프트) + Harness(하네스): 아무리 프롬프트를 잘 짜도 AI는 1%의 확률로 헛소리를 하는데, 하네스는 그 1%를 잡아낸다.
- Context(컨텍스트) + Harness(하네스): 외부 지식을 가져올 때(RAG), 하네스는 그 지식이 질문과 관련이 있는지, 혹은 오염된 데이터인지 검사한다.
- Agentic(에이전틱) + Harness(하네스): 자율적으로 행동하는 에이전트에게 "최대 5단계까지만 생각하라"거나 "이 API는 호출하지 마라"는 물리적 제약(Constraints)을 부여한다.

개발자 역할의 진화
엔지니어링역할비유
| 엔지니어링 | 역할 | 비유 |
| Prompt | 프롬프트 엔지니어 | AI에게 의도를 정확히 전달하는 사람 |
| Context | 컨텍스트 아키텍트 | AI가 참조할 지식 체계를 설계하는 사람 |
| Harness | 플랫폼 엔지니어 | AI가 실수할 수 없는 환경을 만드는 사람 |
하네스 엔지니어링의 두 단계의 역할
Repository 하네스
우리회사는 이렇다!
- AI가 이 저장소 전체에서 어떻게 일할지
- 문서 구조, 팀 규칙, 코드 린터
- 아키텍처 제약 같은 공통환경
- 모든 프로젝트에 적용되는 기반
Application 하네스
이 프로젝트는 이렇다!
- 프로젝트 별로 만들고 싶은 앱, 서비스
- 어떤 기능과 경험을 줘야 하는지
- AI가 이 앱을 위해 어떻게 판단할지
- 해당 프로젝트에만 적용되는 규칙
https://openai.com/ko-KR/index/harness-engineering/
아래와 같은 구조로 시작
AGENTS.md
ARCHITECTURE.md
docs/
├── design-docs/
│ ├── index.md
│ ├── core-beliefs.md
│ └── ...
├── exec-plans/
│ ├── active/
│ ├── completed/
│ └── tech-debt-tracker.md
├── generated/
│ └── db-schema.md
├── product-specs/
│ ├── index.md
│ ├── new-user-onboarding.md
│ └── ...
├── references/
│ ├── design-system-reference-llms.txt
│ ├── nixpacks-llms.txt
│ ├── uv-llms.txt
│ └── ...
├── DESIGN.md
├── FRONTEND.md
├── PLANS.md
├── PRODUCT_SENSE.md
├── QUALITY_SCORE.md
├── RELIABILITY.md
└── SECURITY.md
구조분석
파일/폴더 역할 작성 주체
| AGENTS.md | 에이전트 행동 규칙 | 인간 (한 번) |
| ARCHITECTURE.md | 시스템 전체 지도 | 인간 (한 번 + 업데이트) |
| design-docs/ | 설계 원칙 및 결정 | 인간 |
| exec-plans/active/ | 현재 작업 지시서 | 인간이 작성 → 에이전트가 실행 |
| product-specs/ | 기능 명세 | 인간 |
| references/ | 압축된 라이브러리 문서 | 인간 (or 에이전트가 생성) |
| DESIGN.md | API 포맷·네이밍 등 내부 설계 기준 | 인간 (한 번 + 협의 시 업데이트) |
| FRONTEND.md | 클라이언트 연동 계약·에러코드 정의 | 인간 (클라이언트팀과 협의) |
| QUALITY_SCORE.md | 코드 품질 자체 평가 체크리스트 | 인간 |
| RELIABILITY.md | 장애 대응·타임아웃·재시도 기준 | 인간 |
| SECURITY.md | 보안 체크리스트·금지 패턴 | 인간 |
| docs/generated/ | 에이전트가 생성한 산출물 | 에이전트 |
에이전트 제어 레이어
AGENTS.md
에이전트가 어떻게 행동해야 하는지 정의하는 메타 지시서 [행동 헌법]
- 너는 어떤 역할이야
- 코드 작성할 때 이 규칙을 따라
- 모르면 이렇게 해
- 절대 하면 안 되는 것
사람으로 치면 "신입 개발자 온보딩 문서"인데, 읽는 대상이 AI 이기 때문에 모호한 표현 없이 명확하게 작성해야 한다. Claude Code 기준으로는 이 파일을 프로젝트 루트에 두면 매 세션마다 자동으로 읽음
ARCHITECTURE.md
시스템 전체 구조를 에이전트가 참조하는 지도
- 서비스 구성 (모듈, 레이어)
- 주요 데이터 흐름
- 외부 의존성
- 레이어 간 책임 경계
에이전트가 새 기능을 추가할 때 "이게 어디에 들어가야 하지?"를 판단하는 근거. 이게 없으면 엉뚱한 레이어에 코드를 추가하게됨
의사결정 문서 레이어 (docs/)
design-docs/
기술적 의사결정 기록. ADR(Architecture Decision Record)과 비슷
- index.md — 전체 설계 문서 목록
- core-beliefs.md — "우리는 이런 이유로 이렇게 설계한다"는 원칙
# core-beliefs.md
- DB 트랜잭션 경계는 Service 레이어에서만 관리한다
- 외부 API 호출은 반드시 별도 Client 클래스로 분리한다
- 도메인 객체는 인프라 의존성을 가지지 않는다
exec-plans/
실행 계획 관리.
exec-plans/
├── active/ ← 지금 진행 중인 작업
├── completed/ ← 완료된 작업 (히스토리)
└── tech-debt-tracker.md ← 기술 부채 목록
active/ 안에 파일 하나가 하나의 작업 단위
# feat/sensor-api.md
## 목표
쿠폰 API 구현
## 범위
- [ ] CouponController
- [ ] CouponService
- [ ] CouponRepository
## 제약
- 쿠폰 중복 등록은 안됨
- 쿠폰은 최대 2개까지만 가능
## 완료 기준
- 단위 테스트 커버리지 80% 이상
product-specs/
기능 명세서 (AI 에이전트가 "무엇을 만들지" 참조)
- index.md — 전체 기능 목록 및 상태
- new-user-onboarding.md — 기능별 상세 명세
## 사용자 스토리
신규 가입자가 앱 첫 실행 시 3단계 온보딩을 완료한다
## 화면 흐름
1. 환영 화면
2. 관심사 선택
3. 알림 동의
## API 요구사항
- POST /onboarding/complete
- 완료 시 웰컴 쿠폰 발급 (CouponService 연동)
references/
외부 라이브러리 LLM 최적화 문서
라이브러리 공식 문서를 그대로 넣으면 토큰 낭비가 심해서, AI가 읽기 좋게 압축한 버전을 따로 만들어둔 것
[예: Spring Data JPA 문서]
# Spring Data JPA - LLM Reference
## Repository 정의
interface UserRepository extends JpaRepository<User, Long> {}
## 쿼리 메서드
findByEmailAndStatus(String email, Status status)
→ WHERE email = ? AND status = ?
## 주의사항
- N+1 문제: @EntityGraph 또는 fetch join 사용
품질 기준 레이어
QUALITY_SCORE.md — 에이전트가 코드를 생성할 때 지켜야 할 기준
## 체크리스트
- [ ] 메서드 단위 테스트 존재
- [ ] 예외 처리 명시
- [ ] 로깅 포함
- [ ] 매직 넘버 없음
RELIABILITY.md — 장애 대응 기준
- 외부 API 호출은 timeout 설정 필수
- 재시도 로직은 exponential backoff 적용
- 서킷브레이커 적용 대상 목록
SECURITY.md — 보안 체크리스트
- SQL 인젝션 방어 (파라미터 바인딩 필수)
- 민감 정보 로그 출력 금지
- 인증 없는 엔드포인트 목록 명시
DESIGN.md — 디자인 시스템 제약: 시스템의 미적/구조적 일관성 기준
프론트엔드가 있으면 UI 디자인 시스템이 들어가지만, 백엔드 전용 프로젝트라면 API 구조 포멧 정의
에이전트가 새 API를 만들 때마다 이 파일을 참조해서 포맷을 통일시킴. 이게 없으면 어떤 API는 data, 어떤 건 result, 어떤 건 response로 제각각 만들게됨
**# DESIGN.md
## API 응답 포맷
모든 응답은 아래 구조를 따른다
{
"success": true,
"data": {},
"error": null
}
## 에러 응답 구조
{
"success": false,
"data": null,
"error": {
"code": "USER_NOT_FOUND",
"message": "사용자를 찾을 수 없습니다"
}
}
## 네이밍 컨벤션
- URL: kebab-case → /car-wash-missions
- JSON 필드: camelCase → userId, createdAt
- 에러 코드: UPPER_SNAKE_CASE → INVALID_TOKEN
## 페이지네이션 구조
{
"content": [],
"page": 0,
"size": 20,
"totalElements": 100
}**
FRONTEND.md — 디자인 시스템 제약 : 외부(클라이언트)와의 연동
프론트팀이 없어도, 앱 클라이언트나 외부 연동이 있다면 필요
## 클라이언트 연동 원칙
- 필드 삭제 금지, 추가만 허용 (하위 호환성 유지)
- Null 필드는 응답에서 제외하지 않고 명시적으로 null 반환
- 날짜 포맷: ISO 8601 (2024-01-15T09:00:00Z)
## 인증
- Authorization: Bearer {token} 헤더 방식
- 토큰 만료 시 401 응답, refresh는 클라이언트 책임
## 에러 코드 목록
| 코드 | 의미 | HTTP Status |
|------|------|-------------|
| USER_NOT_FOUND | 사용자 없음 | 404 |
| INVALID_TOKEN | 토큰 오류 | 401 |
| MISSION_EXPIRED | 미션 만료 | 410 |
## 비동기 작업 처리
- 즉시 응답: 202 Accepted + jobId 반환
- 상태 조회: GET /jobs/{jobId}
'AI > 엔지니어링' 카테고리의 다른 글
| 2. Context Engineering(컨텍스트 엔지니어링) — AI에게 필요한 정보를 적절하게 제공하는 기술 (0) | 2026.04.08 |
|---|---|
| 1. Prompt Engineering(프롬프트 엔지니어링) — AI에게 일(말)을 잘 거는 기술 (1) | 2026.04.08 |