# [SRP AX] SchoolNote OCR 

강남의 대입 컨설팅 업체의 전반적인 업무 플로우에 AI를 적용하는 업무를 맡게 되었다.

지인이 TA로 일하던 업체였고, 지인이 개인적으로 사용하던 AI 툴에 관심을 보이셨고, AI 도입에 대한 의지가 있으신 상태셨다. 몇차례의 원장님과의 미팅과 실무자 미팅을 통해 여러 프로젝트를 시작했다.

### 도입 목적

업무 플로우는 여러 방향이었고 진행할 수 있는 프로젝트는 다양했지만, 가장 먼저 해야할 일은 데이터를 잘 정리하여 AI와 소프트웨어에서 사용하기 좋은 형태로 만드는 작업이라고 판단했다.

비정형 데이터이고, 활용 가치가 높으며, 독점적 내부 데이터가 우선순위에 있었고, 이 업체에서는 수강생,상담생들의 생활기록부가 그러한 데이터였다.

![https://i.imgur.com/G5N2K2k.png](https://i.imgur.com/G5N2K2k.png)

기존에 해당 데이터는 다음과 같이 관리 및 활용되고 있었다.

- 종이문서, 또는 그 문서를 찍은 이미지, 또는 pdf 원본

- 구글드라이브에 일괄적으로 관리. 문서명으로 인덱싱, 검색

- 내용기반 검색은 일절 불가능. 컨설턴트의 기억력에 의존하여 유사 사례 조회

이 생활기록부가 중요한 데이터인 이유는 다음과 같다.

- 컨설팅 학생의 모든 것이 담겨있는 근원적 데이터이다.

- 이 데이터를 기반으로 컨설턴트의 분석, 상담, 수업이 이루어진다.

- 이 업체의 해자는 이 기초데이터에 대한 컨설턴트의 노하우가 담긴 커멘트와 평가 그리고 추후 action 제안이다.

그래서

문서,이미지,pdf 로 흩어져있던 데이터를 규격화된 markdown으로 포맷팅하고, 근원 데이터베이스를 축적하는 시스템을 제안했다.

### 기술 파이프라인

OCR 모델은 Mistral 의 OCR 3 모델을 사용했다.

![https://i.imgur.com/Co8zAJO.png](https://i.imgur.com/Co8zAJO.png)

업스테이지의 Document AI를 포함하여, gemini 등 다양한 모델을 테스트해봤을 때, 체감상 가장 정확도가 높았고, api 비용도 2$ / 1000page 로 저렴하여 이 모델을 선택했다.

다만, OCR 모델을 거치더라도 이 데이터를 그대로 활용하기는 어려웠다.

1. 여전히 OCR 모델의 한계상 오타가 있다.

2. 문서의 쪽마다 있는 머릿말 꼬릿말, 페이지와 같은 불필요한 데이터들이 같이 파싱된다.

3. cell이 병합된 데이터의 경우, 셀 구조까지 OCR이 복원해주지는 않았다.

4. 생기부 전체 문서가 아니라 일부만 들어온 경우, 어떤 영역인지 파악할 수 없다.

그래서 raw-ocr 데이터를 LLM으로 한번 정제하는 과정을 추가했다. 

LLM 이 단계에서 오타 교정, 머릿말&꼬릿말 등 불필요한 노이즈 제거, 셀 병합 구조를 마크다운 구조로 변환, 생기부 문서 양식을 기반으로 현재 영역 파악 및 구조화의 작업을 수행한다.

![https://i.imgur.com/HtYZeOo.png](https://i.imgur.com/HtYZeOo.png)

문서의 사이즈가 대체로 유사했고, 한번 처리에 대략 70000 토큰 정도를 출력해야한다. 

따라서 output token 제한이 길고, 오류를 refine 하기에 적당히 똑똑한 모델들을 시도해보았다.

1. gpt 5 : 변환업무는 잘 수행하지만, 가격이 문제였다. 생기부 하나 변환하는데 500원... 단순한 업무를 수행하는거 치고 너무 비싼도구를 사용한다.

2. gemini flash / gpt mini 계열 : spec 상 출력 토큰 수는 문제가 없었지만, 길어질 수록 멍청해졌다. 제시한 structured output 을 지키지 않고, 대화형 assistant 어조의 답변이 섞여들어가 퀄리티가 마음에 들지 않았다.

3. deepseek r2 : GPT보다 제시한 규칙을 훨씬 잘 지키면서, output token 제한도 크고, 말이 안되는 가격($0.42 / 1M token output. gpt 5는 $15.00 / 1M token output. 30배 차이)

중국 모델을 사용하는게 찜찜하고, 이 문서에는 개인정보가 포함되어 있으므로, LLM에 보내기 전, 마스킹 전처리를 해야한다고 판단했다. 생년월일, 주소, 신상 등 우리가 몰라도 되는 정보들을 Rule-based python code로 마스킹 후에 LLM의 Input 으로 전달했다.

### 속도가 느리다

사실 방금 적용한 방법은 너무 원시적이다. 전체 텍스트 중 수정해야할 토큰은 많지 않다.(대략 5%~10% 사이)

이걸 수정하고자 수만 토큰을 다시 출력하는건 비용 낭비이다. (사실 deepseek가 있어서 비용은 큰 문제가 되지는 않았다.)  비용도 문제지만, 처리 시간도 문제였다. 하나의 문서를 처리하는데 약 3분 정도 걸렸다.

전체 재출력이 아닌 다른 방법론들을 실험해봤다.

### 1. diff 만 출력하기

대부분의 코딩 에이전트도 소스코드의 모든 부분을 출력하지 않는다. git 변경사항 처럼 삭제된 내용, 새로 추가된 내용의 변화만을 LLM이 output으로 출력하게 하고, 그 적용을 로직으로 합치면 되지 않을까? 시도했다.

유사 사례 : [https://waleedk.medium.com/the-edit-trick-efficient-llm-annotation-of-documents-d078429faf37](https://waleedk.medium.com/the-edit-trick-efficient-llm-annotation-of-documents-d078429faf37)

(다시 찾아보니 코딩 에이전트들도 full generation을 한다음, Diff 를 계산하여 UX적으로 보여주는 경우가 더 많다고 한다.)

### 2. 동일한 부분은 skip 키워드로 치환

전체 내용을 다 출력하는게 아니라 기존 출력문과 일정 시퀀스 이상 동일하게 출력하고 싶은 경우 skip 키워드로 치환하게 프롬프팅하는 시도를 해봤다.

관련된 적용 시도와 벤치마크 등을 조사해봤을 때, 

![https://i.imgur.com/1g025V7.png](https://i.imgur.com/1g025V7.png)

1. edit 위치 정확도가 중요하고 anchor로 사용할 인덱스가 있어야한다. (안 그러면 Edit command ambiguity 문제 발생)

2. Plain text 에서 좋은 성과를 내고, 구조적으로 복잡한 table 이나 json, md 에서는 취약했다. 

3. output 을 local에 대해서 출력하니 global consistency 가 떨어진다.

아쉽게도 두 방법론 모두 여러번 시도해보았지만 full-Generation 에 비해 정확도가 낮았고, 테이블을 마크다운으로 변환하는 작업도 깨지는 경우가 많았다. 단순하다고 생각했던 

아쉽게도 두 방법론 모두 full 출력에 비해 정확도가 낮았고, 실시간성보다는 정확도가 더 높은게 중요했기에 MVP에서는 기존 방법론을 유지했다.

### 느린 속도 받아들이기

유저 경험 측면에서도 개선이 필요했다. 수 초 안에 끝나는 작업의 경우 스피너로 로딩을 구성하면 되지만, 장기 

백엔드에서 작업을 비동기 백그라운드로 실행하고, job_id 기준으로 상태를 추적하도록 구성했다.

작업 상태와 파일별 진행률은 JSON 기반 Job Store에 저장하여 새로고침 이후에도 처리 상태를 복구할 수 있게 했다.

프론트엔드는 Server-Sent Events(SSE)로 진행 상황을 실시간 구독하고, 연결이 끊기면 polling 방식으로 자동 전환하도록 구현했다. 백엔드는 OCR, 개인정보 마스킹, 마크다운 변환, 파일명 생성 같은 단계별 상태를 갱신하여 프론트엔드에 전달했다.  LLM 처리 구간은 실제 API가 퍼센트를 제공하지 않기 때문에, 텍스트 줄 수를 기준으로 예상 처리 시간을 계산해 진행률을 시뮬레이션했다.

### 이 데이터를 어디에 연결할건데

1. 종합 SaaS의 학생 데이터에 연결
1. 기존 프로세스에서는 이미지로 된 생기부 내용에서 커멘트를 작성하기 위해서 원문을 찾아 일일이 타이핑 했다. 
1. 이제는 이 데이터는 학생에 매칭되어 상담 컨설턴트, 해당 학생을 지도하는 TA, 선생님, 학생 본인이 필요할 때 손쉽게 접근 가능해졌다.

2. 자연어 기반 검색 데이터베이스로 활용.
2. 향후 프로젝트로 지능형 생기부 사례 검색 시스템을 기획 중이다. 자연어 기반으로 찾고 싶은 내용을 입력하면 에이전트가 검색할 쿼리를 생성하고, 이걸 이번에 구축한 생기부 마크다운 DB에서 RAG로 불러와 사례를 찾아 줄 수 있다.

3. 생활기록부 분석 에이전트의 학습 자료로 활용 (동의자에 한하여)
3. 업체의 핵심 비즈니스 모델인 생활기록부 분석 및 평가를 대신하는 에이전트를 만들기 위해서는 데이터셋이 필수적이다. 학습 데이터셋과 추론 대상 데이터의 전처리 프로세스로 활용할 수 있다.

For the site tree, see the [root Markdown](https://slashpage.com/yejun-cheon.md).
