특강
바이브 코딩: 팩트체크 실습을 통해
이종혁 (경희대학교 미디어학과) · 2026년 10월
- PART 1 이론과 환경 구축 — 강의 + 설치
- PART 2 팩트체크 도구 실습 — 웹앱 1개 + 로컬 에이전트 1식
이 강의가 다루는 것은 웹 채팅창이 아님. ChatGPT·Claude·Gemini를 브라우저에서 대화창으로 쓰는 방식이 아니라, 같은 급의 모델을 내 컴퓨터에 설치해 파일과 명령을 직접 다루게 하는 방식을 씀. 둘의 차이는 모델 성능이 아니라 권한과 설계에 있음. 여는 장에서 용어부터 정리함.
이 강의의 진행 방식 ① 계획만 적은 프롬프트 한 장을 던짐 → ② 돌아온 실물을 읽음 → ③ 어긋난 곳만 조임. 결과물은 매번 다르게 나옴. 그래서 이 특강은 완성된 코드를 싣지 않고, 무엇이 나와야 하는지 예측하고 대조하는 법을 실었음.
코딩을 해 본 적이 없어도 됨. 필요한 준비는 8장에서 처음부터 짚어 줌. 모르는 낱말이 나오면 맨 아래 「용어 미니 사전」을 먼저 볼 것.
PART 1. 이론과 환경 구축#
여는 장. 왜 웹 채팅창이 아니라 코딩 에이전트인가#
- 바이브 코딩은 채팅창에 코드를 물어보는 것이 아님. 이 구분이 이 강의의 출발점임.
용어부터 — 바이브코딩의 구분#
기준 — 내 컴퓨터에 손댈 권한이 있는가.
| 용어 | 영어 표기 | 무엇을 가리키나 | |
|---|---|---|---|
| A | 웹 채팅형 어시스턴트 (줄여서 채팅형) |
chat assistant conversational assistant |
브라우저로 chatgpt.com·claude.ai에 접속해 대화창으로 쓰는 방식 |
| B | 코딩 에이전트 (줄여서 에이전트) |
coding agent agentic coding tool |
터미널이나 코드 편집기에 설치해 내 폴더의 파일을 직접 읽고 쓰고 실행하게 하는 방식 |
- B는 사용하는 자리에 따라 다시 구분. 성격은 같고 화면만 다름.
- CLI 코딩 에이전트 (CLI coding agent · terminal-native) — 터미널에서
claude·codex로 실행 - IDE 코딩 에이전트 (IDE coding agent) — VS Code 확장, Cursor, Antigravity처럼 편집기 안에 붙음
- 이렇게 도구를 설계해 가며 일을 맡기는 방식 전체를 업계에서는 에이전틱 코딩(agentic coding)이라 부름. 바이브 코딩(vibe coding)은 그중에서도 코드를 일일이 읽지 않고 자연어 지시로 결과를 얻는 작업 방식을 가리키는 말임.
한 줄 정리 — 대비는 "대화형 대 에이전트형"이 아니라 "보여주기만 하는 채팅형" 대 "직접 해 주는 에이전트형"임. 둘 다 대화로 쓰고, 둘 다 같은 급의 모델을 씀. 갈리는 것은 권한임.
결정적 차이 — 성능이 아니라 권한#
| 웹 채팅형 어시스턴트 | 코딩 에이전트 | |
|---|---|---|
| 대화로 쓰나 | ○ | ○ (여기서는 안 갈림) |
| 하는 일 | 코드를 보여 줌 | 파일을 직접 만들고 고침 |
| 실행 | 내가 복사·저장·실행 | 터미널 명령까지 스스로 실행 |
| 오류 | 내가 붙여넣어 다시 질문 | 스스로 읽고 재시도 |
| 여러 파일 | 한 번에 하나씩 보여 줌 | 폴더 전체를 훑고 여러 파일을 함께 고침 |
| 설정이 남나 | 대화창을 닫으면 사라짐 | 규칙·절차가 파일로 폴더에 남음 |
| 대가 | — | 매번 "실행해도 될까요?" 승인 요청 |
- 채팅형이 못 하는 이유는 똑똑하지 않아서가 아님. 내 컴퓨터에 손댈 권한이 없기 때문임.
- 권한을 넘기는 순간부터 승인 절차와 작업 폴더 제한이 안전장치가 됨.
- 내용을 읽지 않고 승인 버튼을 누르는 습관이 이 도구의 가장 큰 위험임. 실습 내내 반복해 확인할 것.
그래서 채팅형은 1단계에 머무름#
- 다음 장의 네 단계에 대입하면 위치가 분명해짐.
| 단계 | 채팅형 | 코딩 에이전트 |
|---|---|---|
| 1. prompt | ○ | ○ |
| 2. context | △ 파일 업로드·웹검색으로 일부 흉내 | ○ |
| 3. agentic | ✕ 구조적으로 불가능 | ○ |
| 4. harness | ✕ 통제할 대상이 없음 | ○ |
- 3·4단계가 막히는 것은 기능 부족이 아니라 권한이 없어서임.
- 파일을 만들 수 없으면 서브에이전트도 스킬도 규칙 파일도 둘 자리가 없음.
오늘 두 실습이 이 차이를 그대로 보여줌#
| 실습 1 (웹) | 실습 2 (에이전트) | |
|---|---|---|
| 실행 주체 | 사람이 매번 버튼을 누름 | 에이전트가 스스로 순서를 진행 |
| 처리 단위 | 주장 한 개 | input/ 안의 주장 여러 개 |
| 재현 | 브라우저를 닫으면 끝 | 코드와 규칙이 폴더에 남음 |
| 해당 단계 | 1~2단계 | 3~4단계 |
- 실습 1을 먼저 하는 이유 — 사람이 손으로 하던 일이 무엇인지 먼저 겪어야, 실습 2에서 그것이 자동화되는 의미를 알 수 있음.
1장. AI 활용 수준의 네 단계#
prompt engineering → context engineering → agentic engineering → harness engineering
(무엇을 묻나) (무엇을 보여주나) (누가 어떻게 일하나) (어떻게 통제하나)
| 단계 | 다루는 대상 | 한계 → 다음 단계로 |
|---|---|---|
| 1. prompt | 지시문 하나 | 모델이 모르는 정보는 못 냄 |
| 2. context | 문맥창에 넣을 내용 | 사람이 시켜야 한 번 움직임 |
| 3. agentic | 작업의 구조 | 자율성이 커지면 폭주함 |
| 4. harness | 권한·검증·중단 조건 | — |
- 대체가 아니라 누적임. 상위 단계에서도 프롬프트는 계속 씀.
- 채팅형은 1단계에 머무름 (여는 장 참조). 3단계 이후는 권한이 없어 구조적으로 불가능함.
- 업계 표준 분류가 아니라 교육용 설명 틀임.
loop engineering은 별도 단계로 두지 않음. 루프는 3단계 안의 작업 흐름 패턴임.
문맥창(context window)이란 — AI가 한 번에 읽어 둘 수 있는 분량. 사람으로 치면 책상 위에 펼쳐 놓은 자료의 크기임. 책상을 벗어난 자료는 아무리 중요해도 AI 눈에 보이지 않음. 2단계는 이 책상 위에 무엇을 올릴지 고르는 기술임.
2장. 1단계 — prompt engineering#
(무엇을) + (어떤 형식으로) + (어떤 조건에서)
| 기법 | 예시 |
|---|---|
| 역할 부여 | "너는 20년차 사회부 기자다. 담백한 단문으로 답한다." |
| 퓨샷 | 입력·출력 쌍 2~3개를 먼저 보여줌 |
| 출력 형식 지정 | "표로 답한다. 열은 주장·근거·출처 셋이다." |
| 제약 명시 | "모르면 모른다고 답한다. 지어내지 않는다." |
| 분할 요청 | "쇼핑몰 전체"가 아니라 "입력칸 하나" |
| 계획 먼저 요구 | "만들기 전에 무엇을 만들지 먼저 알려줘" — 이 강의 두 실습이 모두 이 줄로 끝남 |
| 아쉬움 | 좋음 |
|---|---|
| "할 일 앱 만들어 줘" | "할 일을 추가·삭제·완료체크하는 웹앱을 index.html 한 파일로, 새로고침해도 목록이 남도록" |
| "안 돼" | "추가 버튼을 눌러도 목록에 안 나타나. 콘솔 오류를 확인하고 고쳐 줘" |
| "예쁘게 만들어 줘" | "글자 크기를 키우고 버튼을 화면 가운데 두 개만 남겨 줘" |
- 막연한 형용사는 지시가 아님. "예쁘게·깔끔하게·잘"은 AI가 알아서 판단해 버림. 셀 수 있는 말로 바꿀 것.
3장. 2단계 — context engineering#
- 많이 넣는 것이 아니라 잘 골라 넣는 것임. 문맥창은 크기와 집중도 두 가지 제약을 받음.
- 자료를 통째로 밀어 넣으면 길이는 채워지지만 정작 중요한 대목이 묻힘.
손이 적게 가는 것부터 차례로 올라감. 아래 순서가 곧 구축 난이도 순서임.
| 순서 | 방법 | 원리 | 용도 · 예 | 드는 품 |
|---|---|---|---|---|
| ① | 대용량 자료를 넣어 두고 필요한 대목만 참조 |
폴더에 자료를 그냥 놓아둠. 에이전트가 목록을 보고 그때그때 필요한 파일·구간만 열어 읽음 | 보고서 수백 장, 기사 수천 건, 회의록 — 가장 먼저 시도할 것 | 거의 없음 |
| ② | API 연결 — 실시간 검색 · RSS |
바깥 서비스를 호출해 최신 내용을 그때그때 끌어와 문맥창에 넣음 | 오늘의 사건·뉴스·주가 (이번 실습의 Tavily가 여기) · RSS로 언론사 새 기사 수집 | 키 발급 + 호출 코드 |
| ③ | MCP (Model Context Protocol) |
외부 도구·데이터를 표준 규약으로 꽂음. 서비스마다 코드를 새로 짜지 않아도 됨 | GitHub·노션·구글드라이브·데이터베이스를 도구처럼 연결 | 서버 설치·설정 |
| ④ | RAG (검색 증강 생성) |
문서를 조각내 벡터로 저장 → 질문과 뜻이 가까운 조각만 골라 삽입 | 사내 문서·논문·판례처럼 양이 아주 많고 계속 되물을 자료 | 가장 큼 (임베딩·DB 구축·갱신) |
- ①부터 해 볼 것. 초보자가 가장 많이 하는 실수가 ①로 충분한 일에 곧바로 ④(RAG)를 만들려는 것임.
- 요즘 모델의 문맥창은 아주 커서, 수백 쪽 분량도 ①만으로 다뤄짐. RAG는 ①로 감당이 안 될 때 가는 곳임.
- ②는 "모델이 모르는 최신 정보"를 메우고, ④는 "모델이 모르는 우리 조직의 정보"를 메움. 메우는 구멍이 서로 다름.
- ③ MCP는 ②·④를 대체하는 것이 아니라 꽂는 방식임. RSS도 RAG도 MCP 서버로 만들어 붙일 수 있음.
왜 ①이 에이전트에서만 제대로 되나 — 채팅형은 파일을 업로드해야 읽음. 용량·개수 제한이 걸림. 코딩 에이전트는 폴더를 그냥 보고 필요한 파일만 스스로 열어 읽음. 여는 장의 권한 차이가 여기서 바로 드러남.
4장. 3단계 — agentic engineering#
먼저 짚을 것 — 누가 "에이전트"인가. 가장 헷갈리는 대목이므로 일하는 주체와 주체가 읽는 문서를 구분해 둠.
| 이름 | 정체 | 위치 | |
|---|---|---|---|
| 일하는 주체 (에이전트) |
메인 에이전트 | 내가 지금 대화하고 있는 그 세션. 모든 도구를 다 쓸 수 있고, 전체를 지휘하고 종합함 | claude를 실행한 그 창 (별도 파일 없음) |
| 서브에이전트 | 메인이 불러내는 별도의 일꾼. 자기만의 깨끗한 문맥창을 갖고 한 가지 일만 함. 결과 요약만 메인에게 돌려줌 | .claude/agents/<이름>.md |
|
| 주체가 읽는 문서 |
메모리 파일CLAUDE.md |
에이전트가 아님. 메인 에이전트가 세션을 열 때마다 자동으로 읽는 지시문. 사람이 써 두는 규칙 메모임 | 작업 폴더의 CLAUDE.md |
| 스킬 | 역시 에이전트가 아님. 상황에 맞을 때만 꺼내 읽는 절차서 | .claude/skills/<이름>/SKILL.md |
비유로 — 메인 에이전트가 팀장, 서브에이전트가 팀원임.
CLAUDE.md는 팀장이 출근할 때마다 먼저 읽는 업무 수칙 게시판이고, 스킬은 캐비닛에 꽂힌 업무 매뉴얼임 — 필요할 때만 꺼내 봄. 게시판과 매뉴얼은 사람이 아님. 그래서CLAUDE.md는 "메인 에이전트"가 아니라 메인 에이전트가 읽는 문서임.
자동 발동은 두 가지로 결정됨
- 폴더 — 정해진 경로에 있어야 존재를 인식함. 경로가 틀리면 아예 없는 것과 같음.
description한 줄 — 평소 본문은 읽지 않음. "언제 쓰는지"를 문장으로 써야 걸림.CLAUDE.md가 "그래도 놓치지 마라"를 담당함.
tools: 줄이 권한을 정함
- 적지 않은 도구는 그 서브에이전트에게 아예 보이지 않음.
- 실습 2의
reviewer에tools: Read만 주면 검토자가 직접 고치는 것을 구조로 막은 것임. - "하지 마"라고 적는 것과 도구를 안 주는 것은 다름. 앞은 부탁이고 뒤는 차단임.
| 패턴 | 예시 | 주의 |
|---|---|---|
| 순차 | 검색 → 판단 → 검토 | 앞 단계 실패가 전파됨 |
| 병렬 | 자료원 3곳 동시 조회 | 사용량이 빠르게 소모됨 |
| 반복 | 검토 통과까지 수정 | 종료 조건 필수 |
- 도구별 대응 — 메모리 파일:
CLAUDE.md(Claude Code) /AGENTS.md(Codex · Antigravity)
5장. 4단계 — harness engineering#
- harness는 마구(馬具)라는 뜻임. 말을 못 달리게 하는 것이 아니라 달리는 방향을 잡아 주는 장치임.
| 장치 | Claude Code에서 | 무엇을 막나 |
|---|---|---|
| 승인 프롬프트 | 기본 동작 | 모르는 사이에 파일이 바뀌는 것 |
| 권한 모드 | 작업 폴더 한정 | 엉뚱한 폴더를 건드리는 것 |
| 훅(Hook) | settings.json의 hooks |
특정 명령을 기계적으로 차단·검사 |
| 검토 에이전트 | .claude/agents/reviewer.md |
자기가 만든 것을 자기가 통과시키는 것 |
| 규칙 파일 | CLAUDE.md의 "하지 말 것" |
반복해서 나는 사고 |
# 하지 말 것
- .env 파일을 절대 커밋하지 않는다.
- 자동 재시도 루프를 만들지 않는다. 실패하면 사용자에게 알리고 멈춘다.
- 한 번의 사용자 요청당 외부 API 호출은 최대 1회로 제한한다.
- 대규모 리팩터링은 먼저 계획을 보여주고 승인받는다.
- 금지는 이름을 찍어서 적을 것. "아껴 쓰라"처럼 모호하면 AI가 알아서 판단해 버림.
- 만드는 주체와 검토하는 주체를 분리함. 같은 문맥에서 자기 결과를 점검하면 그냥 통과시킴.
CLAUDE.md는 강제가 아니라 부탁임. 반드시 막아야 하는 것은 훅이나tools:제한으로 걸 것.
6장. 연구·교육에서의 함의#
- 여는 장의 권한 차이가 실무에서 어떤 결과로 이어지는가.
| 영역 | 채팅형 | 코딩 에이전트 |
|---|---|---|
| 빅데이터 입력 | 업로드 용량·개수 제한 | 폴더 단위로 수천 건 |
| 비정형 데이터 입력 | PDF·이미지 몇 장이 한계. 표로 안 정리된 자료는 매번 손으로 붙여넣어야 함 |
PDF·이미지·음성·영상·HWP를 폴더째 두고 스크립트로 일괄 변환·처리 |
| 결과 표준화 | 매번 흔들림 | 규칙 파일로 고정 |
| 재현 가능성 | 대화가 사라지면 끝 | 코드가 남아 언제든 재실행 |
| 협업·버전 관리 | 대화창 공유 | 저장소 공유 + Git |
비정형 데이터가 왜 따로 중요한가
- 비정형 데이터(unstructured data)란 행과 열로 정리되지 않은 자료임 — 기사 원문, 인터뷰 녹취, 방송 영상, PDF 보고서, 판결문, 설문 주관식 답변, SNS 게시글, 사진.
- 사회과학·언론 연구가 실제로 다루는 자료는 대부분 여기 속함. 엑셀에 이미 정리된 숫자는 오히려 드묾.
- 채팅형에서는 이런 자료를 사람이 하나씩 열어 붙여넣어야 함. 100건이 넘어가는 순간 사실상 불가능해짐.
- 코딩 에이전트는 ①폴더째 놓아두고 → ②변환 스크립트를 스스로 짜서 → ③같은 기준으로 전건 처리 → ④결과를 표로 저장까지 감. 3장 ①번 방법이 그대로 쓰임.
- 예 — 뉴스 500건의 PDF에서 발언 인용문만 뽑아 화자·날짜와 함께 표로 만들기. 방송 영상 30편의 자막을 추출해 주제별로 분류하기. 사람이 하면 주 단위, 에이전트로는 시간 단위.
- 단, 전수 검수는 여전히 사람 몫임. 표본을 뽑아 원자료와 대조하지 않으면 연구 자료로 쓸 수 없음.
- 재현 가능성이 결정적임. 채팅형에 물어 얻은 결과는 논문·보고서의 방법론으로 쓰기 어려움. "ChatGPT에 물어봤다"는 방법 서술이 되지 못함.
- 표준화가 검증을 가능하게 함.
CLAUDE.md를 함께 쓰면 여러 사람의 결과물 형식이 통일되어 서로 대조할 수 있게 됨. - 협업이 파일 단위로 이뤄짐. 공동연구자가 저장소를 받으면 규칙·스킬·에이전트가 함께 딸려옴.
7장. 도구 지형#
| Claude Code | OpenAI Codex | Google Antigravity | |
|---|---|---|---|
| 만든 곳 | Anthropic | OpenAI | |
| 터미널 명령 | claude |
codex |
agy |
| 편집기 확장 | VS Code · JetBrains 공식 확장 | VS Code 확장 | 자체 편집기 + CLI |
| 규칙 파일 | CLAUDE.md |
AGENTS.md |
AGENTS.md (또는 GEMINI.md) |
| 서브에이전트 | .claude/agents/*.md |
.codex/agents/*.toml |
.agents/agents/*.md |
| 스킬 | .claude/skills/ |
.agents/skills/ |
.agents/skills/ |
| 내장 웹검색 | 있음 (WebSearch) |
있음 (web_search) |
있음 |
| 로그인 계정 | Claude 유료 구독 | ChatGPT 계정 (Plus 이상 권장) | Google 계정 |
| 이 특강 | 기본 경로 | 대체 경로 — 13-8 전용 절차 | 대체 경로 — 13-9 |
- 사용법이 거의 같음. 하나만 골라 끝까지 진행함. 여러 개를 동시에 깔면 오히려 헷갈림.
- 단, 파일 위치가 도구마다 다름. Claude Code용 폴더 구조를 그대로 Codex에 쓰면 서브에이전트·스킬이 나타나지 않음. 그래서 Codex는 13-8의 전용 절차를 따로 실었음.
- Gemini CLI(
gemini명령)는 2026년 6월 18일부터 개인 계정(무료·Google AI Pro·Ultra)에 서비스를 중단했고, 후속 도구가 Antigravity CLI(agy명령)임. 옛 자료의gemini로그인은 더 이상 되지 않음. (유료 Gemini API 키·기업 계정만 예외) - Antigravity는 무료 한도가 주 단위로 걸려 실습 도중 막힐 수 있음. Google AI Pro 구독자에게 권함.
- Cursor·Windsurf 같은 편집기형 도구도 성격은 같음(여는 장의 IDE 코딩 에이전트). 다만 이 특강의 파일 경로는 Claude Code와 VS Code 기준임.
8장. 환경 구축 (PART 1의 유일한 실습)#
이 장만 통과하면 나머지는 전부 대화로 진행됨. 가장 많이 막히는 구간이므로 네 가지 설치 방법을 모두 실었음. 하나가 안 되면 바로 다음 것으로 넘어갈 것. 상세 절차: 입문 가이드 1부
설치는 어느 인터넷에서 하나 — 학교·기관 Wi-Fi는 피할 것
학교·회사·공공기관 Wi-Fi는 보안 필터가 프로그램 내려받기를 막거나 느리게 하는 경우가 많음. 여럿이 같은 Wi-Fi로 수백 MB를 동시에 받으면 중간에 끊기기도 함. 이때 뜨는 오류는 명령이 틀린 것처럼 보여서 원인을 찾기 어려움.
순서 어디서 언제 1 집 Wi-Fi 수업 전에 설치·로그인까지 끝내 둠 (가장 권함) 2 내 휴대폰 핫스폿 수업 중 설치·로그인이 필요할 때. 기관 Wi-Fi에서 한 번이라도 아래 증상이 나오면 고민하지 말고 바로 전환 3 학교·기관 Wi-Fi 설치가 끝난 뒤 실습(대화·검색)에는 대개 문제없음
- 망 문제의 증상 —
ETIMEDOUT·ECONNRESET·ENOTFOUND·403·certificate·SSL이 들어간 오류, 설치 스크립트의syntax error near unexpected token '<', 진행률이 몇 분째 멈춤, 로그인 브라우저 창이 "연결할 수 없음".- 핫스폿 데이터 사용량(대략) — Claude Code 약 110MB · Codex 약 160MB · VS Code 약 100MB · Node.js 약 30MB · 파이썬 약 30MB. 도구 하나만 고르면 300MB 안팎임.
- 핫스폿은 각자 자기 휴대폰으로. 한 사람의 핫스폿에 여럿이 붙으면 기관 Wi-Fi와 똑같이 느려짐.
- 핫스폿으로 바꾼 뒤에는 터미널을 새로 열고 실패했던 명령을 그대로 다시 실행하면 됨. 반쯤 설치된 것을 지울 필요 없음.
8-1. 바탕 도구 네 가지#
| 준비물 | 받는 곳 | 왜 필요한가 | 주의 |
|---|---|---|---|
| VS Code | code.visualstudio.com |
파일을 보고 고치는 편집기. 터미널도 여기 안에 들어 있음 | 확장에서 Python 설치 |
| 터미널 | VS Code → Terminal → New Terminal |
명령을 글자로 입력하는 창. AI 도구가 여기서 돎 | 단축키 Ctrl + 백틱(`) |
| Node.js | nodejs.org (LTS) |
방법 4(npm)를 쓸 때만 필요. 방법 1~3은 없어도 됨 | Windows는 "Add to PATH" 체크 유지 · 22 버전 이상 · "Automatically install the necessary tools..." (필요한 도구를 자동으로 설치) 체크하지 말 것 |
| 파이썬 | python.org (3.11 이상) |
실습 2의 검색 스크립트를 돌림 | Windows는 "Add python.exe to PATH" 반드시 체크 |
Windows에서 권하는 것 하나 더 — Git for Windows. 필수는 아니지만 설치해 두면 Claude Code가 더 익숙한 방식(Bash)으로 명령을 실행함. 없으면 PowerShell로 돎.
터미널에서 확인 — 세 줄 모두 버전이 나와야 다음으로 감
node -v # 방법 4를 쓸 때만 필요. v22.x 이상
npm -v # 위와 같음
python --version # macOS는 python3 --version
command not found/'python'은(는) ... 인식되지 않습니다가 뜨면 → 터미널을 완전히 껐다 켜고 재시도. 그래도 안 되면 설치 파일을 다시 실행해 PATH 추가를 확인할 것.
8-2. AI 코딩 도구 설치 — 네 가지 길#
결론부터 — 처음이면 방법 1을 쓸 것. 터미널 명령을 한 줄도 치지 않고 끝남.
Windows 사용자 — 터미널은 PowerShell 하나로 통일하고, 설치 전에 이 한 줄부터
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned -ForceVS Code 터미널의 기본값이 PowerShell이고, 이 교안의 Windows 명령도 모두 PowerShell 기준임. 새 Windows PC는 PowerShell이 npm으로 깐
claude·codex명령과 가상환경 활성화(Activate.ps1)를 막아 둠. 위 한 줄은 내 계정에만 적용되고 관리자 권한도 필요 없음. 처음에 한 번 해 두면 이후 이 오류가 생기지 않음. CMD(명령 프롬프트)는 쓰지 말 것 — 교안의 PowerShell 명령과 섞이면 오히려 실패가 늘어남.
| 방법 | Node.js | 자동 업데이트 | 이럴 때 | |
|---|---|---|---|---|
| 1 | VS Code 확장 | 불필요 | ○ | 초보자 · 터미널이 낯선 경우 ← 권장 |
| 2 | 공식 설치 스크립트 | 불필요 | ○ | 터미널에서 claude 명령을 직접 쓰고 싶을 때 |
| 3 | 패키지 관리자 (winget · Homebrew) |
불필요 | ✕ (수동) | 회사 PC 등 스크립트 실행이 막힌 환경 |
| 4 | npm | 22 이상 필요 | ○ | 이미 Node.js를 쓰고 있을 때 |
방법 1 · VS Code 확장 — 가장 쉬움
- VS Code를 열고 왼쪽 확장(Extensions) 아이콘을 누름 — 단축키
Ctrl+Shift+X(Mac은Cmd+Shift+X) - 검색창에
Claude Code를 입력 → 만든 이가 Anthropic인 것을 확인하고 Install - 설치되면 왼쪽 활동 표시줄에 ✱ 아이콘이 생김. 누르면 대화 패널이 열림
- 처음 열면 로그인 화면이 뜸 → Sign in → 브라우저에서 승인
- 이 방법은 별도의 본체 설치가 필요 없음. 확장이 자체 실행 파일을 품고 있음. Node.js도 필요 없음.
- 필요 조건 — VS Code 1.94 이상 + 유료 구독(Pro·Max·Team·Enterprise) 또는 Console 계정.
- Cursor 등 VS Code 계열 편집기에서도 같은 방식으로 설치됨.
- 확장이 안 보이면 VS Code를 재시작하거나,
Ctrl+Shift+P→Developer: Reload Window.
단, 한 가지만 기억할 것 — 확장을 깔아도 터미널에서
claude라고 치면 안 됨. 확장은 자기 패널 안에서만 돎. 터미널 명령까지 쓰려면 방법 2~4를 추가로 해야 함. 이 특강의 실습은 터미널에서claude를 실행하는 방식으로 적혀 있지만, 확장 패널에서 같은 프롬프트를 넣어도 결과는 같음. (폴더 여는 법은 12-1 참고)
방법 2 · 공식 설치 스크립트 — 터미널에서 claude를 쓰려면
자기 운영체제·자기 터미널에 맞는 한 줄만 복사해 붙여넣을 것. 섞어 쓰면 반드시 실패함.
# macOS · Linux · WSL (터미널)
curl -fsSL https://claude.ai/install.sh | bash
# Windows — PowerShell 창에서
irm https://claude.ai/install.ps1 | iex
REM Windows — 명령 프롬프트(CMD) 창에서
curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd
지금 내가 PowerShell인지 CMD인지 구분하는 법 — 프롬프트 맨 앞을 볼 것
| 화면에 이렇게 보이면 | 이것은 | 써야 할 명령 |
|---|---|---|
PS C:\Users\홍길동> |
PowerShell (앞에 PS가 붙음) |
irm ... | iex |
C:\Users\홍길동> |
CMD (PS가 없음) |
curl ... && install.cmd ... |
~ $ · 사용자@컴퓨터:~$ |
macOS · Linux · Git Bash | curl ... | bash |
- VS Code 터미널에서는 오른쪽 위
+옆 꺾쇠(∨)를 눌러PowerShell·Command Prompt·Git Bash를 골라 열 수 있음. - 설치가 끝나면 터미널을 완전히 닫았다 새로 열 것. 그래야
claude명령이 인식됨.
방법 3 · 패키지 관리자 — 스크립트가 막힐 때
# Windows (PowerShell 또는 CMD)
winget install Anthropic.ClaudeCode
# macOS (Homebrew가 깔려 있어야 함)
brew install --cask claude-code
- 자동 업데이트가 안 됨. 가끔 직접 올려야 함 —
winget upgrade Anthropic.ClaudeCode/brew upgrade claude-code - Ubuntu·Debian·Fedora는
apt·dnf·apk저장소도 제공됨(공식 문서 참조).
방법 4 · npm — 이미 Node.js를 쓰고 있다면
npm install -g @anthropic-ai/claude-code
- Node.js 22 이상이 필요함. 낮은 버전이면
EBADENGINE경고가 뜸(대개 설치 자체는 됨). sudo npm install -g는 쓰지 말 것. 권한이 꼬이고 보안상으로도 나쁨. 권한 오류(EACCES)가 나면 방법 1·2·3으로 전환할 것.- 업데이트는
npm install -g @anthropic-ai/claude-code@latest(npm update -g는 최신으로 안 갈 수 있음).
Codex를 고른 경우 — 설치
아래 중 한 줄만 실행함. 처음이면 npm 줄을 권함(Node.js가 이미 깔려 있다는 전제).
# (권장) npm — Windows · macOS 공통. Node.js 16 이상
npm install -g @openai/codex
# Windows — PowerShell, Node.js 없이
irm https://chatgpt.com/codex/install.ps1 | iex
# Windows — winget
winget install OpenAI.Codex
# macOS · Linux — Node.js 없이
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# macOS — Homebrew
brew install --cask codex
- 설치 후 터미널을 닫았다 새로 열고
codex --version→codex-cli 0.1xx.x처럼 나오면 성공. - Windows PowerShell에서
이 시스템에서 스크립트를 실행할 수 없으므로 ... codex.ps1이 뜨면 → 8-5 표의 실행 정책 줄을 볼 것. npm으로 깐 명령 전부(claude·codex)에 똑같이 생기는 문제임. - 업데이트는
npm install -g @openai/codex@latest(npm으로 깐 경우). - VS Code 확장도 있음 — 확장 검색창에
Codex→ 만든 이가 OpenAI인 것을 Install. 확장은 터미널codex와 설정·로그인을 함께 씀.
Antigravity(Google)를 고른 경우 — 설치
# Windows — PowerShell
irm https://antigravity.google/cli/install.ps1 | iex
REM Windows — 명령 프롬프트(CMD)
curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd
# macOS · Linux
curl -fsSL https://antigravity.google/cli/install.sh | bash
- 터미널을 새로 열고
agy --version으로 확인. 명령 이름이gemini가 아니라agy임. npm install -g @google/gemini-cli로 까는 옛 Gemini CLI는 설치는 되지만 개인 Google 계정으로 로그인해 쓸 수 없음(2026-06-18 종료). 이 교안은agy를 기준으로 함.
8-3. 작업 폴더 만들기 — 도구를 처음 켜기 전에#
AI 코딩 도구는 "지금 열려 있는 폴더"를 작업 공간으로 삼음. 그 폴더의 파일을 읽고, 만들고, 고침. 그래서 로그인(8-4)을 포함해 도구를 처음 켜기 전에 작업 폴더부터 만듦. 순서가 뒤바뀌면 엉뚱한 곳에 파일이 생기거나 홈 폴더 전체가 작업 대상이 됨.
| 규칙 | 이유 |
|---|---|
Windows는 C:\vibecoding\ 아래 | 바탕화면은 OneDrive 동기화 때문에 실제 경로가 C:\Users\...\OneDrive\바탕 화면\처럼 한글·띄어쓰기가 섞인 주소가 되어 오류가 잦음 |
macOS는 ~/Desktop/ 아래 | 찾기 쉽고 경로 문제가 거의 없음 |
| 폴더 이름은 영문 소문자 + 밑줄(_)·하이픈(-) | 한글·공백·특수문자는 일부 도구에서 오류 |
| 실습 하나 = 폴더 하나 | CLAUDE.md·AGENTS.md·.claude/·.codex/는 폴더 단위로 적용됨. 실습 1·2를 섞으면 규칙이 엉킴(12-1·13-1) |
| 홈 폴더·바탕화면 자체에서 그냥 실행하지 않음 | 그 안의 모든 파일이 작업 대상이 됨 |
① 연습용 폴더를 만듦 — 8-4의 첫 실행·로그인을 여기서 함. 자기 운영체제 블록만 복사.
# Windows (PowerShell)
cd C:\
mkdir vibecoding -ErrorAction SilentlyContinue
cd vibecoding
mkdir hello_vibe
cd hello_vibe
# macOS
cd ~/Desktop
mkdir hello_vibe
cd hello_vibe
② VS Code에서 그 폴더를 엶 — File → Open Folder → hello_vibe 선택. "이 폴더의 작성자를 신뢰하나요?"가 뜨면 신뢰.
이렇게 열면 VS Code 터미널이 자동으로 그 폴더에서 시작하고, 확장(방법 1) 패널도 이 폴더를 작업 공간으로 씀.
③ 위치를 눈으로 확인 — 도구를 실행하기 전 매번 터미널 경로 끝을 봄.
PS C:\vibecoding\hello_vibe> ← Windows
사용자이름@맥북 hello_vibe % ← macOS
- 도구가 "이 폴더를 신뢰하나요?"(Claude Code
Yes, proceed· CodexTrust this folder?)라고 물으면 방금 만든 작업 폴더일 때만 Yes. 모르는 폴더에서 이 질문이 뜨면cd로 작업 폴더로 옮긴 뒤 다시 실행할 것. - Codex는 이 "신뢰" 여부에 따라 폴더 안의 설정·서브에이전트를 읽을지 말지가 갈림(13-8). 그래서 폴더를 먼저 정하고 그 자리에서 신뢰하는 순서가 중요함.
- 실습용 폴더는 PART 2에서 따로 만듦 — 웹은
factcheck_tavily(12-1), 에이전트는factcheck_agent(13-1). 모두C:\vibecoding\(macOS는~/Desktop/) 아래에 둠.
8-4. 설치 확인과 로그인#
터미널 경로 끝이 hello_vibe인지 확인한 뒤:
claude --version # 2.1.xxx (Claude Code) 처럼 버전이 찍히면 성공
claude doctor # 설치 상태를 스스로 점검해 문제를 알려 줌
claude # 실행 → 브라우저 로그인 → 끝내려면 /exit
| 단계 | 기대하는 화면 |
|---|---|
claude --version |
2.1.211 (Claude Code) 같은 줄 하나 |
claude 첫 실행 |
브라우저가 열리며 로그인 요청 → 승인하면 터미널로 돌아옴 |
| 로그인 후 | 프롬프트 입력창이 뜸. 아무 말이나 걸어 답이 오면 끝 |
로그인 따라 하기 — 구독한 사람 기준
로그인은 처음 한 번만 하면 됨. 터미널로 하든 VS Code 확장으로 하든 같은 계정 정보를 함께 씀. 비밀번호를 터미널에 치는 일은 없음 — 항상 브라우저에서 로그인하고 "허용"만 누르면 끝남.
먼저 8-3의 작업 폴더(hello_vibe)로 이동해 둠. 아래 첫 실행·로그인은 모두 그 폴더에서 함.
① Claude Code — 터미널에서
- 터미널에
claude입력 → Enter - 글자 색 테마를 고르라는 화면 → 방향키로 고르고 Enter (아무거나 괜찮음)
- 로그인 방법 선택 화면 →
Claude account with subscription(Pro·Max·Team·Enterprise)을 고르고 Enter - 브라우저가 저절로 열림 → 구독한 claude.ai 계정으로 로그인 →
Authorize(승인) 클릭 - "로그인 성공" 문구가 뜨면 터미널로 돌아와 Enter
- "이 폴더의 파일을 신뢰하느냐"는 질문 →
Yes, proceed(작업 폴더 안에서 실행했을 때만 Yes) - 입력창에
안녕이라고 쳐서 답이 오면 끝. 나갈 때는/exit
- 브라우저가 안 열리면 — 터미널에 긴 주소가 찍혀 있음. 안내대로
c를 눌러 복사 → 브라우저 주소창에 붙여넣기 → 승인 후 나오는 코드를 복사해 터미널에 붙여넣기. - 다른 계정으로 바꾸려면
claude안에서/logout후 다시claude.
② Claude Code — VS Code 확장에서
- 왼쪽(또는 편집기 오른쪽 위)의 ✱ 아이콘을 눌러 Claude 패널을 엶
Sign in→ Claude.ai 구독(Claude.ai Subscription) 쪽을 고름- 브라우저에서 로그인 → Authorize
- 브라우저가 "Visual Studio Code를 여시겠습니까?"라고 물으면 열기 → VS Code로 돌아와 패널에 입력창이 보이면 끝
③ Codex — 터미널에서 (Codex를 고른 경우)
- 터미널에
codex입력 → Enter - 로그인 방법 화면에서
Sign in with ChatGPT를 고르고 Enter - 브라우저가 열림 → ChatGPT 계정으로 로그인 → 승인(Continue) → "Codex에 로그인됨" 화면이 나오면 브라우저를 닫음
- 터미널로 돌아오면 입력창이 뜸.
안녕을 쳐서 답이 오면 끝. 나갈 때는/quit - 확인:
codex login status→Logged in using ChatGPT가 나오면 정상
- 브라우저 로그인이 안 돌아오면 —
codex login --device-auth실행 → 화면에 나온 주소를 브라우저로 열고 화면의 코드를 입력. 회사망·원격 PC에서 특히 잘 됨. - 처음 실행한 폴더에서
Trust this folder?가 뜨면 작업 폴더일 때만 Yes. 이 선택이 13-8에서 결정적임. - VS Code 확장도 같음 — Codex 아이콘(왼쪽 또는 오른쪽 사이드바) →
Sign in with ChatGPT→ 브라우저 승인 → VS Code로 돌아옴. 터미널에서 이미 로그인했다면 그대로 이어짐. - 요금 — ChatGPT Plus·Pro·Business·Edu·Enterprise에 포함. Free·Go에도 한시적으로 열려 있으나 한도가 작아 실습엔 Plus 이상을 권함.
④ Antigravity — 터미널에서 (Google을 고른 경우)
- 터미널에
agy입력 → Enter - 브라우저가 저절로 열림 → Google 계정으로 로그인 → 권한 허용
- 터미널로 돌아와 입력창이 뜨면 끝. 계정을 바꾸려면
/logout
- 무료 Google 계정도 되지만 주간 한도가 있음. Google AI Pro 구독 계정으로 로그인하면 한도가 넉넉함.
유료 구독이 필요함. Claude Code는 Pro·Max·Team·Enterprise 구독 또는 Console(API) 계정에서 동작함. 무료 claude.ai 계정으로는 쓸 수 없음. PART 2 전까지 결제를 마칠 것. (실습 1의 Gemini·Tavily 키와는 별개임 — 10장 참조)
8-5. 설치가 안 될 때#
| 화면에 뜨는 말 | 원인 | 해결 |
|---|---|---|
command not found: claude'claude'은(는) ... 인식되지 않습니다 |
설치 경로가 아직 반영 안 됨 | 터미널을 완전히 껐다 켜기. VS Code 자체를 재시작하면 더 확실함 |
'irm' is not recognized ... |
CMD에서 PowerShell 명령을 씀 | PowerShell 창을 새로 열거나, CMD용 명령(방법 2)을 쓸 것 |
The token '&&' is not a valid statement separator |
PowerShell에서 CMD 명령을 씀 | PowerShell용 irm ... | iex를 쓸 것 |
syntax error near unexpected token '<' · 403 |
설치 스크립트를 못 받아옴(네트워크·방화벽) | VPN을 끄고 내 휴대폰 핫스폿으로 바꿔 같은 명령을 재시도. 안 되면 방법 3(winget·brew) |
npm 권한 오류 EACCES |
전역 설치 폴더에 쓰기 권한 없음 | sudo를 붙이지 말 것. 방법 1·2·3으로 전환 |
[Codex] macOS에서 npm install -g @openai/codex가 EACCES |
Node.js 공식 설치 파일로 깐 Mac에서 흔함. 전역 폴더가 관리자 소유 | sudo 금지. npm을 포기하고 brew install --cask codex 또는 curl -fsSL https://chatgpt.com/codex/install.sh | sh로 설치 → 터미널 새로 열고 codex --version |
[Codex] npm 설치 중 ETIMEDOUT · ECONNRESET · ENOTFOUND · 403 · self-signed certificate |
학교·회사망이 npm 저장소나 Codex 실행 파일 내려받기를 막음 | 내 휴대폰 핫스폿으로 바꿔 같은 명령을 다시 실행하는 것이 가장 확실함(8장 첫머리의 망 안내). 망을 못 바꾸면 Windows는 winget install OpenAI.Codex, macOS는 brew install --cask codex를 시도 (이 방법도 인터넷이 필요하므로 같은 망에서 막힐 수 있음) |
[Codex] 설치는 성공했는데 codex를 인식 못 함 |
npm 전역 폴더가 PATH에 없음 | ① 터미널을 완전히 닫았다 열기 ② npm prefix -g로 나온 폴더(Windows는 보통 C:\Users\내이름\AppData\Roaming\npm)가 PATH에 있는지 확인 — 없으면 Node.js 설치 파일을 다시 실행해 Add to PATH 체크 |
[Codex] codex가 바로 꺼지거나 "액세스 거부" · 백신 경고 |
백신(Windows Defender 등)이 codex.exe를 차단·격리 |
codex doctor로 점검 → 백신의 격리 목록에서 복원·허용. 학교 PC처럼 내가 못 바꾸는 PC면 개인 노트북을 쓸 것 |
[Claude Code] npm 설치 끝에Native package "@anthropic-ai/claude-code-win32-x64" not found(Mac은 ...-darwin-arm64 등) |
운영체제용 본체 파일을 내려받다 실패함(망 차단·중간 끊김), 또는 npm 설정이 선택 패키지를 건너뜀 | 같은 명령 npm install -g @anthropic-ai/claude-code를 다시 실행. 또 실패하면 휴대폰 핫스폿 등 다른 망에서 재시도하거나 방법 2(공식 설치 스크립트)로 전환 |
[Claude Code] Failed to place binary · EBUSY · EPERM |
Claude가 실행 중이라 파일을 바꿀 수 없음(업데이트·재설치할 때 흔함), 또는 백신이 잡고 있음 | 열려 있는 claude를 모두 /exit, VS Code 터미널도 모두 닫음 → 새 터미널에서 다시 설치 |
[Claude Code] Mac에서 running x64 Node under Rosetta 2 |
Apple Silicon(M1~) Mac에 Intel용 Node.js가 깔림 | nodejs.org에서 Node.js LTS를 다시 내려받아 설치 → 재설치. 번거로우면 방법 2(curl ... | bash)로 전환 — Node.js가 필요 없음 |
[Claude Code] claude doctor가 설치가 여러 개라고 경고 · 고쳐도 옛 버전이 실행됨 |
npm 설치와 공식 스크립트 설치가 둘 다 있음 | 하나만 남김. npm 쪽을 지우려면 npm uninstall -g @anthropic-ai/claude-code → 터미널 새로 열고 claude --version |
EBADENGINE 경고 |
Node.js 버전이 22 미만 | Node.js LTS를 다시 설치하거나 방법 2로 전환 |
| PowerShell에서 스크립트 실행이 차단됨 | 실행 정책 제한(회사 PC에 흔함) | 방법 3(winget) 또는 방법 1(VS Code 확장) |
이 시스템에서 스크립트를 실행할 수 없으므로... codex.ps1 (또는 claude.ps1) 파일을 로드할 수 없습니다 |
Windows PowerShell의 실행 정책이 npm 명령 파일을 막음 (새 PC의 기본값) | PowerShell에 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned 입력 → Y → 터미널 새로 열기. 관리자 권한 필요 없음. 가상환경 Activate.ps1 오류도 같이 풀림 |
Codex에서 setup refresh had errors또는 명령 실행이 모두 실패 |
Windows용 Codex 샌드박스(관리자 모드) 준비 실패 | %USERPROFILE%\.codex\config.toml을 메모장으로 열어 맨 아래에 [windows] 줄과 sandbox = "unelevated" 줄을 넣고 저장. [windows] 줄이 이미 있으면 새로 넣지 말고 그 아래 sandbox = "elevated"를 "unelevated"로 고침(같은 줄이 두 번 있으면 Codex가 안 켜짐). 13-8 설치 스크립트는 작업 폴더에 이 설정을 미리 넣어 둠 |
gemini 로그인이 안 됨 · 서비스 중단 안내 |
Gemini CLI는 2026-06-18부터 개인 계정 미지원 | Antigravity CLI(agy)를 설치해 씀 (8-2) |
python을 못 찾음 (Windows) |
PATH에 안 잡힘 | 설치 파일 재실행 → Modify → Add to PATH 체크 |
| 로그인 화면이 계속 다시 뜸 | 브라우저 승인이 안 돌아옴 | 기관 Wi-Fi라면 먼저 핫스폿으로 바꿔 재시도. 그래도 안 되면 다른 브라우저를 기본으로 두고 재시도. 확장이면 Developer: Reload Window |
- 모든 오류의 1번 해결책 — 오류 메시지를 그대로 복사해 AI에게 붙여넣고 내 운영체제(Windows 11 / macOS)와 무엇을 하려던 중인지를 함께 밝히며 물을 것.
- 추측해서 이것저것 지우지 말 것. 설치가 반쯤 된 상태에서 손대면 원인 찾기가 더 어려워짐.
PART 2 전 과제 — 수업 전에 집 Wi-Fi에서 끝내 올 것 (8장 첫머리의 망 안내 참조)
- [ ]
python --version이 출력됨 - [ ] Claude Code가 네 방법 중 하나로 설치되고 로그인됨 (확장이면 패널에서 답이 오는 것까지 확인)
Codex를 고른 경우:codex login status→Logged in using ChatGPT/ Google을 고른 경우:agy에서 답이 옴 - [ ] 유료 구독 결제 완료
- [ ] GitHub 계정 생성
- [ ] Tavily API 키 발급 · Gemini API 키 발급 (둘 다 카드 불필요)
PART 2. 팩트체크 도구 실습#
9장. 실습의 전제#
| 실습 1 — 웹 | 실습 2 — 에이전트 | |
|---|---|---|
| 산출물 | index.html 하나 (분석 + 챗봇) |
로컬 폴더 1식 (서브에이전트 3 + 스킬 1) |
| 판정 LLM | gemini-3.1-flash-lite (브라우저에서 API 호출) |
Claude (Claude Code 본체가 직접 판정) |
| 검색원 | Tavily Search (basic) | Tavily + Claude Code 내장 WebSearch |
| 필요한 키 | TAVILY_API_KEY + GEMINI_API_KEY |
TAVILY_API_KEY 하나 |
| 실행 위치 | 브라우저 (GitHub Pages) | 내 컴퓨터 터미널 |
| 작업 폴더 | factcheck_tavily/ |
factcheck_agent/ (별도 폴더) |
- 두 실습의 LLM이 다름.
- 실습 1은
gemini-3.1-flash-lite를 웹에서 직접 부름. 그래서 Gemini 키가 필요함. - 실습 2는 Claude Code 자체가 판정자임. 별도의 LLM 키가 필요 없음.
- 작업 폴더를 반드시 분리함. 이유는 13-1에서 다룸.
판정 척도 — SNU 팩트체크 6단계#
| 판정 | 기준 |
|---|---|
| 사실 | 객관적 증거에 비추어 완전히 정확하고 참인 경우 |
| 대체로 사실 | 대체로 맞으나 일부 세부 보충 설명이나 해명이 필요한 경우 |
| 절반의 사실 | 사실과 거짓이 섞여 있거나 중요한 맥락이 빠져 일부만 맞는 경우 |
| 대체로 사실 아님 | 핵심 주장에 오류가 있거나 사실보다 허위가 더 많은 경우 |
| 전혀 사실 아님 | 객관적 증거와 명백히 다르며 거짓으로 판명된 경우 |
| 판단 유보 | 증거가 부족하거나 진위를 판가름하기 어려운 경우 |
- 등급만 던지지 않음. 판정 근거(+출처 URL) · 수집 자료 · 추가 확인 항목을 함께 냄.
- 결과 없음 ≠ 사실. 근거가 0건이면 판정은 판단 유보뿐임. 초보자가 가장 자주 놓치는 대목임.
- 문장을 통째로 넣지 말고 핵심 명사 두세 개로 검색할 것.
- 키를 코드에 적지 않음. 웹앱은 화면 입력 +
localStorage, 파이썬은.env+.gitignore.
이 도구는 팩트체크를 대신해 주지 않음. AI의 판정은 초벌 정리일 뿐임. 근거로 달린 URL을 사람이 열어 확인하지 않으면 그 판정은 쓸 수 없음. 이 실습의 목표는 "AI에게 판정을 맡기는 법"이 아니라 "AI의 판정을 검증하는 틀을 만드는 법"임.
10장. API 키 발급#
API 키란 — 바깥 서비스를 쓸 때 "나"임을 증명하는 긴 문자열임. 비밀번호와 같게 다뤄야 함. 남에게 보이면 그 사람이 내 요금으로 쓸 수 있음.
| 주소 | 카드 | 비고 | |
|---|---|---|---|
| Tavily | https://app.tavily.com | 불필요 | 키가 tvly-로 시작 · 검색 담당 |
| Gemini | https://aistudio.google.com/api-keys | 불필요 | 키가 AIza로 시작 · 판정 담당 · gemini-3.1-flash-lite |
- 두 키 모두 각자 직접 발급함. 하나를 여럿이 돌려쓰면 한 번의 실습으로 월 한도를 소진함.
WebSearch(실습 2의 둘째 검색원)는 키가 필요 없음. Claude Code 내장 도구이고 크레딧과 무관함.- 실습 2에는 Gemini 키가 필요 없음. 판정을 Claude Code가 직접 하기 때문임.
- 발급한 키는 메모장에 따로 보관할 것. 화면을 닫으면 다시 못 보는 경우가 많음.
Tavily 크레딧 — Search basic 1 / 질의, advanced 2 / 질의.
이 실습은 basic만 씀. crawl은 절대 금지(URL 1,000개에 약 300크레딧). 1인 실습 전체 약 40크레딧.
# 발급 직후 확인 — 키가 살아 있는지 미리 확인해 두면 실습 중 헤매지 않음
curl -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" -H "Authorization: Bearer YOUR_TAVILY_KEY" \
-d '{"query":"백신 자석","search_depth":"basic","max_results":5}'
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent" \
-H "x-goog-api-key: YOUR_GEMINI_KEY" -H "Content-Type: application/json" \
-d '{"contents":[{"parts":[{"text":"안녕"}]}]}'
- Windows PowerShell에서는 줄 끝의
\대신 백틱(`)을 쓰거나, 한 줄로 이어서 붙여넣을 것. - Gemini에서
404가 나면 모델명을gemini-3.5-flash-lite또는gemini-2.5-flash-lite로 바꿔 볼 것. - 모델명·요금·무료 한도는 자주 바뀜. 실습 직전에 각 서비스 문서에서 확인할 것.
11장. GitHub 저장소#
GitHub란 — 코드를 올려 두는 웹 공간임. GitHub Pages는 거기 올린 index.html을
누구나 열 수 있는 웹사이트 주소로 바꿔 주는 무료 기능임. 실습 1의 결과물을 여기에 올림.
| 단계 | 작업 |
|---|---|
| ① 가입 | https://github.com/signup — 사용자명이 배포 URL에 그대로 들어감(신중히 정할 것) |
| ② 저장소 | https://github.com/new — 이름 factcheck_tavily · Public · README 체크 |
| ③ 파일 | Add file → Upload files로 index.html을 맨 위(루트)에 올림 |
| ④ Pages | Settings → Pages → Source Deploy from a branch → main / (root) → Save |
| ⑤ 확인 | 1~3분 뒤 https://<사용자명>.github.io/factcheck_tavily/ |
Public으로 올린다는 것은 전 세계에 공개한다는 뜻임. 배포 전 점검 — [ ] 코드에
AIza로 시작하는 문자열 없음 [ ]tvly-로 시작하는 문자열 없음
VS Code에서Ctrl+F로AIza와tvly-를 각각 검색해 0건인 것을 눈으로 확인할 것. 한 번 올라간 키는 지워도 회수되지 않음. 실수로 올렸다면 즉시 해당 서비스에서 키를 폐기하고 재발급할 것.
- 실습 1의 작업 폴더는
factcheck_tavily/. 실습 2는 별도 폴더에서 함(13-1 참조).
12장. 실습 1 — 팩트체크 판정 도구 (웹)#
12-1. 작업 폴더부터 — 여기서 시작함#
- AI 코딩 도구는 지금 열려 있는 폴더를 작업 공간으로 삼음.
- 그래서 폴더를 먼저 만들고, 그 안에서 도구를 실행함. 이 순서가 뒤바뀌면 사고가 남.
# macOS · Linux
cd ~/Desktop
mkdir factcheck_tavily
cd factcheck_tavily
claude
# Windows (PowerShell) — 경로가 단순한 곳을 권함
cd C:\
mkdir vibecoding -ErrorAction SilentlyContinue
cd vibecoding
mkdir factcheck_tavily
cd factcheck_tavily
claude
- Windows에서 바탕화면을 피하는 이유 — OneDrive 동기화가 켜져 있으면 바탕화면의 실제 경로가
C:\Users\...\OneDrive\바탕 화면\처럼 한글과 띄어쓰기가 섞인 주소가 되어 오류가 잦음.C:\vibecoding\처럼 영문·띄어쓰기 없는 경로를 권함. - 폴더 이름은 영문 소문자 + 밑줄로 지을 것. 한글·공백·특수문자는 피함.
- 터미널 경로 끝이
factcheck_tavily인지 눈으로 확인한 뒤claude를 실행함. - VS Code에서 File → Open Folder로 같은 폴더를 열어 두면 만들어진 파일이 바로 보임.
VS Code 확장(8장 방법 1)으로 하는 경우 — 터미널 명령 없이 이렇게 함.
- 탐색기에서
C:\vibecoding\factcheck_tavily폴더를 먼저 만듦 - VS Code → File → Open Folder → 그 폴더를 선택
- 왼쪽 ✱ 아이콘을 눌러 Claude 패널을 열고, 12-2의 프롬프트를 붙여넣음
| 확인할 것 | 이유 |
|---|---|
| 폴더 이름을 GitHub 저장소 이름과 같게 둠 | 나중에 올릴 때 헷갈리지 않음 |
| 바탕화면이나 홈 폴더에서 그냥 실행하지 않음 | 그 폴더 전체가 작업 대상이 되어 버림 |
| 실습 2는 다른 폴더에서 함 | 규칙 파일이 섞임 (13-1 참조) |
12-2. 던지는 것 — 프롬프트 한 장#
- 쪼개지 않음. 분석과 챗봇을 한 번에 요구함.
- 마지막 두 번째 문단(간결 조건)이 이 프롬프트의 핵심임. 이것이 없으면 결과물이 불필요하게 무거워짐.
- 아래 전체를 그대로 복사해 붙여넣을 것.
팩트체크 자동화 웹페이지 만들기
주장을 입력하면 자동으로 팩트체크해주는 웹페이지를 만들어줘. html js css 사용. GitHub 배포 예정.
이 웹페이지는 분석과 챗봇 2개 버전을 갖춰야 함.
LLM은 gemini-3.1-flash-lite 사용. GEMINI_API_KEY는 외부 이용자가 스스로 입력해서 사용. 발급 절차 간단 포함.
분석에서는 주장을 입력하면 검색어 뽑고 TAVILY 검색으로 참조자료를 수집한 뒤 판단해서 알려줘야 함.
TAVILY_API_KEY는 외부 이용자가 스스로 입력해서 사용. 발급 절차 간단 포함.
챗봇에서는 LLM이 일반 대화하다가 팩트체크나 그와 유사한 요청과 주장이 입력되면
앞의 분석 작동해 결과를 챗봇 대화창에 보여줘야 함.
초보자가 읽을 수 있게 간결하게 만들어줘. 화려한 UI보다 동작과 가독성을 우선. 주석은 한국어로.
만들기 전에 무엇을 만들지 먼저 알려줘.
판단은 다음 6단계 가운데 하나로 보여줘:
| 사실 | 제시된 주장이 객관적 증거에 비추어 볼 때 완전히 정확하고 참인 경우 |
| 대체로 사실 | 대체로는 맞으나 일부 세부적인 보충 설명이나 해명이 필요한 경우 |
| 절반의 사실 | 사실과 거짓이 섞여 있거나, 중요한 맥락이 빠져 있어 일부만 맞는 경우 |
| 대체로 사실 아님 | 핵심 주장에 오류가 있거나 사실보다 허위가 더 많은 경우 |
| 전혀 사실 아님 | 객관적 증거와 명백히 다르며 거짓으로 판명된 경우 |
| 판단 유보 | 증거가 부족하거나 진위 여부를 판가름하기 어려운 경우 |
왜 "만들기 전에 먼저 알려줘"인가 — 곧바로 파일을 만들지 않고 계획 화면이 먼저 뜸. 읽지 않고 승인하지 않는 습관을 여기서 잡음. 계획이 엉뚱하면 이 단계에서 되돌리는 것이 가장 쌈.
12-3. 돌아올 것 — 예측#
- 결과물은 매번 다름. 줄 수도 구조도 사람마다 다르게 나옴. 옆 사람과 달라도 정상임.
- 그래서 코드를 외우지 않고 네 가지 목록으로 대조함.
① 반드시 나와야 하는 것 — 프롬프트가 못박은 것
| 항목 | 확인 방법 |
|---|---|
| 키 입력칸 2개 + 발급 안내 | 화면 상단에 보이는가 |
| 분석 / 챗봇 두 화면 | 둘 다 접근 가능한가 |
| Tavily 검색 → Gemini 판정 순서 | 검색 없이 판정하지 않는가 |
| 6단계 중 하나의 판정 | 6개 밖의 말이 나오지 않는가 |
| 챗봇에서 주장 입력 시 분석이 작동 | 일반 대화와 구분되는가 |
| 한국어 주석 | 코드를 열어 확인 |
② AI가 알아서 정할 것 — 예측
| 항목 | 예상 |
|---|---|
| 파일 개수 | index.html 하나로 올 가능성이 높음. "GitHub 배포"가 단서가 됨 |
| 두 화면 전환 | 탭 또는 버튼 |
| 키 저장 방식 | localStorage |
| Tavily 파라미터 | search_depth="basic" · max_results 5 안팎 |
| 판정 표시 | 텍스트 또는 색 배지 |
| 오류 처리 | 401·429 정도는 잡아 줄 가능성이 높음 |
- 예상과 다르게 와도 틀린 것이 아님. 다르게 온 이유를 물어보는 것이 이 실습임.
- 이 표를 먼저 읽고 맞히기 게임처럼 대조하면 훨씬 잘 남음.
③ 어떤 형식으로 올까 — 골격 예측
- 아래는 실제 결과가 아니라 예측임. 변수명·순서·분량은 다르게 옴.
- 형식만 익히면 됨. 어느 결과물이든 이 다섯 자리는 반드시 있음.
<!DOCTYPE html>
<html lang="ko">
<head> … <style> … </style> </head>
<body>
<!-- ① 키 입력칸 2개 — 코드에 키가 없어야 함 -->
<input type="password" id="tavilyKey" placeholder="tvly-...">
<input type="password" id="geminiKey" placeholder="AIza...">
<!-- ② 두 화면 — 탭이나 버튼으로 전환 -->
<section id="분석">…</section>
<section id="챗봇">…</section>
<script>
/* ③ 키 저장 — localStorage 로 올 가능성이 높음 */
localStorage.setItem("tavily_key", …);
/* ④ Tavily 호출 — 이 형식이 핵심 */
await fetch("https://api.tavily.com/search", {
method: "POST",
headers: { "Content-Type": "application/json",
"Authorization": "Bearer " + tavilyKey },
body: JSON.stringify({ query, search_depth: "basic", max_results: 5 })
});
/* ⑤ Gemini 호출 — 모델명과 헤더가 맞는지 확인할 자리 */
await fetch("https://generativelanguage.googleapis.com/v1beta/models/"
+ "gemini-3.1-flash-lite:generateContent", {
method: "POST",
headers: { "Content-Type": "application/json",
"x-goog-api-key": geminiKey },
body: JSON.stringify({
system_instruction: { parts: [{ text: 판정지시문 }] },
contents: [{ role: "user", parts: [{ text: 주장 + 수집자료 }] }]
})
});
</script>
</body></html>
판정 지시문(system_instruction)에 들어갈 내용 — 이것도 형식이 정해짐
너는 팩트체크 판정자다. 아래 [수집 자료]만을 근거로 [주장]을 판정한다.
판정은 다음 여섯 개 중 정확히 하나만 고른다.
사실 / 대체로 사실 / 절반의 사실 / 대체로 사실 아님 / 전혀 사실 아님 / 판단 유보
출력 형식 — 첫 줄은 반드시 "판정: <여섯 개 중 하나>" 로 시작한다.
그다음 판정 근거를 쓰고, 각 근거 끝에 출처 URL을 괄호로 표기한다.
수집 자료에 없는 내용을 쓰지 않는다.
- "첫 줄은 판정: 으로 시작" 같은 출력 형식 지정이 있어야 화면에서 판정을 뽑아낼 수 있음. 이것이 없으면 판정이 문단 속에 묻힘.
- 결과물에 이 지시문이 없거나 6단계가 빠져 있으면 ④ 적신호로 넘어감.
대조하는 법 — 다섯 자리를 순서대로 확인
| 자리 | 무엇을 볼까 |
|---|---|
| ① 키 입력칸 | AIza·tvly-로 시작하는 문자열이 코드에 없는가 |
| ② 두 화면 | 분석과 챗봇이 둘 다 있는가 |
| ④ Tavily | search_depth가 "basic"인가. crawl이 없는가 |
| ⑤ Gemini | 모델명이 gemini-3.1-flash-lite인가. 헤더가 x-goog-api-key인가 |
| 지시문 | 6단계가 그대로 들어 있는가 |
- 코드를 다 읽을 필요 없음. VS Code에서
Ctrl+F로tavily·gemini·판정을 찾아 그 근처만 보면 됨.
④ 나오면 안 되는 것 — 적신호
| 적신호 | 왜 문제인가 | 조이는 말 |
|---|---|---|
| 키가 코드에 박혀 있음 | 공개 저장소에 올라가면 회수 불가 | "키를 코드에서 빼고 화면 입력으로 바꿔 줘" |
| 검색 0건인데 판정을 냄 | 근거 없는 판정 | "근거가 0건이면 판단 유보로 고정해 줘" |
| "가짜뉴스" 같은 6단계 밖의 말 | 척도를 벗어남 | "판정은 6단계 중 하나만 쓰게 해 줘" |
| 판정 근거에 출처 URL이 없음 | 대조가 불가능해짐 | "각 근거 끝에 출처 URL을 붙여 줘" |
advanced 검색이나 crawl 사용 |
크레딧 급소모 | "Search basic만 쓰게 고쳐 줘" |
| 실패 시 자동 재시도 반복 | 크레딧 폭주 | "재시도하지 말고 실패하면 멈추게 해 줘" |
- ④가 이 실습의 핵심임. 결과물을 받는 것이 아니라 적신호(이상한 점)를 찾아내는 것이 학습 목표임.
- 조이는 말은 짧을수록 잘 먹힘. 한 번에 하나씩, 무엇을 어떻게 바꿀지만 적을 것.
12-4. 진행 순서 — 한 번 던지고 두 번 나눠 읽음#
| 시간 | 하는 일 |
|---|---|
| 0~10분 | 작업 폴더 생성(12-1) → 프롬프트를 던지고 계획 화면을 끝까지 읽음. 승인 |
| 10~25분 | 분석 부분을 읽음. 키 입력 → 주장 하나 넣고 동작 확인 → ③ 다섯 자리 대조 → ④ 적신호 점검 |
| 25~30분 | GitHub에 올려 배포. URL로 열림을 확인 |
| 30~45분 | 챗봇 부분을 읽음. 일반 대화 / 주장 입력을 각각 시험 |
| 45~50분 | 어긋난 곳 하나를 골라 조이는 말로 고침. 다시 배포 |
- 먼저 배포하고 나중에 고침. 뒤에서 깨져도 동작하는 배포본이 남아 있음.
- 한 번에 수백 줄이 오면 읽지 않고 넘어가게 됨. 나눠 읽기가 이 구간의 목적임.
12-5. 체크포인트#
- [ ] 키 두 개를 넣고 주장을 입력하면 검색 결과와 판정이 함께 나옴
- [ ] 판정이 6단계 중 하나임
- [ ] 판정 근거에 출처 URL이 붙어 있음
- [ ] 그 URL을 실제로 열어 보니 근거와 맞음
- [ ] 근거 0건인 주장을 넣으면 판단 유보가 나옴
- [ ] 챗봇에서 일반 대화는 검색 없이 답함
- [ ] 배포 URL로 열림 · 코드에 키 문자열이 없음
12-6. 자주 막히는 곳#
| 증상 | 해결 |
|---|---|
| 화면은 뜨는데 아무 반응이 없음 | F12로 개발자 도구를 열고 Console 탭의 빨간 글씨를 확인. 그 글씨를 그대로 복사해 AI에게 붙여넣을 것 |
| Tavily 호출 실패 (CORS) | 브라우저가 외부 호출을 막은 것. 폴더에서 python -m http.server 8000을 돌리고 http://localhost:8000으로 열어 볼 것 |
401 · 403 |
키 오류. 앞뒤 공백이 딸려 들어갔는지 확인하거나 재발급 |
429 |
호출 한도 초과. 잠시 후 재시도 |
404 (Gemini) |
모델명을 gemini-3.5-flash-lite 또는 gemini-2.5-flash-lite로 대체 |
| 크레딧이 빨리 줄어듦 | basic인지, 재시도 코드가 없는지 확인 |
| GitHub Pages가 404 | index.html이 맨 위 폴더에 있는지 확인. 반영까지 1~3분 걸림 |
확장 과제 — 챗봇의 검색 발동 판단을 키워드 대신 Gemini에게 맡겨
{"need_search": true, "query": "..."}를 받아 분기. 이것이 라우팅(routing)의 기본 형태임.
13장. 실습 2 — 팩트체크 자동화 에이전트#
13-1. 작업 폴더부터 — 반드시 새 폴더에서#
- 실습 1 폴더 안에서 시작하면 안 됨. 새 폴더를 만들어 거기서 시작함.
# macOS · Linux
cd ~/Desktop
mkdir factcheck_agent
cd factcheck_agent
claude
# Windows (PowerShell)
cd C:\vibecoding
mkdir factcheck_agent
cd factcheck_agent
claude
- 터미널 경로 끝이
factcheck_agent인지 눈으로 확인한 뒤claude를 실행함. - VS Code 확장으로 한다면 File → Open Folder로 이 폴더를 여는 것이 곧 같은 뜻임.
왜 분리하는가
| 이유 | 설명 |
|---|---|
CLAUDE.md는 폴더 단위로 적용됨 |
웹 실습 폴더에 두면 웹앱 규칙과 에이전트 규칙이 섞임 |
.claude/도 폴더 단위임 |
서브에이전트가 엉뚱한 프로젝트에서 발동함 |
| 에이전트가 폴더 전체를 작업 대상으로 봄 | 같은 폴더에 있으면 index.html까지 고쳐 버림 |
| GitHub 저장소가 달라짐 | 실습 1만 배포함. 에이전트는 로컬에 둠 |
- 정리 — 웹은
factcheck_tavily/, 에이전트는factcheck_agent/. 서로 겹치지 않게 둠.
13-2. 던지는 것 — 프롬프트 한 장#
팩트체크 자동화 에이전트 워크플로 만들기
주장을 입력하면 팩트체크하는 에이전트 워크플로를 만들고자 해.
CLAUDE.md, subagents(searcher, judge, reviewer), 그리고 필요한 skills로 구성하자.
searcher에서는 Tavily와 Claude의 자체 web search 기능을 사용해 참조자료를 수집.
.env의 TAVILY_API_KEY를 설정해 사용. Tavily Python 코드가 필요하면 scripts에 생성해 사용.
judge에서는 위 참조자료를 바탕으로 아래 6단계 가운데 하나로 판단.
reviewer에서는 위 판단 결과가 참조자료와 비교해 정확한지 재검토.
입력 주장은 input/의 txt 파일에 여러 개 입력해 동시에 진행할 수 있도록 하고,
결과는 output/에 md 파일로 보고서 생성.
시간이 너무 오래 걸리지 않도록 해.
만들기 전에 무엇을 만들지 먼저 알려줘.
6단계 판단:
| 사실 | 제시된 주장이 객관적 증거에 비추어 볼 때 완전히 정확하고 참인 경우 |
| 대체로 사실 | 대체로는 맞으나 일부 세부적인 보충 설명이나 해명이 필요한 경우 |
| 절반의 사실 | 사실과 거짓이 섞여 있거나, 중요한 맥락이 빠져 있어 일부만 맞는 경우 |
| 대체로 사실 아님 | 핵심 주장에 오류가 있거나 사실보다 허위가 더 많은 경우 |
| 전혀 사실 아님 | 객관적 증거와 명백히 다르며 거짓으로 판명된 경우 |
| 판단 유보 | 증거가 부족하거나 진위 여부를 판가름하기 어려운 경우 |
Codex·Antigravity를 쓰는 사람은 이 프롬프트를 쓰지 말 것. 위 프롬프트는 Claude Code 전용 폴더 구조(
.claude/)를 만듦. Codex는 이 위치를 읽지 않아 서브에이전트·스킬이 나타나지 않음. → Codex는 13-8, Antigravity는 13-9로 바로 갈 것.
13-3. 돌아올 것 — 예측#
① 거의 확실한 것 — 경로가 규약으로 정해져 있음
factcheck_agent/
├── CLAUDE.md 매 세션 자동 로드
├── .claude/agents/searcher.md 검색 담당
├── .claude/agents/judge.md 판정 담당
├── .claude/agents/reviewer.md 검토 담당
├── .claude/skills/<이름>/SKILL.md 보고서 절차
├── scripts/search_tavily.py Tavily 호출
├── input/claims.txt 조사할 주장
├── output/ 보고서 저장
└── .env.example · .gitignore · requirements.txt
- 서브에이전트는
.claude/agents/*.md, 스킬은.claude/skills/<이름>/SKILL.md. 이 경로가 아니면 발동하지 않음. AI도 이 규약을 지킴. .으로 시작하는 폴더는 탐색기에서 기본으로 숨겨짐. VS Code에서는 그냥 보임 — 안 보이면 폴더를 제대로 열었는지 먼저 확인할 것.- 스킬 이름은
factcheck-report같은 형태로 올 가능성이 높으나 다를 수 있음.
② 어떤 형식으로 올까 — 파일별 골격
- 아래는 예측임. 문장과 항목 수는 다르게 옴. 형식(프론트매터)만 익히면 됨.
- 프론트매터란 파일 맨 위에
---세 줄표로 감싼 설정 구역임. 여기 적힌 것만 도구가 읽음.
CLAUDE.md — 프론트매터가 없음. 그냥 마크다운임
# 작업 흐름
1. searcher 로 근거를 모은다.
2. judge 로 6단계 중 하나를 고른다.
3. reviewer 로 검토한다. 지적이 있으면 judge 가 한 번만 고친다.
4. 보고서 스킬로 output/ 에 저장한다.
# 검색원
- Tavily (scripts/search_tavily.py) — 1회 = 1크레딧
- WebSearch (Claude Code 내장) — 크레딧 무관
- 주장 하나당 각 검색원을 1회씩만 호출한다.
# 하지 말 것
- .env 를 커밋하지 않는다.
- 자동 재시도 루프를 만들지 않는다. 실패하면 멈춘다.
- 근거가 없으면 판단 유보를 고른다.
서브에이전트 — ---로 감싼 프론트매터가 핵심임
---
name: searcher
description: 주장의 근거 자료를 웹에서 수집해야 할 때 사용한다.
모으기만 하고 해석하거나 판단하지 않는다.
tools: Bash, Read, Write, WebSearch
---
너는 자료 수집만 담당하는 조사원이다.
1. 주장에서 핵심 명사 2~3개를 뽑아 검색어를 만든다.
2. Tavily 와 WebSearch 를 각각 1회씩 실행한다.
3. 결과를 [Tavily] · [WebSearch] 출처를 붙여 그대로 넘긴다.
해석하지 않는다. 참·거짓을 언급하지 않는다.
---
name: judge
description: 수집이 끝난 자료로 주장을 6단계 중 하나로 판정할 때 사용한다.
직접 검색하지 않고 주어진 자료만 쓴다.
tools: Read, Write
---
… 6단계 척도 … 자료 밖의 지식으로 판정하지 않는다 …
근거가 부족하면 판단 유보를 고른다. 애매하면 한 단계 약하게 판정한다.
---
name: reviewer
description: 판정 결과를 저장 전에 검토할 때 사용한다.
근거보다 센 판정과 출처 없는 문장을 잡아낸다.
tools: Read
model: haiku
---
… 점검 항목을 순서대로 확인하고 통과 / 지적 으로 답한다 …
직접 고치지 않는다. 지적만 한다.
tools:줄이 권한을 정함.
| 에이전트 | tools: |
막히는 것 |
|---|---|---|
searcher |
Bash 포함 |
— (검색 스크립트를 실행해야 함) |
judge |
Bash 없음 |
검색을 실행할 수단 자체가 없음 |
reviewer |
Read 하나 |
쓰기도 실행도 못 함 |
- 지시문보다 권한 제한이 확실함. "검색하지 마"라고 적는 것과 도구를 안 주는 것은 다름.
model: haiku— 가벼운 점검이므로 저렴하고 빠른 모델을 지정한 것. 없어도 동작함.
스킬 — 폴더 안에 SKILL.md로 둠
---
name: factcheck-report
description: 팩트체크 판정 결과를 보고서 파일로 저장할 때 사용한다.
주장별 판정이 끝나고 output 폴더에 결과를 남기는 단계에서 이 절차를 따른다.
---
- 저장: output/factcheck_YYYY-MM-DD_HHMM.md (덮어쓰지 않음)
- 주장마다: 판정 / 판정 근거(+출처 URL) / 사용한 검색어 /
수집된 근거 / 자료의 한계 / 검토 기록
- 끝에 「부록. 판정 요약」 표를 붙인다.
- 근거 0건인 주장도 빼지 않고 기록한다.
description이 전부임. 평소 본문은 읽지 않고 이 한 줄만 보고 꺼낼지 판단함. "보고서 관련" 같은 두루뭉술한 설명이면 영영 안 불림. "언제 쓰는지"를 문장으로 쓸 것.
scripts/search_tavily.py — 볼 곳은 세 군데뿐
def search(query, max_results=5):
# ① 캐시 우선 — 같은 검색어면 크레딧 0
if cache_path(query).exists():
return json.loads(cache_path(query).read_text(encoding="utf-8"))
res = requests.post(
"https://api.tavily.com/search",
headers={"Authorization": f"Bearer {os.environ['TAVILY_API_KEY']}"},
json={"query": query,
"search_depth": "basic", # ② advanced 는 2크레딧이므로 쓰지 않는다
"max_results": max_results},
timeout=30)
if not res.ok:
raise SystemExit(f"검색 실패 HTTP {res.status_code}") # ③ 재시도하지 않고 멈춤
...
| 볼 곳 | 확인할 것 |
|---|---|
| ① 캐시 | 있으면 좋은 신호. 프롬프트에 없던 것을 AI가 붙인 것 |
② search_depth |
"basic"이어야 함. advanced나 crawl이면 고칠 것 |
| ③ 실패 처리 | raise로 멈춰야 함. while 재시도가 있으면 크레딧 폭주 |
③ 예측하기 어려운 것
| 항목 | 왜 |
|---|---|
| 각 파일의 줄 수와 문장 표현 | 매번 다름 |
tools: 줄을 넣을지 |
넣으면 좋은 신호 (권한 제한을 스스로 설계한 것) |
| 검색 결과 캐시를 붙일지 | 프롬프트에 없음. 붙으면 크레딧 절약 |
| reviewer의 점검 항목 개수 | 3개일 수도 6개일 수도 있음 |
| 보고서의 구체적 섹션 이름 | 스킬 본문이 정함 |
④ 나오면 안 되는 것 — 적신호
| 적신호 | 조이는 말 |
|---|---|
| judge에게 검색 권한이 있음 | "judge의 tools에서 검색 도구를 빼 줘" |
| reviewer가 직접 고침 | "reviewer는 tools를 Read 하나만 주고 지적만 하게 해 줘" |
description이 두루뭉술함 |
"description을 '언제 쓰는지' 문장으로 다시 써 줘" |
| 재시도 루프가 있음 | "실패하면 멈추게 해 줘. 재시도 루프를 만들지 마" |
.env가 .gitignore에 없음 |
".env를 .gitignore에 넣어 줘" |
search_depth가 advanced |
"basic으로 고쳐 줘" |
읽을 때 볼 곳 세 군데 ①
description— 자동 발동을 좌우함. ②tools:— 그 에이전트가 할 수 없는 일을 정함. ③# 하지 말 것— harness engineering의 실물. 여기 적힌 만큼만 막힘.
13-4. 스킬의 결과, 어디까지 예측되는가#
- 가장 많이 나오는 질문임. 세 층으로 갈림.
| 내용 | |
|---|---|
| 예측 가능 | 파일 경로 · 프론트매터(name·description) · 보고서가 output/에 .md로 저장됨 |
| 예측 불가 | 보고서의 섹션 이름과 순서 · 문장 표현 · 파일 분량 |
| 관찰로 확인 | 주장 3개를 넣었을 때 보고서 3건의 형식이 같은가 |
- 마지막 줄이 핵심임.
- 형식이 같으면 스킬이 발동한 것임.
- 형식이 제각각이면 스킬이 발동하지 않은 것임.
description을 고쳐야 함. - 스킬의 존재 이유가 바로 이 통일성임. 내용이 아니라 형식으로 검증함.
13-5. 설정 순서#
| 단계 | 작업 |
|---|---|
| ① | 13-1대로 factcheck_agent/ 새 폴더를 만들고 그 안에서 claude 실행 |
| ② | 13-2 프롬프트를 던지고 계획 화면을 읽은 뒤 승인 |
| ③ | 생성된 파일을 13-3의 네 목록과 대조. 적신호가 있으면 조이는 말로 고침 |
| ④ | cp .env.example .env (Windows는 copy .env.example .env) → 키 입력 |
| ⑤ | python -m venv .venv → 활성화 → pip install -r requirements.txt |
| ⑥ | input/claims.txt에 주장 3개를 한 줄에 하나씩 작성 |
| ⑦ | 검색 스크립트 단독 테스트: python scripts/search_tavily.py "백신 자석" |
| ⑧ | claude 실행 → "input/claims.txt의 주장들을 조사해 줘" |
⑤ 가상환경(venv) 활성화 명령 — 운영체제마다 다름
source .venv/bin/activate # macOS · Linux
.venv\Scripts\Activate.ps1 # Windows PowerShell
.venv\Scripts\activate.bat # Windows CMD
- 성공하면 터미널 줄 맨 앞에
(.venv)가 붙음. 이게 안 보이면 활성화가 안 된 것임. - PowerShell에서 실행이 거부되면 이 단계는 AI에게 그대로 물어보는 것이 가장 빠름(권한 정책 문제).
- 가상환경이란 — 이 프로젝트에만 쓰는 별도의 파이썬 살림집임. 다른 프로젝트와 라이브러리가 안 섞이게 해 줌.
- ⑥에서 3개인 이유 — 13-4의 형식 통일성을 확인하려면 최소 3건이 필요함.
13-6. 관찰 포인트#
- [ ] 메인 에이전트가 스스로 서브에이전트를 호출하는가
- [ ]
description만 보고 적절한 에이전트를 고르는가 - [ ] judge가 검색 없이 판정하는가
- [ ] reviewer가 근거보다 센 판정을 실제로 지적하는가
- [ ] 보고서 3건의 형식이 같은가 (스킬 발동 확인)
- [ ] 근거가 부족한 주장에 판단 유보가 나오는가
- 화면을 그냥 흘려보내지 말 것. 어떤 서브에이전트가 언제 불렸는지가 터미널에 그대로 찍힘. 그 대목이 3단계의 실물임.
13-7. 자동 발동이 안 걸릴 때#
description을 구체적으로 고칠 것.- "검색 관련 작업" → "주장의 근거 문서를 웹에서 수집해야 할 때 사용한다"
CLAUDE.md에 못박을 것.- "근거 수집이 필요하면 searcher 서브에이전트에게 맡긴다"
- 직접 부를 것. — "searcher 서브에이전트로 검색해 줘"
- 경로를 확인할 것. — 스킬은 폴더 안에
SKILL.md로 두어야 함. 파일 하나만 덩그러니 두면 인식되지 않음. - 세션을 새로 열 것. — 파일을 만든 뒤
/exit하고 다시claude를 실행하면 새 설정이 확실히 읽힘.
정리 — 폴더가 "무엇이 있는지",
description이 "언제 쓰는지",CLAUDE.md가 "그래도 놓치지 마라"를 담당함.
13-8. Codex로 할 때 — 반드시 이 순서#
Codex를 고른 사람은 13-2~13-7 대신 이 절만 따라 하면 됨. 아래 절차는 Codex CLI 0.160(2026년 10월 최신)으로 빈 폴더에서 처음부터 끝까지 실제로 돌려 서브에이전트 3개 호출 → 보고서 저장까지 확인한 순서임.
왜 Claude Code처럼 하면 Codex에서 안 나타나는가 — 직접 재현해 확인한 원인 다섯
| 원인 | 겉으로 보이는 증상 | |
|---|---|---|
| ① | 스킬 위치가 다름 — Codex는 .agents/skills/만 읽음 (.claude/skills·.codex/skills는 무시) | 스킬이 목록에 없음 |
| ② | "신뢰한 폴더"에서만 .codex/ 안의 설정과 서브에이전트를 읽음 | 파일은 있는데 서브에이전트가 default·explorer·worker만 보임 |
| ③ | Codex의 안전장치(샌드박스)가 .codex/ 폴더를 쓰기 금지 구역으로 막음 | Codex에게 만들라고 시키면 PC마다 되기도 하고 "액세스 거부"로 실패하기도 함 |
| ④ | 샌드박스가 기본으로 인터넷을 막음 | Tavily 스크립트가 늘 "연결 실패·시간 초과" |
| ⑤ | Codex는 서브에이전트를 알아서 부르지 않음 | 혼자 다 해 버리고 searcher·judge·reviewer가 안 불림 |
- 그래서 Codex 경로는 방식을 바꿈 — 뼈대(규칙·서브에이전트·스킬·설정)는 설치 스크립트로 한 번에 깔고, Codex에게는 일만 맡김.
- 스크립트가 ①~④를 한꺼번에 해결함. ⑤는 실행할 때 서브에이전트 이름을 불러 해결함.
- 스크립트는 파이썬만 있으면 Windows·macOS 어디서나 똑같이 돎. Codex 샌드박스를 거치지 않으므로 PC마다 결과가 갈리지 않음.
따라 하기 — ①부터 ⑨까지 순서대로
| 단계 | 할 일 | 성공하면 보이는 것 |
|---|---|---|
| ① | 작업 폴더를 만듦 (아래 명령). 아직 codex를 실행하지 않음 | 터미널 경로 끝이 factcheck_agent |
| ② | VS Code → File → Open Folder → 그 폴더 선택 → 왼쪽 탐색기의 새 파일 아이콘 → 이름을 setup_codex.py로 → 아래 코드 전체를 복사해 붙여넣고 Ctrl+S 저장(또는 코드 위의 내려받기 버튼으로 받아 이 폴더로 옮김) | 탐색기에 setup_codex.py 하나 |
| ③ | VS Code 터미널(Ctrl+백틱)에서python setup_codex.py (macOS는 python3 setup_codex.py) | 만듦: ... 12줄 + 신뢰 폴더 등록 + 완료 |
| ④ | 탐색기에서 .env를 열어 tvly-YOUR_KEY를 내 Tavily 키로 바꾸고 저장 | — |
| ⑤ | 검색만 따로 시험:python scripts/search_tavily.py --query "백신 자석" | "results": [가 들어 있는 검색 결과. "error"가 나오면 아래 문제 해결 표 |
| ⑥ | 같은 터미널에서 codex 실행(이미 켜 둔 Codex가 있으면 /quit로 끄고 다시 실행 — 설정은 켤 때만 읽음) | 입력창. Trust this folder?가 뜨면 Yes |
| ⑦ | 인식 확인 — 이렇게 물음:사용할 수 있는 서브에이전트(agent_type)와 이 폴더 스킬 이름을 알려줘 | searcher·judge·reviewer와 factcheck-report가 모두 나옴 |
| ⑧ | input/claims.txt에 주장 3개(한 줄에 하나)를 적고 저장한 뒤, Codex에:input/claims.txt의 주장들을 searcher, judge, reviewer 서브에이전트로 팩트체크하고 factcheck-report 스킬로 보고서를 저장해 줘 | 서브에이전트가 차례로 불리는 표시 → 주장별 판정 요약 |
| ⑨ | output/factcheck_날짜_시각.md를 열어 확인 | 주장마다 판정·근거 URL·검토 기록 + 끝에 「부록. 판정 요약」 |
# ① Windows (PowerShell)
cd C:\
mkdir vibecoding -ErrorAction SilentlyContinue
cd vibecoding
mkdir factcheck_agent
cd factcheck_agent
# ① macOS
cd ~/Desktop
mkdir factcheck_agent
cd factcheck_agent
- ⑧에서 서브에이전트 이름을 꼭 넣을 것. 이름 없이 "팩트체크해 줘"만 치면 Codex가 혼자 처리해 버릴 수 있음(원인 ⑤).
- 중간에 "이 명령을 실행해도 될까요?"가 뜨면 무엇을 실행하는지 읽고 승인.
python scripts/search_tavily.py ...면 승인해도 됨. - VS Code 확장으로 할 때 — ③까지 마친 뒤
Ctrl+Shift+P→Developer: Reload Window→ Codex 패널을 열고 ⑦부터 같은 문장을 입력. input/claims.txt에는 연습용 주장 3개가 미리 들어 있음. 그대로 써도 되고 바꿔도 됨.
설치 스크립트 setup_codex.py — 그대로 복사
# setup_codex.py — Codex용 팩트체크 에이전트 뼈대를 한 번에 만든다.
# 사용법: 빈 작업 폴더(factcheck_agent)에 이 파일을 저장하고
# Windows: python setup_codex.py / macOS: python3 setup_codex.py
import os, sys
from pathlib import Path
ROOT = Path.cwd()
PY = "python" if os.name == "nt" else "python3" # 에이전트가 쓸 파이썬 명령
FILES = {}
FILES["AGENTS.md"] = f"""# 팩트체크 에이전트 작업 규칙
## 작업 흐름 (반드시 이 순서)
팩트체크 요청이 오면 주장마다 아래 순서로 서브에이전트를 spawn해서 진행한다.
1. searcher 서브에이전트: 근거 자료 수집 (Tavily + 내장 웹 검색)
2. judge 서브에이전트: searcher 자료만으로 6단계 중 하나로 판정
3. reviewer 서브에이전트: 판정이 자료와 맞는지 1회 재검토
4. 메인 에이전트가 factcheck-report 스킬(.agents/skills/factcheck-report/SKILL.md)을 읽고 output/에 보고서 저장
서브에이전트를 쓸 수 없으면 쓴 척하지 말고 사용자에게 알린다.
## 입력
- input/claims.txt 에 한 줄에 주장 하나. 빈 줄은 건너뛴다.
- 주장이 여러 개면 최대 3개까지 동시에 진행한다.
## 검색원
- Tavily: `{PY} scripts/search_tavily.py --query "검색어"` (1회 = 1크레딧, 주장당 1회)
- 내장 웹 검색: 주장당 최대 2회
- 검색어는 문장 통째가 아니라 핵심 명사 2~3개로 만든다.
## 6단계 판정
| 판정 | 기준 |
| --- | --- |
| 사실 | 제시된 주장이 객관적 증거에 비추어 볼 때 완전히 정확하고 참인 경우 |
| 대체로 사실 | 대체로는 맞으나 일부 세부적인 보충 설명이나 해명이 필요한 경우 |
| 절반의 사실 | 사실과 거짓이 섞여 있거나, 중요한 맥락이 빠져 있어 일부만 맞는 경우 |
| 대체로 사실 아님 | 핵심 주장에 오류가 있거나 사실보다 허위가 더 많은 경우 |
| 전혀 사실 아님 | 객관적 증거와 명백히 다르며 거짓으로 판명된 경우 |
| 판단 유보 | 증거가 부족하거나 진위 여부를 판가름하기 어려운 경우 |
## 하지 말 것
- .env 내용이나 API 키를 화면·보고서에 출력하지 않는다.
- 실패하면 재시도 루프를 돌지 않는다. 실패 사실을 기록하고 다음으로 넘어간다.
- 근거가 없으면 판단 유보를 고른다. 검색 실패는 거짓의 증거가 아니다.
"""
FILES[".codex/config.toml"] = """# 이 폴더에서만 쓰는 Codex 설정 (폴더를 '신뢰'해야 읽힘)
sandbox_mode = "workspace-write" # 이 폴더 안에서만 파일 생성·수정
web_search = "live" # 내장 웹 검색을 실시간으로
[sandbox_workspace_write]
network_access = true # Tavily 스크립트가 인터넷에 접속하도록 허용
[windows]
sandbox = "unelevated" # Windows: 관리자 권한 없이 동작하는 샌드박스
"""
FILES[".codex/agents/searcher.toml"] = f'''name = "searcher"
description = "팩트체크할 주장의 근거 자료를 웹에서 수집해야 할 때 사용한다. 모으기만 하고 판정하지 않는다."
developer_instructions = """
너는 자료 수집만 담당하는 조사원이다. 판정하지 않고 참·거짓을 말하지 않는다.
1. 주장에서 핵심 명사 2~3개를 뽑아 검색어를 만든다.
2. 터미널에서 {PY} scripts/search_tavily.py --query "검색어" 를 1회 실행한다.
3. 내장 웹 검색을 최대 2회 실행해 지지·반박 자료를 찾는다.
4. 자료마다 [Tavily] 또는 [WebSearch] 표시, 제목, 실제 URL, 핵심 문장 인용을 정리해 돌려준다.
5. 실패한 검색원은 실패 이유를 적는다. 없는 URL이나 내용을 지어내지 않는다.
"""
'''
FILES[".codex/agents/judge.toml"] = '''name = "judge"
description = "수집이 끝난 자료로 주장을 6단계 중 하나로 판정할 때 사용한다. 직접 검색하지 않는다."
sandbox_mode = "read-only"
developer_instructions = """
너는 판정자다. 전달받은 searcher 자료만 근거로 쓴다. 새로 검색하지 않고 파일을 고치지 않는다.
판정은 사실 / 대체로 사실 / 절반의 사실 / 대체로 사실 아님 / 전혀 사실 아님 / 판단 유보 중 정확히 하나.
첫 줄은 반드시 "판정: <여섯 개 중 하나>" 로 시작한다.
그다음 판정 근거를 쓰고, 각 근거 끝에 출처 URL을 괄호로 붙인다.
근거가 부족하면 판단 유보를 고르고, 애매하면 한 단계 약하게 판정한다.
"""
'''
FILES[".codex/agents/reviewer.toml"] = '''name = "reviewer"
description = "judge의 판정을 저장하기 전에 참조자료와 대조해 검토할 때 사용한다."
sandbox_mode = "read-only"
developer_instructions = """
너는 검토자다. 직접 고치지 않고 지적만 한다. 검토는 1회로 끝낸다.
점검: (1) 판정이 6단계 중 하나인가 (2) 근거마다 출처 URL이 있고 자료에 실제로 있는 URL인가
(3) 근거보다 센 판정이 아닌가 (4) 자료 밖의 내용을 쓰지 않았나.
답 형식: 첫 줄 "검토: 통과" 또는 "검토: 지적", 이어서 지적 사항과 권하는 최종 판정.
"""
'''
FILES[".agents/skills/factcheck-report/SKILL.md"] = """---
name: factcheck-report
description: 팩트체크 판정과 검토가 끝난 뒤 결과를 output 폴더에 보고서 파일로 저장할 때 사용한다.
---
# 팩트체크 보고서 저장 절차
1. 파일 이름: output/factcheck_YYYY-MM-DD_HHMM.md (기존 파일을 덮어쓰지 않는다)
2. 주장마다 아래 순서로 쓴다.
- ## 주장 N: <원문>
- **판정:** reviewer 검토를 반영한 최종 판정 (6단계 중 하나)
- **판정 근거:** 문장마다 끝에 출처 URL
- **사용한 검색어:** Tavily / 웹 검색
- **수집된 근거:** 표 (출처 | 제목 | URL)
- **자료의 한계**
- **검토 기록:** judge 판정 → reviewer 의견 → 최종 판정
3. 맨 끝에 「부록. 판정 요약」 표 (번호 | 주장 | 최종 판정)
4. 근거 0건이거나 실패한 주장도 빼지 않고 판단 유보로 기록한다.
"""
FILES["scripts/search_tavily.py"] = '''# Tavily 검색 스크립트 — 파이썬 기본 기능만 사용 (추가 설치 불필요)
# 사용: python scripts/search_tavily.py --query "백신 자석"
import argparse, json, os, sys, urllib.error, urllib.request
from pathlib import Path
sys.stdout.reconfigure(encoding="utf-8") # Windows 한글 깨짐 방지
def load_key():
# 환경변수 → .env 파일 순서로 키를 찾는다
key = os.environ.get("TAVILY_API_KEY", "")
env = Path(__file__).resolve().parent.parent / ".env"
if not key and env.exists():
for line in env.read_text(encoding="utf-8-sig").splitlines():
if line.strip().startswith("TAVILY_API_KEY="):
key = line.split("=", 1)[1].strip().strip('"').strip("'")
return key
def main():
p = argparse.ArgumentParser()
p.add_argument("--query", required=True)
p.add_argument("--max-results", type=int, default=5)
q = p.parse_args()
key = load_key()
if not key.startswith("tvly-") or "YOUR" in key:
print(json.dumps({"error": ".env 파일에 실제 TAVILY_API_KEY를 넣어 주세요"}, ensure_ascii=False))
sys.exit(1)
body = json.dumps({"query": q.query, "search_depth": "basic", # basic = 1크레딧
"max_results": q.max_results}).encode("utf-8")
req = urllib.request.Request(
"https://api.tavily.com/search", data=body, method="POST",
headers={"Content-Type": "application/json", "Authorization": "Bearer " + key})
try:
with urllib.request.urlopen(req, timeout=30) as res:
data = json.loads(res.read().decode("utf-8"))
except urllib.error.HTTPError as e: # 401 키 오류, 429 한도 초과 등 — 재시도하지 않고 멈춘다
print(json.dumps({"error": "Tavily HTTP 오류", "status": e.code}, ensure_ascii=False))
sys.exit(1)
except Exception as e: # 인터넷 차단·시간 초과
print(json.dumps({"error": "Tavily 연결 실패", "detail": str(e)}, ensure_ascii=False))
sys.exit(1)
results = [{"title": r.get("title"), "url": r.get("url"), "content": r.get("content")}
for r in data.get("results", [])]
print(json.dumps({"query": q.query, "results": results}, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()
'''
FILES[".env.example"] = "TAVILY_API_KEY=tvly-YOUR_KEY\n"
FILES[".gitignore"] = ".env\n__pycache__/\n"
FILES["input/claims.txt"] = "대한민국의 수도는 서울이다.\n물은 압력과 관계없이 항상 섭씨 100도에서 끓는다.\n코로나19 백신을 맞으면 몸에 자석이 붙는다.\n"
FILES["output/.gitkeep"] = ""
def write_files():
for rel, text in FILES.items():
path = ROOT / rel
if path.exists() and rel in ("input/claims.txt", ".env.example"):
continue # 이미 쓰던 입력은 덮어쓰지 않는다
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(text, encoding="utf-8", newline="\n")
print(" 만듦:", rel)
env = ROOT / ".env"
if not env.exists():
env.write_text(FILES[".env.example"], encoding="utf-8")
print(" 만듦: .env ← 여기에 Tavily 키를 넣을 것")
def trust_folder():
# Codex는 '신뢰한 폴더'에서만 .codex/ 설정과 서브에이전트를 읽는다.
# Codex 첫 화면의 'Trust this folder? → Yes'와 같은 일을 미리 해 둔다.
home = Path(os.environ.get("CODEX_HOME", Path.home() / ".codex"))
cfg = home / "config.toml"
key = str(ROOT)
old = cfg.read_text(encoding="utf-8") if cfg.exists() else ""
if key in old or key.lower() in old.lower():
print(" 신뢰 폴더: 이미 등록됨")
return
home.mkdir(parents=True, exist_ok=True)
entry = f"\n[projects.'{key}']\ntrust_level = \"trusted\"\n"
cfg.write_text(old.rstrip("\n") + "\n" + entry if old else entry.lstrip(), encoding="utf-8")
print(" 신뢰 폴더 등록:", key)
if __name__ == "__main__":
if "'" in str(ROOT):
sys.exit("폴더 경로에 작은따옴표(')가 있으면 안 됨. C:\\vibecoding\\factcheck_agent 같은 경로에서 실행할 것.")
print("작업 폴더:", ROOT)
write_files()
trust_folder()
print("\n완료. 다음 순서:")
print(" 1) .env 파일을 열어 tvly-YOUR_KEY 를 내 Tavily 키로 바꾸고 저장")
print(f" 2) {PY} scripts/search_tavily.py --query \"백신 자석\" 로 검색 확인")
print(" 3) codex 실행 → '사용할 수 있는 서브에이전트와 스킬 이름을 알려줘'")
이 스크립트가 만드는 것 — 13-3의 Claude 버전과 1:1로 대응함
factcheck_agent/
├── AGENTS.md ← CLAUDE.md 자리 (작업 흐름 · 6단계 · 하지 말 것)
├── .codex/config.toml ← 이 폴더 전용 설정 (인터넷 허용 · 웹 검색 · Windows 샌드박스)
├── .codex/agents/searcher.toml ← 검색 담당
├── .codex/agents/judge.toml ← 판정 담당 (sandbox_mode = "read-only")
├── .codex/agents/reviewer.toml ← 검토 담당 (sandbox_mode = "read-only")
├── .agents/skills/factcheck-report/SKILL.md ← 보고서 절차 (Codex의 스킬 위치)
├── scripts/search_tavily.py ← Tavily 호출 (추가 설치 불필요)
├── input/claims.txt · output/
└── .env · .env.example · .gitignore
- 폴더 신뢰 등록 — 스크립트 마지막 단계가
~/.codex/config.toml(Windows는C:\Users\내이름\.codex\config.toml)에[projects.'이 폴더 경로']·trust_level = "trusted"두 줄을 더함. Codex 첫 화면에서Trust this folder? → Yes를 고르는 것과 같은 일임. - Claude의
tools:줄에 해당하는 것이 Codex에서는sandbox_mode임. judge·reviewer를read-only로 묶어 파일을 못 고치게 구조로 막음 — 4장의 "부탁이 아니라 차단"이 Codex에서는 이렇게 표현됨. - 내용을 바꾸고 싶으면 VS Code에서 해당 파일을 직접 열어 고치고 저장 → Codex를
/quit후 다시 실행. (Codex에게.codex/안을 고치라고 시키면 원인 ③ 때문에 승인 창이 뜨거나 거부될 수 있음) - 폴더를 옮기거나 이름을 바꾸면 신뢰가 풀림 — 새 위치에서
python setup_codex.py를 한 번 더 실행할 것(input/claims.txt·.env는 덮어쓰지 않음).
Codex 문제 해결
| 증상 | 원인 | 해결 |
|---|---|---|
⑦에서 서브에이전트가 default·explorer·worker뿐 | 폴더가 신뢰되지 않음 · 다른 폴더에서 실행 | 터미널 경로 끝이 factcheck_agent인지 확인 → 그 자리에서 python setup_codex.py 재실행 → Codex 재시작 |
⑦에서 factcheck-report가 없음 | 스킬 파일 위치 오류 | .agents/skills/factcheck-report/SKILL.md가 있는지 탐색기로 확인. 없으면 스크립트 재실행 |
⑤에서 .env 파일에 실제 TAVILY_API_KEY를 넣어 주세요 | 키를 안 넣었거나 저장 안 함 | .env의 tvly-YOUR_KEY를 실제 키로 바꾸고 Ctrl+S |
"status": 401 | 키 오류 | 키 앞뒤 공백 확인, Tavily 대시보드에서 키를 다시 복사 |
⑤는 되는데 Codex 안에서만 Tavily 연결 실패 | 인터넷 허용 설정이 안 읽힘(원인 ②·④) | 폴더 신뢰 확인(이 표 첫 줄) 후 Codex 재시작 |
명령이 전부 setup refresh had errors로 실패 | Windows 샌드박스 | 8-5 표의 해당 줄 |
python을 못 찾음 | PATH | 8-5 표. macOS는 python3 |
Claude Code와 비교해 관찰할 것 — 같은 일을 시켰는데 설정 파일의 이름·위치·형식(
.md대.toml)이 모두 다름. 그러나 규칙 파일 + 역할별 서브에이전트 + 권한 제한 + 보고서 스킬이라는 설계는 그대로임. 도구가 바뀌어도 3·4단계의 설계 방식은 그대로 옮겨 감 — 이것이 이 절의 학습 목표임.
13-9. Antigravity(Google)로 할 때#
- Google 쪽은
agy(Antigravity CLI)를 씀. 옛gemini명령은 개인 계정으로 로그인되지 않음(7장). - 파일 위치 — 규칙
AGENTS.md· 서브에이전트.agents/agents/<이름>.md· 스킬.agents/skills/<이름>/SKILL.md. - 서브에이전트 프론트매터에
subagent: true가 있어야 메인이 부를 수 있음.tools:를 빼면 도구가 하나도 없는 상태가 되고, 철자가 틀린 도구 이름은 멈춤을 일으킴. 그래서 도구 이름은 사람이 적지 않고agy에게 "네가 실제로 가진 도구 이름으로 적어 줘"라고 시킴.
| 단계 | 할 일 |
|---|---|
| ① | 13-8의 ①처럼 factcheck_agent 새 폴더를 만들고 그 안에서 agy 실행 |
| ② | 아래 프롬프트를 붙여넣음 → 계획을 읽고 승인 |
| ③ | 파일이 다 만들어지면 /exit → agy를 다시 실행(새 설정 읽기) |
| ④ | /agents를 입력해 searcher·judge·reviewer가 보이는지 확인 |
| ⑤ | 13-8의 ④⑤처럼 .env에 키를 넣고 검색 스크립트를 단독 시험 |
| ⑥ | input/claims.txt의 주장들을 searcher, judge, reviewer 서브에이전트로 팩트체크하고 factcheck-report 스킬로 보고서를 저장해 줘 |
팩트체크 자동화 에이전트 워크플로 만들기 (Antigravity CLI용)
주장을 입력하면 팩트체크하는 에이전트 워크플로를 만들고자 해.
아래 경로 규칙을 반드시 지켜서 만들어줘. 경로가 틀리면 Antigravity가 인식하지 못함.
- 규칙 파일: AGENTS.md (폴더 맨 위)
- 서브에이전트 3개: .agents/agents/searcher.md, .agents/agents/judge.md, .agents/agents/reviewer.md
각 파일 맨 위 --- 프론트매터에 name, description, tools, subagent: true 를 반드시 넣음.
tools에는 네가 지금 실제로 쓸 수 있는 도구 이름만 정확한 철자로 적음. 없는 이름을 적으면 멈춤.
searcher는 웹 검색·명령 실행·파일 읽기 도구, judge와 reviewer는 파일 읽기 도구만 줌.
- 스킬: .agents/skills/factcheck-report/SKILL.md (맨 위에 name, description 프론트매터)
searcher에서는 Tavily와 너의 자체 웹 검색 기능을 사용해 참조자료를 수집.
.env의 TAVILY_API_KEY를 설정해 사용. Tavily 호출 코드는 scripts/search_tavily.py 로 만들고,
파이썬 기본 라이브러리(urllib)만 써서 추가 설치 없이 돌게 해줘. search_depth는 basic, 실패하면 재시도하지 말고 멈춤.
judge에서는 위 참조자료를 바탕으로 아래 6단계 가운데 하나로 판단.
reviewer에서는 위 판단 결과가 참조자료와 비교해 정확한지 재검토.
AGENTS.md에는 "팩트체크 요청이 오면 반드시 searcher → judge → reviewer 서브에이전트를 차례로 호출해서 진행하고,
마지막에 factcheck-report 스킬로 보고서를 저장한다"는 작업 흐름을 적어줘.
입력 주장은 input/claims.txt 에 한 줄에 하나씩 여러 개 넣어 동시에 진행할 수 있도록 하고,
결과는 output/에 md 파일로 보고서 생성.
.env.example 과 .gitignore(.env 포함)도 만들어줘.
시간이 너무 오래 걸리지 않도록 해.
만들기 전에 무엇을 만들지 먼저 알려줘.
6단계 판단:
| 사실 | 제시된 주장이 객관적 증거에 비추어 볼 때 완전히 정확하고 참인 경우 |
| 대체로 사실 | 대체로는 맞으나 일부 세부적인 보충 설명이나 해명이 필요한 경우 |
| 절반의 사실 | 사실과 거짓이 섞여 있거나, 중요한 맥락이 빠져 있어 일부만 맞는 경우 |
| 대체로 사실 아님 | 핵심 주장에 오류가 있거나 사실보다 허위가 더 많은 경우 |
| 전혀 사실 아님 | 객관적 증거와 명백히 다르며 거짓으로 판명된 경우 |
| 판단 유보 | 증거가 부족하거나 진위 여부를 판가름하기 어려운 경우 |
- ④에서 서브에이전트가 안 보이면 → "
.agents/agents/의 세 파일에subagent: true와tools가 있는지 확인하고 고쳐 줘" →/exit후 재실행. - 무료 계정은 주간 한도가 있어 ⑥이 중간에 멈출 수 있음. 그때는 Google AI Pro 계정으로 로그인하거나 한도가 풀릴 때까지 기다림.
유료 Gemini API 키로 옛 Gemini CLI(
gemini)를 쓰는 경우 — 규칙GEMINI.md(또는AGENTS.md) · 서브에이전트.gemini/agents/<이름>.md· 스킬.agents/skills/. 처음 실행 때 뜨는Do you trust the files in this folder?에서 신뢰를, 이어 뜨는New Agents Discovered에서Acknowledge and Enable을 눌러야 서브에이전트가 등록됨. 이 창을 건너뛰면 파일이 있어도 서브에이전트가 없는 것처럼 동작함.
용어 미니 사전#
| 낱말 | 뜻 |
|---|---|
| 터미널 (Terminal · CLI) | 명령을 글자로 입력하는 검은 창. 마우스 대신 키보드로 컴퓨터에 일을 시킴 |
| PATH | 컴퓨터가 프로그램을 찾아보는 폴더 목록. 여기 등록이 안 되면 "명령을 찾을 수 없음"이 뜸 |
| LLM | Large Language Model. ChatGPT·Claude·Gemini의 속 알맹이인 언어 모델 |
| 문맥창 (context window) | AI가 한 번에 읽어 둘 수 있는 분량. 책상 위에 펼친 자료의 크기 |
| API | 다른 서비스의 기능을 프로그램이 불러 쓰는 창구 |
| API 키 | 그 창구에서 "나"임을 증명하는 긴 문자열. 비밀번호처럼 다룰 것 |
| 프롬프트 | AI에게 주는 지시문 |
| 서브에이전트 | 메인이 불러내는 별도의 일꾼. 자기 문맥창에서 한 가지 일만 함 |
| 프론트매터 | 파일 맨 위에 ---로 감싼 설정 구역. 도구는 여기 적힌 것만 읽음 |
| 마크다운 (.md) | #·- 같은 기호로 서식을 표시하는 글자 문서 형식 |
| 저장소 (repository) | GitHub에서 프로젝트 하나가 들어가는 방 |
| 커밋 (commit) | 바뀐 내용을 기록으로 남기는 저장 |
.gitignore |
GitHub에 올리지 않을 파일 목록. .env는 반드시 여기 넣음 |
.env |
API 키 같은 비밀값을 따로 담아 두는 파일 |
| CORS | 브라우저가 다른 사이트로의 호출을 막는 보안 규칙 |
| 콘솔 (Console) | F12로 여는 개발자 도구의 탭. 웹페이지 오류가 여기 찍힘 |
| 크레딧 | 유료 API에서 호출할 때마다 깎이는 사용량 |
참고 링크#
| 항목 | URL |
|---|---|
| 바이브 코딩 가이드 | https://jonghhhh.github.io/vibecoding_guide/ |
| Claude Code 공식 문서 | https://code.claude.com/docs/ |
| Claude Code 설치 안내 | https://code.claude.com/docs/en/setup |
| Claude Code VS Code 확장 | https://code.claude.com/docs/en/vs-code |
| VS Code 내려받기 | https://code.visualstudio.com |
| Node.js 내려받기 (LTS) | https://nodejs.org |
| 파이썬 내려받기 | https://www.python.org/downloads/ |
| Git for Windows | https://git-scm.com/downloads/win |
| Gemini API 문서 | https://ai.google.dev/gemini-api/docs?hl=ko |
| Gemini 키 발급 | https://aistudio.google.com/api-keys |
| Tavily 가입 | https://app.tavily.com |
| Tavily API 문서 | https://docs.tavily.com/documentation/api-reference/introduction |
| GitHub 가입 | https://github.com/signup |
| GitHub 새 저장소 | https://github.com/new |
| SNU 팩트체크 | https://factcheck.snu.ac.kr |
실습 전 최종 점검#
- 설치와 로그인이 끝났는가 —
claude --version이 찍히거나, VS Code 확장 패널에서 답이 오는가 (8-4)
Codex는codex login status, Antigravity는agy에서 답이 오는지. Codex는 13-8의 ⑦ 인식 확인까지 미리 해 둘 것 - 유료 구독이 활성 상태인가 — 무료 claude.ai 계정으로는 실습 2가 진행되지 않음
- 키 두 개가 살아 있는가 — 10장의
curl두 줄로 미리 확인해 둘 것 gemini-3.1-flash-lite가 호출되는가 —404면gemini-3.5-flash-lite또는gemini-2.5-flash-lite- 작업 폴더 두 개를 미리 만들어 두었는가 —
factcheck_tavily/와factcheck_agent/는 서로 다른 폴더여야 함 (13-1) - 시험할 주장 5~6개를 준비했는가 — 검색 결과가 잘 나오는 것으로 골라 둘 것. 너무 최근 사건이나 너무 사소한 주장은 근거가 안 잡힘
- Tavily 크레딧이 남아 있는가 — 대시보드에서 잔량 확인. 1인 실습 전체 약 40크레딧
버전 주의 — 모델명·요금·무료 한도·API 인증 방식·설치 명령은 변동이 잦음. 실습 직전에 각 공식 문서에서 확인할 것. 이 특강의 내용은 2026년 9월 기준임.