이 차시에서 준비할 것
map/식당리스트_실습용.csv (15,144건)이 차시는 정하늘 대리의 광고 업무가 아니라 완전히 다른 도메인을 다룹니다. 일부러 그렇게 했습니다 — 하네스 만드는 방법은 도메인을 가리지 않는다는 것을 확인하는 것이 목적입니다. 7차시에서 다시 자기 업무로 돌아옵니다.
이 차시에서 처음 나오는 말
- 인코딩
- 글자를 컴퓨터에 저장하는 방식. 방식이 다르면 한글이 깨집니다. 이 데이터는 요즘 표준(UTF-8)이 아닌 옛 방식(CP949)입니다.
- 정제 (클렌징)
- 지저분한 원본을 계산할 수 있는 형태로 다듬는 일. 실무 데이터 작업의 8할입니다.
- 스펙 (명세)
- "무엇을 만들 것인가"를 해석의 여지 없이 적은 문서. 모호함 하나가 곧 AI의 임의 결정 하나입니다.
- 교차 검증
- 결과물 하나만 보는 게 아니라 원본과 결과를 나란히 놓고 대조하는 것. "파일이 있네요"는 검증이 아닙니다.
이 차시에서 배우는 것
- 실무 데이터가 왜 그냥 안 되는지 직접 확인한다
- 처리 규칙을 스펙 문서로 못 박고, 그 스펙으로 팀을 만든다
- 결과를 원본과 대조해 검증한다 — 하네스의 마지막 조각
- (선택) 스펙 쓰는 규칙 자체를 스킬로 만들어 어느 업무에나 쓴다
1. 문제 — 실무 데이터는 깨끗하지 않다
소재는 서울시청 인근 업무추진비 집행 내역입니다. "공무원이 법인카드로 반복 방문한 식당 = 검증된 맛집"이라는 가설로 분석할 수 있는 데이터입니다.
| 집행 기록 | 15,144건 (2026년) |
|---|---|
| 총 집행액 | 약 20.3억 원 (건당 평균 13.4만 원) |
| 컬럼 | 해당년도 · 해당월 · 집행일시 · 집행장소 · 집행금액 · 정리식당명 · 주소 |
1-1. 먼저 그냥 시켜 봅니다
cd C:\harness-edu\map; claude
cd ~/harness-edu/map && claude
식당리스트_실습용.csv 를 열어서 어떤 데이터인지 알려주고, 방문 횟수 상위 10개 식당을 표로 뽑아줘.
예상 결과: 한 번에 안 됩니다. AI가 이런 것들을 만나 스스로 고쳐 가며 진행합니다.
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc7 ... → 인코딩을 cp949 로 바꿔 재시도 → 컬럼이 하나로 붙어 나옴 → 구분자가 쉼표가 아니라 탭이었음 → 다시 파싱 → 겨우 상위 10개 추출
결국 답은 나옵니다. 문제는 이 과정이 매번 다르다는 것입니다. 다음에 돌리면 AI가 또 처음부터 헤매고, 다른 판단을 내립니다.
1-2. 이 데이터에 숨은 함정 네 가지
| 함정 | 내용 | 그냥 두면 |
|---|---|---|
| 인코딩·구분자 | UTF-8이 아닌 CP949, 쉼표가 아닌 탭 | 한글이 깨지거나 컬럼이 안 나뉨 |
| 혼합 필드 | 집행장소 한 칸에 상호와 주소가 같이 — 명동칼국수(서울시 중구 세종대로 21길 48) | 식당명 집계가 어긋남 |
| 명칭 불일치 | 법인명(주식회사 보원에프앤비) vs 간판명, 지점 표기 편차(창고43시청점 / 창고43 무교점) | 같은 가게가 여러 개로 세어짐 |
| 좌표 없음 | 주소만 있고 위경도가 없음 | 지도에 못 올림 (이번 차시 범위 밖) |
이 네 가지는 이 데이터에만 있는 특수 사정이 아닙니다. 사내 시스템에서 내려받은 엑셀, 팀마다 다르게 쓴 양식, 오래된 CSV — 실무 데이터는 대개 이렇습니다. 2차시의 "분임조 은어"와 같은 문제가 형태만 바꿔 나타난 것입니다.
2. 개념 — 스펙이 계약이다
4차시에서 팀을 만들 때 도메인·입력·산출물·품질 기준 네 줄을 적었습니다. 데이터 작업에서는 그 정도로 부족합니다. 처리 규칙까지 못 박아야 합니다.
모호한 지시
"식당별로 집계해줘"
- 같은 가게를 하나로 볼 기준이 없음
- 법인명과 간판명 중 무엇을 쓸지 AI가 정함
- 돌릴 때마다 기준이 바뀜
스펙으로 못 박기
"정리식당명 기준으로 집계. 지점 표기가 달라도 같은 상호로 시작하면 별도 집계. 법인명은 사용하지 않음"
- 판단 기준이 문서에 남음
- 결과가 재현됨
- 기준이 바뀌면 문서만 고침
스펙은 사람이 읽는 기획서가 아니라 AI가 실행하는 계약서입니다.
모호함 하나 = AI의 임의 결정 하나. "깔끔하게", "적절히", "보기 좋게" 같은 말이 들어가면 그만큼 결과가 흔들립니다.
3. 실습 A — 스펙 쓰기
AI에게 스펙부터 쓰게 합니다. 바로 작업시키지 않는 것이 핵심입니다.
식당리스트_실습용.csv 를 분석해 "시청 주변 맛집 랭킹 리포트" 를 만들려고 해. 바로 만들지 말고, 먼저 처리 규칙을 정한 스펙 문서를 MATZIP_SPEC.md 로 써줘. 스펙에 반드시 들어갈 것: 1. 파일 읽는 법 — 인코딩과 구분자를 실제로 확인해서 명시할 것 2. 집행장소 컬럼에서 상호와 주소를 분리하는 규칙 3. 같은 식당으로 볼 기준 (법인명·지점 표기 처리 방침) 4. 집계 항목 정의 — 방문 횟수, 총 집행액, 평균 단가, 최근 방문일 5. 제외 규칙 — 식당이 아닌 항목(매점 등)을 어떻게 다룰지 6. 검증 기준 — 결과가 맞는지 확인할 숫자 (총 건수, 총액 등) 각 규칙은 "적절히", "깔끔하게" 같은 말 없이 실행 가능한 문장으로 써줘. 정하지 못한 것은 [확인 필요] 로 남겨줘.
예상 결과: MATZIP_SPEC.md 가 생깁니다. AI가 파일을 실제로 열어 보고 인코딩이 CP949, 구분자가 탭이라는 것을 스펙에 적어 넣습니다.
좋은 스펙인지 보는 법 — 열어서 세 가지만 확인하세요.
- 숫자와 값이 적혀 있는가 — "CP949", "탭 구분"처럼 구체적으로. "적절한 인코딩" 이면 실패
- 하지 않을 일이 적혀 있는가 — 지도 시각화·리뷰 수집은 이번 범위가 아님
[확인 필요]가 남아 있는가 — AI가 모르는 것을 정직하게 남겼다는 뜻입니다. 하나도 없으면 오히려 의심하세요
4. 실습 B — 스펙으로 팀 만들기
이제 그 스펙을 실행할 팀을 구성합니다. 4차시와 같은 방식이되, 스펙이 이미 있으므로 설명이 훨씬 짧아집니다.
하네스 구성해줘. MATZIP_SPEC.md 를 유일한 요구사항 문서로 삼는다. 데이터 정제 → 집계·분석 → 검증 순서의 팀으로 만들어줘. - 정제 담당: CSV 파싱, 상호·주소 분리, 명칭 통합 - 분석 담당: 식당별 집계와 랭킹, 구별·월별 분포 - 검증 담당: 원본과 결과를 대조. 총 건수·총액이 일치하는지 확인하고 불일치를 발견하면 담당자를 지목해 수정 요청 스펙의 처리 규칙은 스킬 파일로 만들어 정제 담당이 참조하게 해줘.
예상 결과: 담당자 3명과 .claude/skills/ 아래 정제 규칙 스킬이 만들어집니다. 4차시에서 본 것과 같은 구조인데, 이번에는 스펙이 먼저 있어서 팀이 훨씬 정확하게 나옵니다.
5. 실습 C — 돌리고 검증하기
만든 팀으로 MATZIP_SPEC.md 에 따라 작업을 진행해줘. 결과는 맛집랭킹.md 로 저장하고, 검증 담당의 대조 결과도 함께 보고해줘.
정답 — 이 숫자와 맞는지 대조하세요. 직접 계산해 확인한 값입니다.
| 확인 항목 | 맞는 값 |
|---|---|
| 총 집행 건수 | 15,144건 |
| 총 집행액 | 2,028,266,478원 (약 20.3억) |
| 건당 평균 | 약 133,932원 |
| 고유 식당 수 | 약 2,945곳 (명칭 통합 기준에 따라 조금 달라질 수 있음) |
| 최다 방문 | 창고43시청점 146회 · 서울시청매점 142회 · 구이구이 125회 |
| 구별 분포 | 중구 11,848건 · 종로구 1,154건 · 강남구 256건 |
총 건수와 총액이 다르면 파싱 단계에서 행이 누락된 것입니다. 검증 담당이 이것을 잡아냈어야 합니다.
검증 담당이 제대로 일했는지 보는 법
이건 검증이 아닙니다
"맛집랭킹.md 파일이 정상적으로 생성되었습니다."
이게 검증입니다
"원본 15,144행 중 15,144행이 집계에 반영됨. 총액 2,028,266,478원 일치. 단, 서울시청매점 은 식당이 아니어서 스펙의 제외 규칙 적용 여부를 확인 필요."
파일 존재 확인은 누구나 합니다. 원본과 결과를 나란히 놓고 숫자를 맞춰 보는 것이 검증입니다.
5-1. 규칙 하나를 바꿔 보기
하네스의 진짜 값어치는 여기서 드러납니다. 스펙 한 줄만 고치고 다시 돌려 보세요.
MATZIP_SPEC.md 의 제외 규칙에 "매점·편의점·구내식당은 집계에서 제외" 를 추가하고, 그 스펙으로 다시 돌려줘. 바뀐 결과와 이전 결과의 차이를 알려줘.
예상 결과: 서울시청매점(142회)이 랭킹에서 빠지고 순위가 바뀝니다. 지시문을 다시 쓰지 않았습니다 — 스펙 한 줄만 고쳤습니다. 이것이 규칙을 파일로 두는 이유입니다.
6. 실습 D (선택) — 스펙 쓰는 규칙을 스킬로
선택 실습입니다. 건너뛰어도 다음 차시에 지장이 없습니다. 다만 스펙을 앞으로 계속 쓸 사람이라면 여기가 이 차시에서 가장 남는 부분입니다.
3절에서 스펙을 요구할 때, 프롬프트가 열 줄이 넘었습니다. "반드시 들어갈 것 여섯 가지", "적절히 같은 말 금지", "모르는 건 [확인 필요]" — 이걸 다음 프로젝트에서도 또 씁니다.
2차시의 판단 기준을 그대로 적용합니다. "다음에도 또 나오나?" → 예 → 파일로.
이번에 파일로 만들 것은 업무 지식이 아니라 "좋은 스펙이란 무엇인가"라는 기준입니다.
6-1. 만들기
방금 MATZIP_SPEC.md 를 쓸 때 내가 요구했던 조건들을 스킬로 만들어줘. .claude/skills/spec-writer/SKILL.md description 에 넣을 것 — 언제 쓰는지가 분명하게: "데이터 처리·분석·자동화 작업을 시작하기 전에 요구사항 명세서를 쓸 때 사용. 바로 작업에 들어가지 않고 스펙부터 확정해야 하는 모든 작업에 적용." 본문에 넣을 것: 1. 스펙에 반드시 들어갈 항목 — 입력(파일/형식/인코딩) · 처리 규칙 · 산출물 형식 · 제외 규칙 · 검증 기준 · 범위 밖(하지 않을 일) 2. 금지 표현 목록 — "적절히" "깔끔하게" "보기 좋게" "알아서" "필요시" 이런 말이 들어가면 그만큼 AI가 임의로 결정한다는 것을 명시 3. 구체성 규칙 — 값은 실제 값으로 쓴다 (인코딩은 "CP949", 구분자는 "탭", 기준은 "노출 1,000 미만" 처럼) 4. 모르는 것 처리 — 추측하지 말고 [확인 필요] 로 남긴다 5. 스펙 검수 3문항 — 구체적 값이 있는가 / 안 할 일이 적혔는가 / [확인 필요] 가 남아 있는가 파일만 만들고 실행은 아직 하지 마.
예상 결과: .claude/skills/spec-writer/SKILL.md 가 생깁니다. 2차시에서 만든 용어집 스킬과 완전히 같은 형태입니다 — 담긴 것이 매체 용어가 아니라 "스펙 쓰는 법" 일 뿐입니다.
6-2. 다른 일에 써 보기
같은 폴더에서 쓰면 "아까 대화 때문"인지 구분이 안 됩니다. 완전히 다른 주제로 시험합니다. Claude Code를 껐다 켠 뒤 — 스킬은 재시작해야 읽힙니다.
/exit
claude
사내 회의실 예약 현황을 정리해서 "어느 회의실이 언제 노는지" 알려주는 작업을 하려고 해. 스펙부터 써줘. 아직 데이터는 없어.
예상 결과: 맛집 데이터와 아무 상관 없는 주제인데도 같은 틀로 스펙이 나옵니다 — 입력·처리 규칙·산출물·제외·검증·범위 밖. 데이터가 없으니 [확인 필요] 가 여럿 남습니다. 그게 맞는 동작입니다.
2차시 스킬은 한 업무에서만 쓰였습니다. 이 스킬은 모든 업무에서 쓰입니다.
6-3. 스킬에는 두 종류가 있습니다
| 업무 지식 스킬 | 일하는 방식 스킬 | |
|---|---|---|
| 예 | 2차시 media-glossary | 5차시 spec-writer |
| 담긴 것 | 우리 팀만 아는 용어·기준 | 누구에게나 통하는 절차·품질 기준 |
| 쓰이는 범위 | 그 업무에서만 | 주제를 가리지 않고 |
| 누가 만드나 | 그 업무 담당자만 가능 | 한 명이 만들어 팀 전체가 씀 |
| 바뀌는 빈도 | 자주 (새 매체·새 지표) | 드물게 |
두 번째 종류를 몇 개 갖고 있느냐가 실력 차이로 나타납니다. 스펙 쓰기 · 회의록 정리 · 보고서 검수 · 데이터 검증 — 이런 "일하는 방식"을 파일로 갖고 있으면 새로운 업무를 만나도 시작이 빠릅니다. 7차시에서 다룰 하네스 100선이 통째로 이 두 번째 종류입니다.
더 정교하게 만들고 싶다면 — 소프트웨어 개발용으로 만들어진 공개 스펙 작성 스킬들이 참고가 됩니다. 데이터 모델·화면 정의·구현 순서까지 항목을 나눠 두는데, "색은 이름이 아니라 hex 코드로", "크기는 ‘크게’가 아니라 픽셀 값으로" 같은 규칙이 핵심입니다. 우리가 "인코딩은 CP949로" 라고 쓴 것과 정확히 같은 원리입니다.
7. 스스로 점검
- 이 데이터가 "그냥은 안 되는" 이유 네 가지를 말할 수 있다
- 스펙을 먼저 쓰게 하는 이유를 "모호함 = 임의 결정" 으로 설명할 수 있다
MATZIP_SPEC.md에 인코딩·구분자가 구체적 값으로 적혀 있다- 결과를 정답 숫자(15,144건 / 20.3억)와 대조했다
- "파일이 생성되었습니다" 와 교차 검증의 차이를 안다
- 스펙 한 줄을 고쳐 결과가 바뀌는 것을 확인했다
- (선택) 스펙 쓰는 규칙을 스킬로 만들어 다른 주제에 써 봤다
- (선택) 업무 지식 스킬과 일하는 방식 스킬의 차이를 설명할 수 있다
흔한 실패와 대처
| 증상 | 왜 생기나 | 대처 |
|---|---|---|
한글이 �� 로 깨짐 | UTF-8로 읽음 | 정상입니다 — AI가 CP949로 바꿔 재시도하는지 보세요. 스펙에 인코딩이 적혔는지 확인 |
| 스펙이 두루뭉술함 | "적절히" 같은 말이 들어감 | "이 문장을 그대로 실행할 수 있나?" 를 기준으로 다시 쓰게 하세요 |
| 총 건수가 15,144가 아님 | 헤더·빈 행 처리 차이 | 검증 담당에게 "원본 행 수와 집계 행 수를 대조하라" 고 요청 |
| 검증이 "파일 있음" 수준 | 검증 담당 정의가 약함 | "원본과 결과의 숫자를 대조하라" 를 에이전트 정의에 명시 |
| 팀이 안 만들어짐 | 에이전트 팀 기능 · 플러그인 범위 | 설치가이드 3-5절 / /plugin User 범위 확인 |
8. 더 해보기 (선택)
- 지도로 만들기 — 이 데이터로 실제 웹앱까지 만드는 과정이 원본 교안에 있습니다. 주소를 좌표로 바꾸고(지오코딩) 지도에 올리는 단계까지 다룹니다 → map/README.md
- 명칭 통합 강화 —
창고43시청점과창고43 무교점을 한 브랜드로 묶는 규칙을 스펙에 추가해 보세요. 랭킹이 어떻게 바뀌는지 봅니다. - 내 업무 데이터로 — 지저분한 파일이 있다면 같은 순서로 해보세요. 스펙 먼저, 팀 그다음, 검증 마지막.
9. 다음 차시
여기까지 Agent(누가) 와 Skill(무엇을·어떻게) 을 다뤘습니다. 그런데 정제와 집계를 아무리 잘해도, AI가 계산이나 사실을 지어내면 결과를 믿을 수 없습니다. 6차시에서 마지막 축 Tool 로 그 문제를 막습니다.