# AIACube Reader 2.2 기능별 개발명세 — 운수 좋은 날

기준일: 2026-09-30. 이 문서는 실제 코드와 잔여 개발의 인수 기준을 정의한다. 특허 관련 판단은 포함하지 않는다.

## 1. 데이터와 구성

- `book.json`/`book.js`: 판본 ID, 원고 해시, 문단 ID·내용·역할, 주석. 92블록/71주석. 버전 2.2.0, 원문이 같으므로 판본 ID 유지.
- `reader-core.js`, `reader.js`: 독서 위치·표시·페이지 이동. 저장용 위치의 코드포인트와 렌더링용 UTF-16 오프셋을 혼용하지 않는다.
- `reader2.js`: 노트·선택 구절·문단 기능. `speech-core.js`: 문장 분할과 낭독 텍스트 변환.
- `upgrade.js`: 낭독 상태·AI 대화·마이크 UI. `server.cjs`: 등록 본문 검증과 API 중계.
- 원고 각주 표시는 화면에서 `[^n]` 대신 `〔n〕` 사용. 원본 source.md는 그대로 보존.

## 2. 독서·기록 명세

| ID | 입력/동작 | 결과/저장 | 실패·검증 기준 |
|---|---|---|---|
| R01 | 페이지·스크롤 전환, 글자 설정 | 같은 원문 위치 중심으로 표시 | 끝/처음 경계 및 설정 변경 뒤 위치 검증 |
| R02 | 검색어 입력 | 일치 구절과 본문 이동 | 무결과 표시, 원래 읽던 곳 복귀 |
| R03 | 책갈피·문단 집중 | 판본별 원문 위치 저장 | 잘못된 판본 위치 혼용 금지 |
| R04 | 선택 구절 메모 | 원문 인용과 메모, 수정·삭제·복구 | 선택 없음 안내, 기존 메모 보존 |
| R05 | JSON 백업/가져오기 | 로컬 노트 병합, 텍스트 내보내기 | 손상된 입력 거절, 계정 동기화와 구별 |
| R06 | 주석 열기·검색 | 71주석 및 본문 이동 | 참조 누락 없음 |

## 3. 낭독 명세

| ID | 동작·설정 | 구현 계약 | 제한/인수 기준 |
|---|---|---|---|
| N01 | 기기 음성 선택 | speechSynthesis 음성 목록, 목록 변경 반영 | 음성 수는 기기에 종속 |
| N02 | 속도·높낮이·음량 | 속도 0.5~2, 기기 높낮이 0.5~1.5 | ‘속도 지금 적용’은 재생 중 문장을 다시 시작 |
| N03 | AI 음성 | coral/alloy/sage/nova/marin/cedar와 3개 말투 | 실제 시험 coral 1종. 합성 음성 표시 |
| N04 | 시작·정지·재개 | 취소 후 같은 문장 처음부터 재개 | 정밀 시간점 재개로 표현하지 않음 |
| N05 | 문장·문단 이동 | 원문 인덱스 및 범위로 앞/뒤 이동 | 처음·끝 경계, 취소된 음성의 늦은 콜백 방지 |
| N06 | 화면/선택부터 | 현재 원문 범위에서 읽기 | 선택 구절 재개는 범위 처음 |
| N07 | 강조·따라가기 | 원문 문장 강조, 필요시 문단 테두리 대체 | 단어 단위 타임스탬프 아님. 수동 탐색 시 따라가기 해제 |
| N08 | 반복·종료 예약 | 1~3회, 5/15/30분 | 탭 수명·OS 절전에 영향받음 |
| N09 | 발음 사전 | 사용자 문자열 치환을 낭독문에만 반영 | 원본과 검색·인용은 변경 금지 |
| N10 | AI 음원 탐색·저장 | 현재 생성된 음원 10초 이동·다운로드 | 책 전체 음원 파일 아님 |
| N11 | 노트 낭독 | 노트 텍스트를 음성 입력으로 전달 | 현재 3,500자 제한. 후속 분할 필요 |
| N12 | 한자 병기 생략 | 아래 알고리즘, 기본 ON | 미등록·불일치는 유지 |
| N13 | 낭독문 확인 | 원문/변환문과 생략 개수 팝업 | 재생 중 현재 문장, 정지 중 현재 범위 표시 |

### N12 알고리즘과 위치 계약

1. 연속 한글 바로 뒤의 ASCII 또는 전각 괄호에 한자만 있는 후보를 찾는다.
2. 여닫는 괄호 종류가 같고, 괄호 안 전체 문자열의 등록 독음이 앞 연속 한글 전체와 일치할 때만 괄호 부분을 제거한다. 단어 접미부만 추정해 지우지 않는다.
3. 주석 표식 제거와 사용자 발음 치환을 수행한다. 변환 구간이 겹치면 기존 편집 구간을 보존하고 중복 편집하지 않는다.
4. `prepare()`는 text, map, edits, sourceLength를 반환한다. map은 낭독문 UTF-16 인덱스에서 원문 인덱스로의 단조 대응이며 마지막 값은 원문 길이다. 치환 문자열은 원문 시작점에 대응한다. edits에 시작·끝·사유를 유지한다.
5. `clean()`은 text만 반환하며 기기/AI 본문 낭독에 같은 변환을 사용한다. map은 향후 단어 정렬에 사용할 기반으로 생성되지만 현재 문장 강조가 이 map으로 단어 추적을 하는 것은 아니다.

수의(壽衣)→수의, 신조（信條）→신조는 통과. 수의(未知), 다른수의(壽衣), 서로 다른 괄호, 설명문은 보존. 반복 출현과 이모지 앞뒤 위치를 검사한다. 옵션 OFF이면 병기는 유지하되 주석 번호 제거는 유지한다. 13개 회귀 사례를 development/test-speech.cjs에 포함한다.

## 4. AI 질문과 음성 입력 명세

| ID | 처리 | 인수 기준/현재 상태 |
|---|---|---|
| A01 | 선택/현재 화면/현재 위치까지 문맥 선택 | 판본 ID와 문단 인덱스·시작/끝만 서버 전달 |
| A02 | 서버 등록 본문으로 문맥 구성 | 범위 초과·다른 판본 거절. 요청 본문을 권위 있는 원문으로 믿지 않음 |
| A03 | 답변과 근거 인용 | 반환 인용을 원문과 대조하고 위치 연결. 실제 응답 시험 성공 |
| A04 | 문자/음성/둘 다 | 문자 표시와 음성 합성 선택. 모델 해석 오류 가능성은 별개 |
| A05 | 답변 노트 저장 | 질문·답변·인용·모델 정보 기록 |
| A06 | 닫기·새 질문 | 이전 요청 취소, 늦은 응답이 새 화면 덮지 않도록 제어 |
| A07 | 마이크 질문 | 최대 60초 녹음→STT→사용자 확인 후 전송. 실제 마이크 검증 대기 |
| A08 | 실시간 음성 | WebRTC/SDP, 책 문맥, 2분 세션, 종료 정리. 시험 기능이며 실제 세션 검증 대기 |
| A09 | 외부 ChatGPT | 질문 문맥 복사와 외부 링크 | 내장 API와 외부 계정 서비스를 구분 |

### API 계약

| 경로 | 입력/출력 | 주요 조건 |
|---|---|---|
| GET /api/status | 연결 상태 및 로컬 요청 토큰 | 토큰을 보고서·로그에 출력하지 않음 |
| POST /api/key | key → 연결 확인 | 로컬 서버 메모리, 종료 시 삭제 |
| POST /api/ask | editionId, ranges[{i,start,end}], question → answer,citations | 원문 범위와 인용 검증, 기본 gpt-4.1-mini |
| POST /api/speech | text,voice,style → MP3 | 최대 4,000자, gpt-4o-mini-tts |
| POST /api/transcribe | audio(base64),mime → 인식문 | webm/mp4/ogg/wav, gpt-4o-mini-transcribe |
| POST /api/realtime | editionId,ranges,sdp → SDP | gpt-realtime, 문자 인용 검증과 별개 |
| POST /api/shutdown | 종료 | 메모리 키 정리 |

보호되는 요청에는 로컬 토큰과 Origin 검증을 적용한다. 서버 파일 접근은 허용된 웹 자산으로 제한한다. 이 제어를 공개 서비스 사용자 인증으로 간주하지 않는다.

## 5. 제작·EPUB·배포 명세

| ID | 요구 | 현재/완료 기준 |
|---|---|---|
| B01 | 원고 보존 | 원본 SHA-256 및 source.md 일치 |
| B02 | 웹·EPUB 일관성 | 92블록/71주석, 본문 대조 통과 |
| B03 | EPUB 유효성 | EPUBCheck 5.3.0 오류 0/경고 0인 동일 파일 사용 |
| B04 | 범용 자동 제작 | 현재 미완료. 경로 매개변수·다른 원고 2종·실패 보고·단일 명령 필요 |
| D01 | 로컬 실행 | START.cmd/STOP.cmd, Node.js 22+ |
| D02 | 서버 배포 | reader/A_Lucky_Day 대상, 이번 공개판 배포 대상 |
| D03 | 공개 AI | HTTPS 백엔드와 /api 라우팅, 비밀키·인증·비용 한도·운영 로그 후속 구현 |

## 6. 검증 기록 및 인수 보류

이번 자동 검증: 변환 13사례, 92블록 원문 문장 재결합, 원문 매핑 단조성, 중복 5건, 실제 질문 HTTP 200 및 인용, TTS HTTP 200/57,600바이트. 화면 검증: 동광학교 병기 ON/OFF, 설명 괄호 유지, 원문 불변, 오류 로그 없음. EPUB과 원고 파일은 이전 검증본 및 원본과 해시 비교한다.

이전 판 검증은 verification.json에 이력으로 유지한다. 이번에 모든 기존 조합을 재시험했다는 의미는 아니다. 마이크/STT, 실시간 음성, 실제 모바일 기기, 공개 서버 URL 종단 시험은 인수 대기다. 개발 완료와 운영 검증 완료를 구분해 출시한다.


## 공개판 배포 보완 — 2026-09-30

/reader/에 AiaCube ebook 목록을 두고 사라진느 기존 주소와 /reader/A_Lucky_Day/를 연결한다. 개발 문서는 최신 계획안·명세 두 개만 게시한다. 상단 EPUB 독서 메뉴는 바로 읽기(파일 제공), Thorium 공식 다운로드 안내, Project Gutenberg 링크 및 닫기·바깥 클릭·Esc 닫기를 제공한다.

이번 공개판은 독서·메모·기기 낭독·EPUB을 제공한다. 내장 AI 백엔드는 미연결 상태로 키 입력·API 질문·AI 음성·마이크·실시간 대화는 비활성화하고 준비 중 안내를 표시한다. 질문 복사와 외부 ChatGPT 링크는 제공한다. 로컬판의 API 검증 결과는 공개 서버의 AI 연결 검증을 의미하지 않는다. 기존 로컬 실행본과 메모리 키는 유지한다.
