← Start here · Module 3B · Project

Module 3B · Project — job-post extractor

자유 텍스트 구인 공고를 붙여넣으면 검증된 구조화 필드(JSON)로 뽑아내는 작은 Flask 웹앱. Module 3의 forced tool use를 실제로 굴려봅니다.

🧩 개념은 Module 3 · Tools & Structure에서 — 이 페이지는 그 3.7 Project직접 실행하는 곳이에요. 앱 코드: Projects/Module_03_extractor/webapp/.

3B.1 · What it builds

강사 구인 공고 텍스트 → title · pay · location · requirements 같은 깔끔한 필드.

입력은 사람이 쓴 지저분한 공고 한 덩어리예요. 출력은 프로그램이 바로 DB에 넣을 수 있는 구조화된 JSON. 보너스로, 같은 앱이 구조화 추출과 대비되는 자유 텍스트 이메일 초안도 만들어 줍니다(도구를 강제하지 않는 경우).

한 화면에서 보는 두 모드
  • Extract — 도구를 강제해 스키마에 맞는 필드를 뽑음(기계가 검증 가능)
  • Draft email — 도구 없이 자연스러운 문장 생성(사람이 읽는 산문)

3B.2 · How it works

브라우저 한 페이지 → Flask 한 프로세스(:5001) → Claude 호출. 끝.

flowchart LR B["Browser
paste text, click Extract"] --> F["Flask :5001
/api/extract"] F -->|"forced tool_use"| C["Claude"] C -->|"structured fields"| F F -->|"validated JSON"| B

chat-app(2B)과 달리 프론트가 따로 없어요 — Flask가 templates/index.html을 직접 렌더링하는 단일 프로세스라, 실행이 가장 단순합니다(그래서 아래 "Run it live"의 첫 대상).

3B.3 · Run it live

버튼을 누르면 서버가 이 앱을 잠깐 띄우고 URL을 돌려줍니다(놀면 자동 종료).

⚙️ 어떻게 작동하나: "Run it live"는 GitHub Pages가 아니라 당신의 서버의 런처(launcher)에게 요청합니다. 런처가 컨테이너 하나를 띄워 URL을 주고, 일정 시간 idle이면 정리해요. 런처를 아직 안 깔았다면 버튼은 아래 로컬 실행 안내로 보내줍니다.

3B.4 · Run it locally

가장 확실한 방법 — 키는 내 .env에, 비용·노출 걱정 0.

cd instructor-extractor
../.venv/bin/pip install -r requirements.txt   # 저장소 루트의 venv 사용
../.venv/bin/python app.py                      # → http://localhost:5001

브라우저에서 http://localhost:5001 → 공고 텍스트를 붙여넣고 [Extract]. ANTHROPIC_API_KEY는 Module 1에서 만든 공유 .env를 그대로 씁니다.

3B.5 · The key idea — forced tool_use

"산문 말고 이 스키마를 채워"라고 도구로 강제 → 그 다음 코드로 검증.

📋 비유: 빈칸이 정해진 양식을 내미는 것. 모델이 마음대로 글을 쓰는 대신 정해진 칸(title/pay/…)을 채우게 하고, 칸이 비거나 틀리면 "다시"라고 돌려보냅니다.

같은 앱이 "이메일 초안"엔 도구를 강제하지 않는 이유는?

출력 형태는 용도를 따릅니다. 기계가 쓸 데이터는 스키마로 강제(Extract)하고, 사람이 읽을 글은 자유롭게 둡니다(Email). 같은 모델, 다른 계약(contract)이에요.