ONDOKS(온독스)는 문서를 읽고, 구조를 복원하고, 사람이 검수한 결과를 업무 시스템에 전달하는 Document AI 플랫폼입니다.
글자 인식에서 시작해 표의 행·열과 병합 셀, 여러 페이지에 걸친 문서, 반복 양식의 필드까지 다루는 제품으로 확장했습니다.
개발의 중심에는 세 가지 문제가 있습니다.
문서마다 다른 입력 품질을 어떻게 처리할 것인가, 구조화 결과를 어떻게 검수하고 다시 사용할 것인가, 큰 문서와 여러 사용자가 함께 들어와도 어떻게 작업을 이어갈 것인가입니다.
서비스 범위 — 업로드에서 검수·전달까지
사용자는 작업 공간에서 이미지·PDF를 업로드하거나 카메라로 문서를 촬영합니다.
전체 글자를 읽을지, 레이아웃과 표를 분석할지, 필요한 영역이나 등록된 템플릿으로 값을 추출할지 선택합니다.
여러 파일과 ZIP은 배치로 처리하고, 긴 작업은 다른 화면으로 이동한 뒤에도 처리 현황과 완료 알림으로 이어 봅니다.
글자와 좌표를 추출하고 제목·본문·표·그림 등 영역을 구분합니다.
PDF는 페이지별 결과와 원본을 함께 확인합니다.
직접 그린 영역의 본문, 필드 하나의 값, 표 구조를 목적에 맞게 추출합니다.
반복 문서는 템플릿으로 저장해 다시 사용합니다.
페이지별 영역을 읽기 순서로 배치하고 문서 블록과 이어지는 표를 조립합니다.
차트의 표 변환도 설정에 따라 연결합니다.
원본과 결과를 비교하고, 검토가 필요한 항목을 고칩니다.
페이지별 수정·되돌리기와 템플릿 리포트의 검토 상태를 관리합니다.
편집용 Word, 검색·복사용 PDF, CSV, Markdown, XML로 결과를 전달합니다.
큰 이력은 필요한 페이지 범위만 내보냅니다.
REST API와 API 키를 제공하고, MCP 도구로 템플릿 조회·OCR·작업 상태·페이지 결과 조회를 연결합니다.
입력 처리 — PDF의 글자를 다시 읽지 않아도 되는 경우
스캔 PDF와 디지털 PDF를 같은 방식으로 처리하면 불필요한 추론과 오인식이 생깁니다.
디지털 PDF에는 이미 글자와 위치가 들어 있을 수 있습니다.
비레이아웃 OCR 경로에서는 텍스트 레이어의 문자 품질·좌표·최소 줄 수를 검사하고, 기준을 통과한 페이지의 전체 OCR을 생략합니다.
텍스트가 없거나 품질이 낮으면 OCR 경로로 돌아갑니다.
문서 복원은 레이아웃과 텍스트의 대응까지 확인해 디지털 추출·혼합·OCR 전략을 선택합니다.
표와 그림은 별도 구조 분석을 계속 수행합니다.
템플릿 경로에서도 전체 페이지의 글자는 앵커·가이드 탐색에 재사용하되, 지정 영역을 잘라 읽는 경로는 유지합니다.
텍스트 레이어가 있다는 이유만으로 모든 시각 분석을 건너뛰지는 않습니다.
10월에는 서로 다른 글꼴로 나뉜 글자 조각의 읽기 순서와 띄어쓰기를 보정했습니다.
날짜의 숫자와 ‘년·월·일’이 따로 떨어지거나 괄호 안 단어가 뒤로 밀리는 문제를 줄 단위 묶기와 실제 공백 확인으로 다룹니다.
글자 자체가 정확해도 조각을 잘못 이어 붙이면 업무 값이 틀린다는 문제를 처리한 것입니다.
촬영 이미지에는 방향 보정, 작은 기울기 보정, 저해상도 확대를 적용하는 전처리 경로가 있습니다.
원근 보정은 기본적으로 꺼 두고 필요한 환경에서 선택합니다.
보정된 이미지를 기준으로 OCR 좌표와 화면 표시 이미지를 맞춰, 회전 뒤 결과 상자가 원본의 다른 위치에 그려지는 문제도 다뤘습니다.
템플릿 영역 추출은 정규화 좌표를 보존하기 위해 같은 기하 변환 체인을 그대로 적용하지 않습니다.
브라우저 카메라는 문서 모서리 추정 모델과 기하 탐지 후보를 함께 검토하고, 연속 프레임에서 경계가 안정됐을 때 보정 미리보기를 만듭니다.
모델 자산을 사용할 수 없으면 기하 탐지로 동작합니다.
촬영 보정과 서버 OCR 전처리는 각각의 입력·좌표 계약을 갖습니다.
표와 문서 복원 — 셀에서 여러 페이지의 문서까지
표 복원의 핵심 문제는 병합 셀, 다단 헤더, 끊긴 격자선, 셀 경계에서 갈라진 텍스트입니다.
하나의 좌표 군집이나 고정 임계값으로 모든 표를 처리하기 어려워 후보 생성 → 비교·선택 → 보정 흐름을 설계했습니다.
현재 classic 경로는 단계별 파이프라인입니다. bbox 기반 기본 구조와 선분 기반 격자 후보를 만들고, 구조의 안정성과 텍스트 배치를 비교한 뒤 헤더·셀 결합·누락 구간을 보정합니다.
선택된 후보와 비교·되돌림 이력은 진단 메타데이터로 남깁니다.
후보가 여러 개라는 사실과 모든 후보가 동시에 실행된다는 것은 구분해야 합니다.
실제 실행은 설정된 단계 순서와 조건을 따릅니다.
정밀 표 처리에는 VLM 경로가 있고, 자동 선택 경로는 표의 복잡도와 결과 상태에 따라 처리 방식을 고릅니다.
PDF 문서 복원에는 Camelot 후보를 검토하는 경로도 있습니다.
이 선택지는 모델과 서빙이 준비된 배포에서 사용할 수 있습니다.
일반 문단이나 그림 안의 글자가 페이지 전체 표로 오인되지 않도록 표 판정 근거도 분리했습니다.
문서 복원은 표 하나의 정확도에서 한 단계 더 나아갑니다.
페이지의 제목·본문·그림·표를 블록으로 구성하고 읽기 순서를 정렬하며, 페이지를 넘어 이어지는 표의 세그먼트를 비교해 병합합니다.
결과에는 페이지별 내용과 문서 단위 조립 정보가 함께 남습니다.
표 구조를 얻지 못한 영역도 인식한 글자가 사라지지 않도록 보존합니다.
문서 전체를 VLM으로 처리하는 경로 역시 별도로 구현되어 있습니다.
기본 파이프라인과 결과의 성격·좌표 정보가 다르며, 배포 설정으로 비활성화할 수 있습니다.
차트 → 표도 별도 모델 설정과 실행 옵션이 필요한 기능입니다.
이들을 모든 설치에서 항상 켜진 기능으로 설명하지 않습니다.
반복 양식 — 위치가 밀려도 추출하고, 불확실하면 검토하기
템플릿은 정규화 좌표와 필드·가이드 정보를 저장합니다.
문서 안에서 값의 위치가 조금 달라지면 앵커와 가이드로 후보를 좁히고 위치를 보정합니다.
영역의 목적도 분리했습니다.
필드 하나의 값을 고르는 추출, 영역 안 글자 전체를 읽는 추출, 행·열을 복원하는 표 추출은 서로 다른 결과 계약을 갖습니다.
여러 페이지의 양식에서는 품목 수에 따라 합계나 서명이 뒤로 밀립니다.
가이드가 있는 필드는 설정된 탐색 깊이 안에서 후속 페이지를 확인하고, 가이드가 없는 위치 기반 필드는 엉뚱한 페이지의 값을 채우지 않도록 탐색 범위를 제한합니다.
날짜와 금액은 필드별 출력 형식도 지정할 수 있습니다.
추출 실패를 임의의 값으로 감추지 않는 것도 중요합니다.
표 구조화가 실패하면 영역의 글자와 검토 사유를 남깁니다.
사용자는 원본과 결과를 비교하고, LLM 보정이 설정된 경우 제안값을 검토·적용하거나 직접 수정합니다.
템플릿 리포트는 성공·검토 필요·검토 완료·실패·내보냄 상태를 구분합니다.
대용량 작업 — 처리와 결과 열람을 함께 나누기
수천 페이지 PDF 한 건이 워커 하나를 계속 점유하면 워커 수만 늘려도 그 파일은 빨라지지 않습니다.
설정을 켠 durable queue 구성에서는 큰 PDF를 페이지 범위로 나눠 여러 배치 워커가 처리한 뒤 순서대로 합칩니다.
각 묶음은 lease와 재시도 상태를 갖고, 재개할 때 완료된 묶음을 재사용합니다.
페이지 범위 분산 처리는 선택 기능이며 모든 배포의 기본값은 아닙니다.
짧은 단건 요청이 큰 작업 뒤에서 계속 기다리는 문제에는 우선순위와 대화형 요청용 워커를 둡니다.
추론 서빙이 일시적으로 불가능하면 작업 상태에 대기를 드러내고, 다시 사용할 수 있을 때 이어갑니다.
복구되지 않은 페이지 오류는 실패 페이지와 부분 실패 정보로 남깁니다.
작업 취소·재개와 SSE 진행 상태도 이 실행 흐름에 연결됩니다.
처리가 끝난 뒤에도 결과 전체를 한 번에 내려받지 않도록 설계했습니다.
이력과 완료 작업의 페이지 색인에서 요약을 먼저 읽고, 화면에 필요한 범위만 가져옵니다.
사용자가 한 페이지를 수정하면 전체 결과 본문을 다시 쓰는 대신 페이지 수정분을 별도로 저장하고 색인을 갱신합니다.
아직 받지 않은 페이지가 빠진 요약으로 전체 결과를 덮어쓰는 요청은 거부합니다.
페이지 이미지도 큰 응답에 계속 내장하는 대신 파일 저장소의 참조로 관리할 수 있습니다.
저장에는 객체 키를 남기고, 이력과 작업을 다시 읽을 때 접근 URL을 재발급합니다.
처리 성능뿐 아니라 오래된 이력의 재열람과 검수 내용의 보존까지 같은 문제로 다룬 것입니다.
결과 전달 — Word·검색 가능한 PDF·구조형 텍스트
내보내기는 화면과 API가 공통 변환기를 사용합니다.
10월 27일에는 Word와 검색 가능한 PDF를, 28일에는 이력의 페이지 범위 내보내기와 Markdown·XML의 블록 구조 출력을 추가했습니다.
| 출력 | 결과와 사용 조건 |
|---|---|
| Word (.docx) | 제목·문단·표·그림을 편집 가능한 문서로 구성합니다. 템플릿 결과는 필드 표로 만듭니다. 추출된 구조를 문서로 옮기는 기능으로, 원본의 편집 레이아웃을 그대로 복제하지는 않습니다. |
| 검색 가능한 PDF | 원본 페이지에 투명 텍스트 레이어를 얹어 검색·복사할 수 있게 합니다. 원본 PDF 또는 페이지 배경 이미지가 필요합니다. |
| CSV | 인식 결과나 템플릿 리포트를 행 단위 데이터로 전달합니다. 문서 블록의 배치보다 데이터 재사용에 맞춘 형식입니다. |
| Markdown·XML | 기본은 줄 단위 결과입니다. 레이아웃이 있는 이력의 블록 모드에서는 문서형 Markdown 또는 영역 유형·표 구조를 담은 XML을 만듭니다. |
| 페이지 범위 내보내기 | 페이지 단위 이력의 특정 파일·구간을 골라 받습니다. 큰 Word·PDF는 설정된 내보내기 한도에 맞춰 나눌 수 있습니다. |
REST API는 OCR·문서 복원·템플릿·작업·이력으로 역할을 정리했습니다.
웹 안에는 API 연동 가이드와 실제 서버에 요청을 보내는 플레이그라운드가 있습니다.
API 키 발급·폐기도 사용자와 관리자 화면에서 관리합니다.
MCP는 같은 API와 권한 검사를 재사용합니다.
에이전트는 등록된 템플릿을 확인하고 OCR을 요청한 뒤, 비동기 작업의 상태와 필요한 페이지를 도구로 가져옵니다.
페이지가 있는 완료 결과는 우선 요약으로 전달해 에이전트가 문서 전체를 컨텍스트에 한꺼번에 넣지 않도록 했습니다.
운영·개발 보조 도구는 별도 설정으로 구분하며, MCP 사용 가능 여부도 납품 구성에 따릅니다.
운영·납품 — 실행 역할과 보호 범위를 명확히 하기
FastAPI API와 Next.js 웹을 통합 이미지로 제공하면서, 작업 소비와 모델 추론은 별도 역할로 분리할 수 있게 했습니다.
고가용성 구성에는 PostgreSQL, Redis 기반 작업 큐, S3 호환 파일 저장소를 연결합니다.
10월에는 배포 매니페스트와 납품 번들의 저장소를 SeaweedFS로 전환하고, 기존 MinIO 데이터의 이전 경로도 추가했습니다.
실제 설치별 자원과 기능은 납품 설정으로 결정합니다.
운영자에게는 사용자 승인·권한·API 키 관리, 가입 허용 도메인과 메일 인증 정책, LLM·프롬프트 설정, 공지·문의 게시판을 제공합니다.
사용 현황은 활성 사용자와 처리 요청·파일·페이지 수를 기능별·사용자별·웹/API 키/MCP 경로별로 구분합니다.
요청 ID와 사용자 식별을 잇는 로그, 큐 정체·서빙 상태·처리 지연 지표로 장애를 추적합니다.
보호 납품은 암호화된 모델 자산과 서명·봉인된 payload, Cython으로 컴파일한 핵심 코드를 조합합니다.
비루트 실행, 읽기 전용 파일 시스템, 임시 메모리 파일 시스템에서의 모델 복호화로 평문 자산과 소스의 노출을 줄입니다.
고객별 기능·모델·계정·서빙 구성을 빌드와 기동 단계에 연결했습니다.
이 보호의 목적은 저장된 파일의 단순 추출과 일반적인 런타임 접근의 비용을 높이는 데 있습니다.
호스트의 관리자 권한을 가진 상대에게 절대적인 모델 비밀을 보장하는 것으로 설명하지 않습니다.
화면·API·소스의 연결
API 경로는 애플리케이션 기준입니다.
게이트웨이에서는 배포 설정에 따라 /api 접두사가 붙습니다.
표의 기능은 선택된 납품 기능과 권한에 따라 노출됩니다.
| 사용자 기능 | 화면·API | 핵심 구현 |
|---|---|---|
| 문자·레이아웃·영역 추출 | 작업 공간 · /ocr/text, /ocr/layout, /ocr/regions | app/invision/ocr/, layout/, table/ |
| 문서 복원·차트 변환 | 문서 복원 · /ocr/document, /ocr/chart2table | app/invision/parser/, chart/ |
| 처리 현황 | 처리 현황 보드 · /jobs, /jobs/{id}/events, /jobs/{id}/pages | app/invision/tasks/, workflows/, app/worker_entrypoints.py |
| 검수·이력·내보내기 | 이력 상세·템플릿 리포트 · /histories, /ocr/results/render | app/history/, app/invision/shared/result_export/ |
| 템플릿 재사용 | 템플릿 편집·라이브러리 · /templates | app/templates/, web/src/components/template/ |
| 외부·에이전트 연동 | 연동 가이드·플레이그라운드 · /mcp | app/mcp/, web/src/app/(protected)/guide/, playground/ |
| 사용 현황·접근 관리 | 관리자 사용 현황·가입 정책·API 키 관리 | app/usage/, app/admin/, app/auth/ |
| 설치·운영 | 단일 런타임·역할 분리 배포·보호 납품 | delivery/, docker/, deploy/ |
개발 과정의 평가 체계와 현재 확인 범위
초기 표 복원 개발에서는 HTML table 정답을 기준으로 TEDS·TEDS-S, 셀 매칭 F1, 셀 내부 CER, 행·열 일치를 함께 평가하는 벤치마크 콘솔을 구축했습니다.
구조와 글자 오류를 분리해 보고, 비교 방법과 실패 사례·회귀 세트로 개선을 점검한 경험입니다.
이 연구용 벤치마크·실험 화면과 관련 실행 도구는 2026년 9월 29일 정리했습니다.
문서 복원은 정식 기능으로 남겼습니다.
현재 제품 기능과 과거 연구 도구를 구분하며, 과거 데이터셋의 점수를 현행 버전의 정확도나 다른 데이터셋 대비 개선율로 제시하지 않습니다.
현재 저장소에는 PDF 텍스트 레이어·혼합 글꼴 읽기 순서, 문서 복원, 페이지 분산 처리, 페이지 색인·수정, 내보내기, MCP 인증·결과 조회, 가입 정책·사용량 집계에 대한 테스트가 있습니다.
실서버 API·화면 QA 스위트도 마련되어 있습니다.
자동 QA 실행 여부는 CI 설정에 따르며, 이번 글 갱신 시점의 저장소 기본 스위치는 꺼져 있습니다.
이 글의 기능 설명은 2026년 10월 28일 소스와 테스트 정의를 대조한 범위입니다.
실제 설치별 활성 기능·가용성·처리 속도·최신 모델 정확도는 해당 환경의 실행 결과로 확인해야 합니다.
코드에 있는 기능과 이번 검수에서 재실행한 시험 결과를 혼용하지 않습니다.
기여와 성과
백엔드·프론트엔드·표 복원 엔진·벤치마크·보호 빌드의 초기 설계와 구현부터, 문서 복원·비동기 작업·검수·업무 연동으로의 확장을 단독 수행했습니다.
관련 기술 특허 출원과 K사 솔루션 공급 계약 수주를 프로젝트 성과로 기록했습니다.
표의 셀을 복원하는 기술에서 출발해 입력 품질, 문서 조립, 사용자 검수, 데이터 전달, 설치 후 운영까지 연결하는 시스템을 만들고 있습니다.
각 단계의 결과와 실패 상태를 다음 단계가 사용할 수 있는 계약으로 정리하는 것이 이 프로젝트에서 지속해서 해결하는 과제입니다.