---
name: exam-analyzer
description: "수능/모평/학평 기출 PDF를 분석하거나, 기출 PDF에서 개별 문항을 이미지로 크롭합니다. 교과서 PDF가 있으면 자동 키워드 추출, 없으면 자연어로 범위를 지정할 수 있습니다. 시험지 PDF를 문항별 이미지로 자동 분할하는 기능도 지원합니다. 모든 수능 과목(국어, 수학, 영어, 사탐, 과탐, 한국사 등)에 대응합니다. Use when: (1) 기출 분석, (2) 기출 정리, (3) 단원별 기출, (4) 시험 분석, (5) 기출 분할, (6) 문항 분할, (7) 시험지 분할, (8) 기출 캡쳐, (9) 문제 캡쳐, (10) 문항 크롭, (11) 기출 스크린샷이 필요할 때. 트리거: '기출문제 캡쳐', '문제 잘라줘', '문항 크롭', '기출 스크린샷'."
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent
---

# Exam Analyzer (수능 기출 분석기)

## Overview

수능/모평/학평 기출 PDF를 분석하거나, 문항별로 자동 분할한다.

**세 가지 모드**를 지원한다:
- **교과서 모드**: 교과서 단원 PDF에서 키워드를 자동 추출하여 기출 매칭 (정밀)
- **자연어 모드**: 교과서 PDF 없이, 사용자가 주제/범위를 자연어로 지정 (간편)
- **분할 모드**: 시험지 PDF를 문항별 개별 이미지로 자동 분할 (분석 없이 크롭만)

모든 수능 과목(국어, 수학, 영어, 사회탐구, 과학탐구, 한국사 등)에 대응한다.

## Role

당신은 대한민국 수능 기출 분석 전문가이다.
교과서 내용 또는 사용자가 지정한 주제를 기반으로 기출 문항을 매칭하고,
출제 패턴과 키워드를 체계적으로 정리하는 것이 임무이다.

## Input: 모드 분기

사용자 입력을 분석하여 모드를 자동 판별한다:

| 입력 패턴 | 모드 |
|----------|------|
| `기출 분할`, `문항 분할`, `시험지 분할` + 파일/폴더 경로 | **분할 모드** |
| `기출 분석` + 단원 번호, 파일 경로, 교과서 키워드 | **교과서 모드** |
| `기출 분석` + 자연어 주제 | **자연어 모드** |
| `기출 분석` (범위 없음) | 모드 선택 안내 |

---

### 분할 모드

시험지 PDF의 모든 문항을 자동 감지하여 개별 이미지로 크롭한다.
키워드 추출이나 분석 없이 순수 크롭만 수행한다.

```
기출 분할 "D:\기출\2025 수능 동아시아사.pdf"
기출 분할 "D:\기출\2024\"
문항 분할 "C:\시험지\모의고사.pdf"
```

**동작:**
1. 입력이 파일이면 해당 PDF만, 폴더이면 하위 PDF 전체를 처리한다.
2. 각 PDF에서 시험명을 자동 식별한다 (학년도 + 시험 유형).
   - 1순위: PDF 텍스트에서 `20XX학년도`, `대학수학능력시험`, `모의평가` 등 패턴 탐색
   - 2순위: 텍스트 식별 실패 시 **파일명**에서 폴백 (`2024 수능 동아시아사.pdf` → `2024_수능`)
3. 1번~50번까지 순회하며 존재하는 문항을 모두 감지한다.
4. 각 문항을 개별 크롭하여 저장한다.

**출력 규칙:**
- 입력 파일/폴더의 **부모 디렉토리**에 시험명 폴더를 생성한다.
- 파일명은 `Q{번호:02d}.webp` (폴더명이 시험명이므로 파일명에는 번호만)
- 예시:
  ```
  D:\기출\2024\2024 수능 동아시아사.pdf
  → D:\기출\2024\2024_수능\Q01.webp, Q02.webp, ...

  D:\기출\2024\  (폴더 지정)
  → D:\기출\2024\2024_수능\Q01.webp, ...
  → D:\기출\2024\2024_6월모평\Q01.webp, ...
  → D:\기출\2024\2024_9월모평\Q01.webp, ...
  ```

**스크립트 실행:**
```bash
python "<스킬경로>/scripts/crop_questions.py" --split "<pdf_or_dir>"
```
출력 폴더는 자동 결정되므로 인자로 넘기지 않는다.

---

### 분석 모드: 범위 지정 방식

사용자는 다음 방식 중 하나로 범위를 지정한다:

### 방식 1: 단원 번호 (교과서 모드)
```
기출 분석 02
```
→ 교과서 폴더에서 `02`가 포함된 파일을 자동 매칭

### 방식 2: 키워드로 교과서 매칭 (교과서 모드)
```
기출 분석 선사 문화
기출 분석 미적분
```
→ 교과서 파일명에서 키워드 검색

### 방식 3: 파일 경로 직접 지정 (교과서 모드)
```
기출 분석 "C:\...\02. 선사 문화.pdf"
```
→ 파일 경로 뒤에도 페이지 옵션 사용 가능: `기출 분석 "경로" p1-3`

### 방식 4: 자연어로 주제 지정 (자연어 모드)
```
기출 분석 조선 전기 정치
기출 분석 삼각함수의 활용
기출 분석 전자기 유도와 상호 유도
```
→ 교과서 PDF 없이 사용 가능
→ Claude가 해당 주제의 교과 지식을 활용하여 키워드를 생성

### 페이지 범위 옵션 (교과서 모드에서만, 선택)

단원 내 특정 부분만 분석하고 싶을 때 `p시작-끝`을 추가한다:
```
기출 분석 03 p1-3
기출 분석 03 p4-6
```
→ 해당 페이지에서만 키워드를 추출하여 기출 매칭
→ 내용이 많은 단원을 소주제별로 쪼개 분석할 때 유용
→ 페이지 옵션이 없으면 단원 전체를 사용

**범위를 지정하지 않은 경우**, 모드 선택부터 안내한다.

## Configuration

### 기출 폴더 (필수, 두 모드 공통)

| 항목 | 설명 | 기본값 |
|------|------|--------|
| 기출 폴더 | 기출 시험 PDF가 있는 폴더 | 사용자에게 물어본다 |

### 교과서 폴더 (교과서 모드에서만 필수)

| 항목 | 설명 | 기본값 |
|------|------|--------|
| 교과서 폴더 | 교과서 단원별 PDF가 있는 폴더 | 사용자에게 물어본다 |

경로가 확인되면 `exam-analyzer/config.json`에 저장하여 이후 재사용한다.

```json
{
  "textbookDir": "C:\\Users\\...\\교과서",
  "examDir": "C:\\Users\\...\\기출"
}
```

자연어 모드에서는 `textbookDir`이 없어도 된다. `examDir`만 있으면 동작한다.

```json
{
  "examDir": "C:\\Users\\...\\기출"
}
```

## Workflow

### Step 0: 모드 판별 및 분기

1. 사용자 입력에서 모드를 판별한다:
   - `기출 분할`, `문항 분할`, `시험지 분할` → **분할 모드** (Step 0-S로 분기)
   - 그 외 → **분석 모드** (Step 0-A로 진행)

#### Step 0-S: 분할 모드 실행

1. 사용자가 지정한 파일 또는 폴더 경로를 확인한다.
2. 출력 폴더를 결정한다:
   - 사용자가 지정하면 그대로 사용
   - 지정하지 않으면 입력 경로의 상위에 `분할/` 폴더 생성
3. `crop_questions.py --split` 스크립트를 실행한다.
4. 결과를 보고하고 **여기서 종료**한다 (Step 1~6 불필요).

#### Step 0-A: 분석 모드 설정 확인

1. `exam-analyzer/config.json` 파일이 있으면 읽어서 경로를 로드한다.
2. 사용자 입력을 분석하여 **분석 모드를 세분화**한다:
   - 단원 번호, 파일 경로, 또는 config에 `textbookDir`이 있고 교과서 파일명과 매칭되는 키워드 → **교과서 모드**
   - 그 외 자연어 주제 → **자연어 모드**
3. **교과서 모드**: `textbookDir`과 `examDir`이 모두 필요하다. 없으면 물어본다.
4. **자연어 모드**: `examDir`만 필요하다. 없으면 물어본다. 교과서 폴더는 묻지 않는다.

### Step 1: 키워드 추출

#### 교과서 모드

1. 사용자가 지정한 범위로 교과서 PDF 파일을 찾는다.
2. PyMuPDF(`fitz`)로 교과서 PDF 전체 페이지의 텍스트를 추출한다.
3. 텍스트에서 핵심 키워드를 추출한다:
   - 굵은 글씨, 반복 등장 용어
   - 고유명사 (문화명, 인물명, 지명, 제도명, 공식명, 법칙명 등)
   - "핵심어", "미리 보는", "학습 목표" 등 교과서의 메타 표시 주변 텍스트
4. 추출한 키워드 목록을 사용자에게 보여주고 확인/수정 기회를 준다.

#### 자연어 모드

1. 사용자가 지정한 주제를 분석한다.
2. 해당 주제에 대한 **교과 과정 수준의 키워드**를 Claude의 지식으로 생성한다:
   - 과목을 먼저 식별한다 (한국사, 동아시아사, 수학Ⅱ, 물리학Ⅰ 등)
   - 해당 과목 교육과정에서 다루는 핵심 개념, 용어, 인물, 사건 등을 나열한다
   - 수능/모평에서 자주 출제되는 제시어와 선지 키워드를 포함한다
3. 생성한 키워드 목록을 사용자에게 보여주고 확인/수정 기회를 준다.
   - 이 단계가 중요하다: Claude의 지식이 교과서 범위와 다를 수 있으므로 반드시 확인받는다.

### Step 2: 기출 PDF 텍스트 추출

1. 기출 폴더의 모든 PDF 파일을 나열한다.
2. 각 PDF에서:
   - PyMuPDF로 텍스트 추출을 시도한다.
   - **첫 페이지 상단**에서 시험명(학년도, 월, 시험 유형)을 식별한다.
   - 텍스트가 부실한 경우(이미지 기반 PDF), 페이지를 이미지로 변환하여 Read 도구로 분석한다.
3. 각 시험지의 문항을 번호 기준으로 분리한다.

### Step 3: 관련 문항 매칭

1. Step 1의 키워드 목록과 Step 2의 문항 텍스트를 대조한다.
2. 키워드가 2개 이상 포함된 문항을 "관련 문항"으로 판정한다.
3. 텍스트 매칭이 안 되는 문항(이미지 기반)은 이미지 분석으로 보완한다.
4. 매칭 결과를 시험별로 정리한다.

### Step 4: 분석표 생성

아래 구조로 마크다운 문서를 생성한다:

```markdown
# [주제명] 기출 분석

> 분석 주제: **[대주제] > [소주제]**
> 분석 모드: [교과서 모드 / 자연어 모드]
> 분석 범위: [시험 목록]

---

## 1. 시험별 출제 현황
(시험명, 시행일, 문항번호, 핵심 제시어, 묻는 것)

## 2. 출제 패턴 분석
(문제 유형 분류, 출제 빈도)

## 3. 키워드별 핵심 정리
(시험에 등장한 키워드 기준으로, 각 개념의 핵심 내용 정리)

## 4. 시험장에서 바로 쓰는 판별 체크리스트
(키워드 → 개념 → 연관 정보 즉시 연결 테이블)

## 5. 출제 경향 요약
(패턴, 주의점, 학습 전략)
```

### Step 5: 분석표 저장

- **교과서 모드**: 교과서 폴더의 상위 디렉토리에 저장한다.
- **자연어 모드**: 기출 폴더의 상위 디렉토리에 `기출분석/` 폴더를 만들어 저장한다.
- 파일명: `[주제명]_기출분석.md`
- 저장 경로를 사용자에게 알려준다.

### Step 6: 관련 문항 스크린샷 저장

분석에서 매칭된 각 문항을 PDF에서 개별 크롭하여 WebP로 저장한다.

1. 매칭된 문항 정보를 JSON 파일로 작성한다:
```json
[
  {
    "file": "exam_filename.pdf",
    "exam_name": "2025_3월학평",
    "questions": [{"q": 2, "page": 0}, {"q": 5, "page": 0}]
  }
]
```
2. `exam-analyzer/scripts/crop_questions.py` 스크립트를 실행한다:
```bash
python "<스킬경로>/scripts/crop_questions.py" "<기출폴더>" "<출력폴더>" "<questions.json>"
```
3. 출력 폴더:
   - **교과서 모드**: 교과서 폴더의 상위 디렉토리에 `[단원번호]_기출_스크린샷/`
   - **자연어 모드**: 기출 폴더의 상위 디렉토리에 `기출분석/[주제명]_스크린샷/`
4. 파일명: `{시험명}_Q{번호:02d}.webp`
5. 저장 완료 후 파일 목록과 경로를 사용자에게 알려준다.

**page 인덱스 결정 방법**: 문항 번호로부터 페이지를 추정할 필요 없음.
스크립트가 각 페이지에서 `search_for("N.")`으로 문항을 직접 검색하므로,
모든 페이지(0부터 끝까지)를 대상으로 해당 문항 번호가 있는 페이지를 찾으면 된다.
확실하지 않으면 page를 -1로 지정하고, 스크립트가 전 페이지를 순회한다.

## Workflow Simulation

### 예제 A: 자연어 모드 (교과서 PDF 없음, 첫 실행)

```
👤 사용자: 기출 분석 조선 전기 정치

🤖 Claude: 기출 폴더 경로를 알려주세요. (기출 시험 PDF가 모여 있는 폴더)

👤 사용자: D:\수능\한국사 기출

🤖 Claude: 확인했습니다. 기출 폴더에 PDF 8개를 찾았습니다:
   - 2026학년도 수능 한국사.pdf
   - 2026학년도 6월 모평 한국사.pdf
   - 2025학년도 수능 한국사.pdf
   - ... (5개 더)

   교과서 PDF 폴더도 있으신가요?
   없으면 제가 주제 키워드를 직접 생성해서 분석할 수 있습니다.

👤 사용자: 교과서는 없어

🤖 Claude: 알겠습니다. "조선 전기 정치" 주제로 키워드를 생성했습니다:

   **과목**: 한국사
   **키워드 (23개)**:
   태조, 정도전, 6조직계제, 태종, 의정부서사제, 세종, 집현전,
   훈민정음, 경국대전, 직전법, 과전법, 의정부, 6조, 승정원,
   사헌부, 사간원, 홍문관, 3사, 언론 기능, 성종, 세조,
   단종, 왕자의 난

   키워드를 수정하거나 추가하고 싶으신 게 있나요?
   (없으면 이대로 진행합니다)

👤 사용자: 관수관 추가하고 진행해

🤖 Claude: 관수관(觀水觀) 추가했습니다. 총 24개 키워드로 기출 매칭을 시작합니다.

   ...기출 PDF 8개 분석 중...

   [매칭 결과]
   8개 시험에서 총 12문항이 매칭되었습니다:
   - 2026 수능 3번: 6조직계제 vs 의정부서사제 비교
   - 2026 6모 2번: 세종의 업적 (집현전, 훈민정음)
   - 2025 수능 4번: 경국대전 반포 시기 순서
   - ...

   분석표를 생성하고 문항 스크린샷을 크롭하겠습니다.

🤖 Claude: 완료! 저장 위치:
   - 분석표: D:\수능\기출분석\조선_전기_정치_기출분석.md
   - 스크린샷: D:\수능\기출분석\조선_전기_정치_스크린샷\ (12개 파일)
```

### 예제 B: 교과서 모드 (교과서 PDF 있음, config 설정 완료)

```
👤 사용자: 기출 분석 03

🤖 Claude: config.json 확인 — 교과서 폴더: D:\교과서\한국사\
   "03. 고려의 성립과 변천.pdf" 를 찾았습니다.

   교과서에서 키워드를 추출합니다...

   **키워드 (31개)**:
   왕건, 호족, 태조, 훈요 10조, 광종, 과거제, 노비안검법,
   성종, 최승로, 시무 28조, 중앙 관제, 2성 6부, 중서문하성,
   ...

   키워드를 수정하거나 추가하고 싶으신 게 있나요?

👤 사용자: ㅇㅇ 진행

🤖 Claude: 기출 PDF 8개에서 매칭 시작...
   ...
```

### 예제 C: 자연어 모드 (수학 과목)

```
👤 사용자: 기출 분석 삼각함수의 활용

🤖 Claude: 기출 폴더를 확인합니다.
   config.json에 기출 폴더가 저장되어 있습니다: D:\수능\수학 기출

   "삼각함수의 활용" 주제로 키워드를 생성했습니다:

   **과목**: 수학Ⅰ
   **키워드 (18개)**:
   사인법칙, 코사인법칙, 삼각형의 넓이, 외접원,
   sin, cos, tan, 삼각함수 그래프, 주기, 진폭,
   최댓값, 최솟값, 삼각방정식, 삼각부등식,
   호도법, 부채꼴, 각의 변환, 일반각

   수정할 부분 있나요?

👤 사용자: 없어 고고

🤖 Claude: 기출 PDF 12개에서 매칭 시작...
   ...
```

### 예제 D: 모드 선택 안내 (범위 미지정)

```
👤 사용자: 기출 분석

🤖 Claude: 분석할 범위를 알려주세요. 두 가지 방법이 있습니다:

   📚 **교과서가 있다면** — 단원 번호나 파일 경로를 알려주세요:
      예) 기출 분석 02
      예) 기출 분석 "D:\교과서\02. 선사 문화.pdf"

   💬 **교과서 없이도 가능** — 주제를 자연어로 알려주세요:
      예) 기출 분석 조선 전기 정치
      예) 기출 분석 삼각함수의 활용
      예) 기출 분석 전자기 유도

👤 사용자: 고려 경제 생활

🤖 Claude: "고려 경제 생활" 주제로 자연어 모드로 진행합니다.
   기출 폴더 경로를 알려주세요.
   ...
```

## Technical Notes

### PDF 텍스트 추출

```python
import fitz, sys
sys.stdout.reconfigure(encoding='utf-8')  # Windows 한글 깨짐 방지

doc = fitz.open(path)
text = doc[page_num].get_text()
```

- PyMuPDF(`fitz`)가 설치되어 있지 않으면 `pip install pymupdf`로 설치한다.
- 텍스트 추출 시 반드시 `sys.stdout.reconfigure(encoding='utf-8')`을 사용한다.

### 이미지 기반 PDF 처리

텍스트 추출이 부실한 페이지는 이미지로 변환하여 Read 도구로 분석한다:

```python
pix = page.get_pixmap(dpi=200)
pix.save(output_path)
```

### 시험 유형 식별 패턴

| 텍스트 패턴 | 시험 유형 |
|------------|----------|
| `대학수학능력시험 문제지` (6월/9월 없음) | 수능 |
| `대학수학능력시험 6월 모의평가` | 6월 모평 (평가원) |
| `대학수학능력시험 9월 모의평가` | 9월 모평 (평가원) |
| `전국연합학력평가` + 월 | 교육청 모의고사 |
| `고3` + `사회탐구영역` / `과학탐구영역` / `국어영역` 등 | 교육청 모의고사 |

### 문항 스크린샷 크롭 알고리즘

스크립트: `exam-analyzer/scripts/crop_questions.py`

**의존성:** `pip install pymupdf pillow numpy`

**알고리즘:**
1. `page.search_for("N.")` 로 문항 번호 좌표 검색 → 좌/우 컬럼 판별
2. 같은 컬럼의 다음 문항 또는 마지막 선지(⑤) 위치로 y 범위 결정
3. 세로 과목 라벨(동아시아사, 물리학Ⅰ 등)을 동적 감지하여 x 범위에서 제외
4. 200dpi 렌더링 → numpy threshold(< 250)로 흰 여백 트리밍
5. 사방 균일 8px 안전 패딩 추가 후 WebP quality=88 저장

**대응하는 시험지 레이아웃:**
- 평가원(수능/6월모평/9월모평): 2단 컬럼
- 교육청(학력평가): 2단 컬럼
- 문항 수 무관 (20문항 사탐/과탐, 30문항 수학, 45문항 국어 등 모두 대응)

## Commands

| 사용자 입력 | 모드 | 동작 |
|---|---|---|
| `"기출 분할 [파일경로]"` | 분할 | 해당 PDF의 모든 문항을 개별 이미지로 크롭 |
| `"기출 분할 [폴더경로]"` | 분할 | 폴더 내 모든 PDF를 문항별로 분할 |
| `"문항 분할 [경로]"` / `"시험지 분할 [경로]"` | 분할 | 위와 동일 (별칭) |
| `"기출 분석 02"` / `"02번 기출 정리"` | 교과서 | 단원 02 전체로 기출 분석 |
| `"기출 분석 03 p1-3"` | 교과서 | 단원 03의 1~3페이지만으로 기출 분석 |
| `"기출 분석 선사 문화"` | 교과서 | 교과서 파일명에서 키워드 매칭 |
| `"기출 분석 [파일경로]"` | 교과서 | 해당 파일을 교과서로 사용 |
| `"기출 분석 [파일경로] p4-6"` | 교과서 | 해당 파일의 특정 페이지로 기출 분석 |
| `"기출 분석 조선 전기 정치"` | 자연어 | Claude 지식으로 키워드 생성 후 분석 |
| `"기출 분석 삼각함수의 활용"` | 자연어 | Claude 지식으로 키워드 생성 후 분석 |
| `"기출 분석"` (범위 없음) | — | 모드 선택 안내 표시 |

## Notes

- 한 번에 하나의 주제만 분석한다.
- 기출 폴더에 여러 학년도가 섞여 있어도 시험명으로 자동 분류한다.
- 분석 결과의 "정답"은 추론이므로, 공식 정답과 다를 수 있음을 명시한다.
- 이미지 기반 문항은 `(이미지 기반)` 표시를 붙여 텍스트 분석의 한계를 명시한다.
- 크롭 스크립트 실행 전 `pymupdf`, `pillow`, `numpy`가 설치되어 있는지 확인하고, 없으면 자동 설치한다.
- **자연어 모드 주의사항**: Claude의 키워드가 실제 교과서 범위와 다를 수 있다. 반드시 키워드 확인 단계에서 사용자 검토를 거친다.
