저~ 밑에 깔려 있어서 한참 못 봤는데, 어느새 심사를 통과해서 App Store에 올라가 있더군요. 개인적으로 만들던 문서 스캐너 앱 DOXcanner가 정식 출시됐습니다. 기념으로, 무엇을 만들었고 만들면서 뭘 배웠는지 짧게 정리해 둡니다.
한 줄로 말하면
종이를 스캔해서 기기 안에서 바로 텍스트로 바꾸고, 본인의 Claude API 키로 번역·요약까지 받는 미니멀 문서 스캐너.
흐름은 딱 세 단계입니다.
- 스캔 — 카메라로 문서를 찍으면 가장자리를 자동으로 인식해 반듯하게 잘라 줍니다. 여러 장도 한 번에.
- OCR — 잘라낸 이미지를 기기 안에서 텍스트로 변환합니다. 한국어와 영어를 같이 인식해요.
- Claude — 추출한 텍스트를 Claude에게 보내 번역·요약·핵심 포인트·주의사항·할 일까지 정리해 받습니다.
왜 만들었나
외국어 안내문, 영수증, 회의 때 찍은 화이트보드 사진… "이거 그냥 텍스트로 바꿔서 요약만 보면 되는데" 싶은 순간이 자주 있었습니다. 기존 스캐너 앱은 스캔까지는 잘 해주는데 거기서 끝나고, 번역·요약은 또 다른 앱에 붙여 넣어야 했죠.
그래서 스캔 → 텍스트 → 이해까지를 한 앱 안에서 끊김 없이 하고 싶었습니다. 그리고 이왕이면, 내 문서를 남의 서버에 쌓아 두지 않는 방식으로요.
프라이버시는 타협하지 않았습니다
이 앱에서 제일 신경 쓴 부분입니다.
- 스캔한 이미지는 기기를 떠나지 않습니다. 원본 이미지는 기기 안 SQLite에만 저장돼요. 외부로 전송되는 건 OCR로 추출된 텍스트뿐입니다.
- API 키는 iOS 키체인(보안 저장소)에 저장됩니다. 앱 어디에도 평문으로 남지 않아요.
- 자체 백엔드도, 계정도, 광고도, 클라우드 동기화도 없습니다. 가입 절차 자체가 없습니다.
대신 사용 모델은 BYO(Bring Your Own) Claude API 키 방식입니다. 설정 화면에 본인의 Anthropic API 키를 한 번 넣어 두면, 사용량과 과금은 전적으로 본인 계정에서 관리됩니다. 제가 중간에서 토큰을 떼지도, 구독을 강제하지도 않습니다. 쓴 만큼만 본인 계정에 청구돼요.
어떻게 만들었나 (그리고 어디서 고생했나)
기술 스택은 Flutter + iOS입니다. 핵심 조각은 단순해요.
- 스캔 UI:
cunning_document_scanner(시스템 스캐너 기반 자동 가장자리 인식) - 온디바이스 OCR: Google ML Kit Text Recognition
- 번역·요약: Claude haiku 4.5 (
claude-haiku-4-5-20251001)
그런데 단순한 조합이라고 순탄했던 건 아니고, 기록해 둘 만한 함정이 둘 있었습니다.
함정 1 — OCR 라이브러리가 iOS 26에서 앱을 통째로 죽였다
ML Kit 텍스트 인식 패키지의 최신 버전(0.15.1)을 쓰면 iOS 26에서 Flutter 앱이 시작조차 못 하고 죽는 문제가 있었습니다. 처음엔 제 코드 어딘가가 잘못된 줄 알고 한참 헤맸는데, 의존성을 하나씩 끄고 켜며 이분 탐색(bisect)한 끝에 범인이 OCR 패키지의 특정 버전이라는 걸 확인했어요. 결국 호환되는 0.14 버전으로 고정해서 해결했습니다.
교훈: "최신 버전 = 안전"이 아니다. 새 OS가 나온 직후엔 더더욱. 이상 동작이 보이면 의존성부터 의심하고, 추측 대신 bisect로 범인을 특정하는 게 결국 제일 빠르다.
함정 2 — LLM이 항상 깔끔한 JSON만 주진 않는다
번역·요약 결과는 화면에 예쁘게 뿌려야 하니까, Claude에게 정해진 JSON 형식(번역문·요약·핵심 포인트·주의사항·할 일·면책 문구)으로 답해 달라고 했습니다. 대부분 잘 따라 주는데, 가끔은
```json같은 코드 펜스로 감싸서 주거나,- JSON 앞뒤에 설명 문장을 덧붙이거나,
- 입력이 길면 답이 중간에 잘려서 오기도 했습니다.
그래서 두 가지로 대응했습니다. 첫째, max_tokens를 넉넉하게(8192) 잡아 답이 잘리지 않게 했고, 둘째, 3단계로 점점 관대해지는 파서를 뒀습니다. 원문 그대로 파싱 → 코드 펜스 벗겨내고 파싱 → 본문에서 JSON 덩어리만 추출해 파싱. 그래도 안 되면 원문 텍스트를 그대로 보여 주는 폴백 화면으로 떨어집니다.
교훈: LLM 출력을 구조화 데이터로 쓸 거면, 모델이 형식을 살짝 어겨도 무너지지 않게 파싱을 설계해 두자. "잘 되겠지"는 사용자 앞에서 깨진다.
디자인은 '읽기에 방해되지 않게'
화려한 걸 의도하지 않았습니다. 거의 흑백에 가까운 잉크 톤, 얇은 산세리프 헤드라인, 직각 버튼, 헤어라인 디바이더 — 문서를 읽는 데 방해되지 않는 에디토리얼 톤을 목표로 했어요. 결국 이 앱의 주인공은 UI가 아니라 사용자의 문서니까요.
이런 분께 잘 맞습니다
- 영문·일문·중문 자료를 빠르게 훑어야 할 때
- 영수증·청구서를 텍스트로 정리하고 싶을 때
- 회의 노트나 화이트보드를 찍어서 요약만 받고 싶을 때
- 외국어 안내문을 즉시 이해하고 싶을 때
마무리
DOXcanner는 거창한 사업이라기보다, "이런 게 있으면 내가 쓰겠다" 싶어서 끝까지 만들어 본 결과물입니다. 작은 앱이지만 OS 호환성, LLM 출력 파싱, 프라이버시 설계 같은 현실적인 문제를 직접 부딪히며 푸는 게 즐거웠어요.
혹시 비슷한 필요가 있으셨다면 한 번 써 보시고, 피드백 주시면 정말 감사하겠습니다.
'써보니 좋아서' 카테고리의 다른 글
| 사용도 못 해보고... 카카두 엔드그레인 도마 (0) | 2024.08.02 |
|---|