KikiLeoBook 리더 개선 기록: TXT/EPUB TTS 붙이고 EPUB 위치 저장까지 점검한 날
2026년 3월 25일 오후 - 3월 26일 새벽
이번 작업은 KikiLeoBook 리더에 오프라인 TTS를 붙이는 데 집중했다.
처음에는 단순히 읽어주기 버튼 하나를 추가하는 정도로 생각했지만, 실제로는 TXT와 EPUB이 텍스트를 다루는 방식이 달라서 읽기 위치 표시, 페이지 이동 동기화, EPUB 위치 저장 문제까지 함께 정리해야 했다.
결과적으로 이번 단계에서는 아래 세 가지가 중심이었다.
- 오프라인 TTS 1차 도입
- TXT / EPUB 읽기 흐름 정리
- EPUB 위치 복원 문제 디버깅
오프라인 TTS 1차 도입
이번에는 클라우드 음성은 제외하고, Android 기기 안에 있는 TTS 엔진을 사용하는 방향으로 정리했다.
비용 부담 없이 바로 붙일 수 있고, 현재 목표인 “앱 화면이 켜져 있을 때만 동작”에도 가장 잘 맞는 방식이었다.
1차 목표는 이렇게 잡았다.
- 앱 화면이 켜져 있을 때만 동작
- TXT와 EPUB 모두 지원
- 내부는 문장 단위로 읽되, UI는
Read aloud / Pause / Stop정도로 단순화 - 백그라운드 재생이나 문장 이전/다음 같은 고급 기능은 다음 단계로 미룸
구조도 리더 화면에 TTS 코드를 직접 붙이기보다 공통 계층을 두는 방식으로 정리했다.
ReaderTtsControllerAndroidTtsEngineReaderTextProviderTtsUiState
이렇게 해두니 TXT와 EPUB이 각자 다른 방식으로 텍스트를 제공하더라도, 상위 제어 흐름은 같은 방식으로 묶을 수 있게 됐다.
TXT와 EPUB에 TTS 연결
TXT는 비교적 straightforward했다.
이미 현재 페이지 문자열과 페이지 상태를 가지고 있어서, 현재 위치 기준으로 문장을 나눠 순차적으로 읽도록 연결하면 됐다.
EPUB은 조금 더 손이 갔다.
WebView 안에서 렌더링되는 구조라 Android 쪽에서 현재 보이는 텍스트를 바로 알 수 없기 때문이다.
그래서 epub.js와 Android 사이 브리지를 확장해서, JS에서 현재 보이는 페이지 기준 텍스트를 추출한 뒤 Android로 넘기는 흐름으로 정리했다.
함께 반영한 내용은 다음과 같다.
- 리더 상단 메뉴에서
Read aloud진입 가능하도록 정리 - TTS 시작, 일시정지, 정지 상태를 리더 상태와 연결
- 아직 준비되지 않은 경우 무리하게 시작하지 않도록 방어
Speech speed,Speech pitch옵션 연결Korean / English선택은 1차 범위에서 제외
언어 선택은 처음에는 넣어봤지만, 실제 사용 기준에서는 굳이 유지할 필요가 없다고 판단했다.
현재 단계에서는 속도와 피치 정도만 남기는 쪽이 더 단순하고 실용적이었다.
현재 읽는 위치가 보이도록 개선
TTS를 붙이고 나니 바로 보였던 문제가 하나 있었다.
음성은 나오는데 지금 어디를 읽고 있는지가 화면에서 잘 보이지 않는다는 점이었다.
그래서 현재 읽는 문장을 강조 표시하는 흐름을 추가했다.
- TXT는 현재 읽는 문장을 페이지 안에서 하이라이트
- EPUB도 WebView 내부에서 현재 문장을 강조 표시
- 검색 하이라이트와 TTS 하이라이트가 서로 덮어쓰지 않도록 분리
이와 함께, 읽는 문장이 다음 페이지로 넘어가면 화면도 같이 따라가도록 보강했다.
즉 TTS는 다음 페이지를 읽고 있는데 사용자가 보고 있는 화면은 이전 페이지에 멈춰 있는 어색한 상태를 줄이는 방향으로 정리한 것이다.
이 부분은 실제 사용감에 꽤 크게 영향을 줬다.
단순히 읽어주는 기능에서 끝나는 것이 아니라, 지금 읽는 위치를 눈으로 함께 따라갈 수 있어야 훨씬 자연스럽게 느껴졌기 때문이다.
중간 점검 결과
직접 확인한 결과는 다음과 같았다.
- TXT는 TTS 동작이 비교적 안정적으로 붙음
- EPUB도 현재 보이는 페이지 기준으로 읽어오는 동작까지는 정리됨
- 메뉴 노출 문제와 준비 상태 gating 문제는 중간 수정으로 정리
- 속도와 피치 옵션도 정상 동작 확인
반면 EPUB 쪽에는 한 가지 큰 문제가 남아 있었다.
- 읽다가 나갔다가 다시 들어오면 항상 첫 페이지가 열림
- 즉 EPUB 위치 복원이 실패하고 있었음
이건 단순 UI 문제가 아니라, 저장된 읽기 위치가 실제로 다시 적용되지 않는 흐름에 가까웠다.
EPUB 위치 복원 문제를 추적한 과정
이 문제는 생각보다 오래 걸렸다.
처음에는 Android 쪽 저장 순서 문제, WebView 초기화 타이밍 문제, savedCfi 반영 순서 문제를 차례대로 의심했다.
그래서 여러 번에 걸쳐 다음과 같은 방향으로 수정과 확인을 반복했다.
- EPUB progress와
savedCfi로드 순서 조정 openBook()시점에 초기 CFI를 바로 반영하도록 수정- 복원 중 잘못된 첫 위치 이벤트가 저장값을 덮어쓰지 않도록 방어
- 현재 표시 위치와 저장 위치가 다르면 다시
goToCfi()를 시도하는 보강 - EPUB 압축 해제를 캐시 재사용 방식으로 바꿔 초기 로딩 시간을 완화
이 과정에서 로딩 속도는 다소 나아졌지만, 위치 복원 자체는 계속 첫 페이지로 열리는 문제가 남아 있었다.
Claude Code로 이어서 확인한 원인
복원 문제가 계속 남아 있어서, 이 부분은 Claude Code로 이어서 원인 분석을 진행했다.
여기서 핵심 원인은 CFI 저장값 자체가 비어 있거나 잘못된 문자열로 들어가고 있었다는 점이었다.
정리하면 다음과 같다.
epub_reader.html
locationChanged이벤트 객체의loc.start.cfi대신rendition.currentLocation().start.cfi에서 실제 CFI를 읽도록 변경
이 epub.js 버전에서는 loc.start.cfi가 항상 빈 문자열을 반환하고 있었고,
그 결과 Android 쪽에는 정상 위치가 아니라 빈 값이나 "undefined" 같은 문자열이 들어가고 있었다.
EpubReaderFragment.kt
"epubcfi"로 시작하지 않는 값은 위치 변경 로직에서 무시하도록 방어 코드 추가
ReaderActivity.kt
onStop()에서 EPUB 진행 저장 시에도cfi.startsWith("epubcfi")를 통과하는 값만 저장하도록 정리
즉, 처음에는 복원 로직 자체를 의심했지만, 실제로는 복원에 필요한 정상적인 위치값이 저장되지 않고 있었던 쪽에 더 가까웠다.
빌드와 검증
기능을 붙이고 나서는 코드 컴파일과 APK 생성까지 계속 확인했다.
확인한 항목:
compileDebugKotlin성공assembleDebug성공- 디버그 APK 생성 확인
실기기 기준으로는 다음 내용까지 확인했다.
- TXT TTS 동작 확인
- EPUB TTS가 현재 보이는 페이지부터 읽는 동작 확인
- EPUB 복원 문제는 원인 분석과 수정이 반영된 상태까지 정리
다만 EPUB 위치 복원은 최종적으로 실기기에서 한 번 더 재확인할 필요가 있다.
이번 글에서는 “원인 분석과 수정 반영까지 완료된 상태”를 기준으로 기록해둔다.
이번 작업에서 정리된 내용
완료
- 오프라인 Android TTS 1차 구조 추가
- TXT / EPUB 리더에 TTS 연결
Read aloud / Pause / Stop흐름 정리- TTS 속도와 피치 옵션 연결
- TXT 현재 문장 하이라이트 반영
- EPUB 현재 문장 하이라이트 반영
- 읽는 위치가 다음 페이지로 넘어갈 때 화면도 따라가도록 보강
- EPUB 현재 보이는 페이지 기준 텍스트 읽기 개선
- EPUB CFI 저장 경로 문제 원인 분석 및 수정 반영
- 디버그 빌드와 APK 생성 확인
남은 확인
- EPUB 위치 복원 최종 실기기 재확인
- TTS 하이라이트 색상과 가독성 미세 조정
- EPUB 페이지 전환 시 체감 자연스러움 추가 점검
- 이후 단계에서 백그라운드 재생 여부 검토
메모
이번 작업은 단순히 “읽어주기 기능을 추가했다”로 끝나는 작업은 아니었다.
TXT와 EPUB이 각각 다른 방식으로 텍스트를 다루고 있어서, 실제로는 리더 구조와 현재 위치 표현, 페이지 전환 동기화, 위치 저장 방식까지 같이 손봐야 했다.
특히 EPUB은 WebView, JS 브리지, Android 저장 흐름이 함께 얽혀 있어서 겉으로 보이는 문제 하나를 수정하려고 해도 원인 추적 범위가 넓었다.
그래도 이번 단계로 리더에 TTS 기본 골격은 올라갔고,
사용자가 “듣고, 어디를 읽는지 보고, 페이지 흐름을 따라가는” 경험까지는 만들어가는 단계에 들어섰다.
다음 단계에서는 EPUB 위치 복원 최종 재확인과 함께,
하이라이트 완성도와 문장 추적 안정성을 더 다듬는 쪽으로 이어갈 예정이다.
'AI > 잡다한개발노트' 카테고리의 다른 글
| KikiLeoBook 릴리즈 준비 — 패키지 리네임부터 GitHub Release까지 (0) | 2026.03.29 |
|---|---|
| KikiLeoBook 개발 진행 상황 5차 (0) | 2026.03.29 |
| KikiLeoBook 개발 진행 상황 3차 (0) | 2026.03.25 |
| KikiLeoBook 개발 진행 상황 2차 (0) | 2026.03.24 |
| 타워디펜스 - 맵 에디터 × Battle Simulator 통합 강화 플랜 (1) | 2026.03.02 |