Document AI로 문서 검토 한방에 끝내기

Document AI로 문서 검토 한방에 끝내기

시작하며

안녕하세요. 카카오페이손해보험 플랫폼기술팀의 달리오입니다. 이번 주제는 제가 if(kakaoAI)2024에서도 공유했던 내용인데요. 발표 시간 제약 때문에 미처 전달하지 못했던 기술적인 내용을 좀 더 깊게 공유해 보고자 이번 글을 작성합니다.

🔗 발표 영상 보러 가기: 문서 검토는 이제 Document AI로 한방에!

보험사에서 다룬 기술이기에 보험 이야기를 빼놓을 수 없을 것 같은데요. 아마 독자분들도 한 번쯤은 보험사에 보험금 청구를 해보셨을 것 같습니다. 그때마다 어떤 경험이었나요? 서류를 꼼꼼히 챙겨서 보험사에 제출했음에도 실제로 보험금을 입금받기까지 길게는 하루 이상 걸려보신 경험이 있으실 거예요.

그 이유는 사실 제출한 문서를 사람이 검토하기 때문인데요. 카카오페이손해보험에서는 문서 검토를 Document AI가 대신하기 때문에 고객분들의 기다리는 시간은 10분을 넘어가지 않습니다. 이번 글에서는 이 Document AI를 어떻게 구현했는지를 다루려고 합니다. 문서 기반의 비즈니스를 갖고 있어서 업무 효율화를 검토하시는 분들에게 특히 더 도움이 될 것 같습니다.

Document AI가 무엇인가요?

본격적인 구현 방법을 말씀드리기에 앞서 Document AI가 무엇인지 정확한 정의를 알아보겠습니다. Document AI는 기계 학습과 자연어 처리 등의 기술을 활용하여 문서의 내용을 자동으로 인식하고 처리하는 기술입니다. 쉽게 표현하자면 ‘문서 내에서 원하는 정보를 자동으로 찾는 기술’ 정도로 정의할 수 있습니다.

Document AI 구성 Task

Document AI는 문서를 이미지 형태로 입력받아서 문서 내용을 Key-Value 형태의 데이터로 출력하는 기술입니다. 문서 이미지에서 정제된 Key-Value 형태의 데이터를 만들기까지는 몇 가지 절차를 거쳐야 하는데 각 절차를 Task라고 표현합니다. 어떤 Task가 필요한지는 문서마다 다르고 개발자마다 다르기 때문에 이번 목차에서는 일반적으로 자주 사용되는 Task들만 소개해 보려고 합니다.

1. OCR(광학 문자 인식)

아마 OCR은 이미 익숙하실 것 같은데요. 문서 내 문자를 인식하는 Task입니다. 일반적으로 알려진 OCR 모델은 이미지에서 텍스트의 위치를 검출하는 Detection과 검출한 위치의 문자를 인식하는 Recognition으로 구성되어 있습니다. 그래서 OCR 모델의 추론 결과에는 인식한 텍스트와 함께 텍스트의 위치를 표현한 Bounding Box가 함께 제공되는 것이 일반적입니다. 그러나 최근 AI 분야의 트렌드인 Transformer 기반으로 만들어진 TrOCR처럼 Detection은 없고, Recognition만 제공하는 경우도 있습니다.

2. Layout Analysis(구조 분석)

Layout Analysis는 문서의 구조를 분석하는 Task로 제목, 표, 본문 등 문서를 구성하는 영역들을 구분하여 검출합니다. 문서에서 찾으려는 정보가 특정 영역에만 있다면 효과가 큰 Task입니다. 가령, 원하는 정보가 특정 표에 담겨있다면 Layout Analysis로 해당 표만 찾아서 OCR을 수행하면 되기 때문에 더 효율적이겠죠.

3. Classification(분류)

Classification은 대상 이미지가 어떤 문서에 해당하는지를 분류하는 Task인데요. 이 Task는 주로 아래의 상황에 활용할 수 있습니다.

  • 여러 개의 문서가 업로드된 경우 비즈니스 요구에 맞는 문서만 필터링하기.
  • 고객이 필수 문서를 누락한 경우 업로드 단계에서 알려주기.
  • 문서별로 로직이나 모델이 다른 경우 분기의 기준으로 사용하기.

4. Parsing(구문 분석)

Parsing은 다른 Task의 결과들을 종합하여 문서의 인식 내용을 서비스 요구 사항에 맞게 Key-Value 형태로 만드는 Task입니다. 예를 들어, Classification에서 사업자등록증으로 분류한 경우 OCR로 인식한 텍스트 중 {3자리 숫자}-{2자리 숫자}-{5자리 숫자}의 패턴이 있다면 사업자 번호에 해당하겠죠. 이렇게 인식한 텍스트의 의미까지 파악하여 "사업자번호": "{3자리 숫자}-{2자리 숫자}-{5자리 숫자}"와 같이 Key-Value 형태로 만드는 것이 Parsing 태스크입니다.

카카오페이손해보험에서는 문서를 어떻게 인식하나요?

Document AI가 무엇이고, 이를 구성하는 Task까지 알아봤는데요. 이제는 저희 회사의 Document AI가 어떻게 동작하는지를 소개해 보겠습니다. 카카오페이손해보험에서는 휴대폰 보험 서비스를 통해 고객의 휴대폰이 파손된 경우 수리비를 보상하고 있습니다. 수리비 증빙을 위해서 제출하는 서류 중에는 수리비 영수증이 포함되어 있는데요. 이 수리비 영수증을 통해 구현 방법을 소개하겠습니다.

수리비 영수증 소개

저희는 수리비 영수증에서 수리처 / 발행일 / 결제금액 이렇게 3개의 정보를 인식해야 합니다. 수리처는 삼성전자서비스라는 고정값이고 발행일과 결제금액은 일정 포맷을 갖는 가변값입니다.

수리비 영수증을 인식하는 프로세스

먼저 수리비 영수증 인식을 위해 어떤 Task들을 거치는지 살펴보겠습니다. 수리비 영수증 인식에는 Edge Detection > Layout Analysis > OCR > Parsing 이렇게 4개의 Task를 순차적으로 수행하여 최종 인식 결과를 생성하도록 구현했는데요. 여기서 Parsing은 규칙 기반의 로직으로 수행하도록 구현했고, 나머지 3개의 Task는 학습시켜 둔 모델 기반으로 수행하고 있습니다. 그럼 각 단계별로 어떤 역할을 수행하는지 설명해 보겠습니다.

1단계. Edge Detection(테두리 검출)

Edge Detection은 Document AI에서 일반적인 Task는 아니어서 이전 목차에서는 언급하지 않았는데요. 이 Task는 이미지 내에서 문서의 테두리를 검출하여 더 정확한 문서 인식을 위해 이미지를 전처리하는 게 최종 목적입니다. 사실 Edge Detection 모델은 문서의 테두리에 해당하는 다수의 점들을 x, y 좌표 값으로 표현하는 것에 그치는데요. 저는 추가적으로 모델이 알려준 x, y 좌표 값들을 바탕으로 이미지에서 불필요한 배경을 제거하고 나아가서 문서가 기울어져 있는 경우 이를 직각으로 세워주는 로직을 구현했습니다. 여기서 기울어진 이미지를 직각으로 세우는 것은 OpenCV가 제공하는 Perspective Transform을 사용하여 구현했습니다.

2단계. Layout Analysis(구조 분석)

앞서서 Layout Analysis는 문서의 구조를 분석하는 Task라고 설명드렸습니다. Layout Analysis 모델이 영수증 내에서 제가 원하는 3개의 정보가 적힌 위치를 잘 찾을 수 있도록 학습시켜 뒀는데요. 위치를 찾는 것과 함께 해당 영역의 이름이 무엇인지까지 알려줘서 이후에 Parsing 하기가 수월합니다. 그리고 위치 값과 함께 confidence라는 값도 알려주는데 이 값의 개념을 잠시 짚고 넘어가겠습니다.

잠깐! Confidence란?

  • 모델이 추론한 결과에 대해서 얼마나 확신하는지를 나타내는 지표입니다. (=자신감)
  • 보통 0과 1 사이의 실수로 표현하고 값이 클수록 추론한 결과에 대해서 더 확신한다는 의미입니다.
  • 모델의 추론 결과를 신뢰하는 기준으로 사용합니다. (예 : 0.7 이상인 경우에만 신뢰)

3단계. OCR(광학 문자 인식)

다시 인식 프로세스로 돌아오겠습니다. 3단계인 OCR에서는 Layout Analysis가 검출해 준 각 영역에 어떤 텍스트가 담겨있는지를 인식하는데요. OCR에서도 텍스트 인식에 더해 앞서 설명드린 Confidence 값이 함께 제공되어 신뢰 기준을 정할 수 있습니다.

4단계. Parsing(구문 분석)

이제 모델로 추론하는 과정은 모두 끝났습니다. Layout Analysis 추론 결과와 OCR 추론 결과를 합쳐서 Key-Value 형태의 최종 결과를 로직을 통해 만들어보겠습니다. 결제 금액을 예시로 보면 Layout Analysis가 AMOUNT(총액)라는 태그명으로 해당 정보의 위치를 찾아줬기 때문에 이 영역에 OCR을 수행하면 화폐 형태의 텍스트가 인식되겠죠. 그런데 결제 금액은 영수증마다 다르기 때문에 정규표현식인 \d+,\d+{3} 파싱을 하여 "amount": 80,000라는 결과를 만들 수 있습니다.

구현하면서 고민했던 것은 무엇이었나요?

앞서 소개해 드린 인식 과정은 해피 케이스 기준으로만 설명해 드렸는데요. 이번에는 실제로 서비스를 운영하며 발생할 수 있는 예외 케이스를 마주하며 추가로 고민했던 내용들을 소개하겠습니다.

1. 회전된 이미지 보정하기

먼저, 2단계인 Layout Analysis 태스크를 구현할 때 있었던 일인데요. 고객분들이 업로드한 영수증 이미지는 대부분 세로 정방향인데, 간혹 이미지가 가로로 회전되어서 업로드된 경우들도 있습니다. 이런 경우 Layout Analysis 모델은 어떻게 인식할까요?

가로로 회전된 이미지는 학습시키지 않았기 때문에 모델은 일부 객체를 검출하지 못하거나 검출하더라도 낮은 confidence 값을 부여하여 비정상적인 추론 결과를 제공합니다. 그래서 영수증 이미지를 90도, 180도, 270도로 모두 회전시켜서 모델이 정상적으로 추론할 때까지 입력해 봅니다. 만약 90도를 회전시켰더니 정상적인 추론 결과가 나왔다면 이 이미지의 원본은 -90도 상태였다는 것을 경험적으로 알게 되어 보정할 수 있습니다. 이런 방식으로 회전된 영수증 이미지여도 Layout Analysis가 정상 추론하도록 구현했습니다.

2. 수리비 영수증만 필터링하기

한 단계 더 들어가서 회전된 영수증 이미지가 아닌 아예 다른 문서의 이미지라면 어떻게 대응할까요? Layout Analysis는 인식 과정의 2단계이기 때문에 아직 이 이미지가 어떤 문서인지는 알 수 없습니다. 그래서 이것 역시 회전된 이미지를 보정할 때와 같이 90도, 180도, 270도 세 가지 각도로 회전하여 분석을 시도해 보는데요.

그런데 이번에는 영수증이 아닌 아예 다른 문서이기 때문에 세 가지 각도로 회전시켜 봐도 모두 비정상적인 분석 결과가 나옵니다. 이 결과를 토대로 현재 인식하고 있는 이미지는 영수증이 아니라고 판단할 수 있기 때문에 이후 프로세스는 진행하지 않습니다. 즉, 영수증 이미지가 아닌 경우 필터링이 가능한 것이죠.

3. OCR에서 오인식한 문자 보정하기

다음은 4단계인 Parsing을 구현할 때의 일이었습니다. Parsing의 앞 단계인 OCR에서 문자를 오인식한 경우 이것을 보정하는 방법에 대해 고민했었습니다. 가령, 수리처 정보인 삼성전자서비스의 전이란 글자를 진으로 인식하고 서라는 글자를 아예 인식하지 못하는 건데요. 단 두 글자만 틀렸는데 수리처 정보가 없다고 판단하기에는 너무 아쉽겠죠. 그래서 약간의 오차를 허용하기 위해서 레빈슈타인 디스턴스라는 알고리즘을 적용했습니다.

이 알고리즘은 편집 거리 알고리즘 중 하나로 두 텍스트의 유사도를 판단할 때 사용합니다. 원리는 간단한데요. 비교 대상의 텍스트와 동일해지려면 몇 번의 수정이 필요한지를 카운팅 하고, 그 횟수를 거리로 표현하는 방식입니다. 이 알고리즘을 예시에 적용해 보면, 진과 서 두 글자만 수정하면 되기 때문에 거리는 2입니다. 이 거리가 특정 수치 이하면 동일한 텍스트로 간주하는 규칙을 적용하여 약간의 오차는 허용하고 있습니다.

어떤 모델을 활용했나요?

이제 마지막으로 제가 어떤 모델들을 활용했는지 소개해 드릴게요.

YOLO(You Only Look Once)

먼저, Edge Detection과 Layout Analysis에는 YOLO라는 모델을 사용했습니다. 사실 YOLO는 실생활에서의 객체들을 탐지(Object Detection) 하기 위한 목적으로 만들어졌습니다. YOLO가 제공하는 기능에는 Segment와 Detect 기능이 있는데요. 저는 Segment를 Edge Detection에 활용하고, Detect를 Layout Analysis에 활용했습니다. Segment는 객체를 검출할 때 다각형으로 정교하게 객체를 검출하는 반면, Detect는 객체를 사각형으로만 검출할 수 있다는 차이가 있습니다.

나아가서 학습 데이터의 차이에 대해서도 말씀드리자면, Edge Detection에 사용되는 Segment는 영수증뿐만 아니라 문자가 인쇄된 종이라면 모두 검출하도록 학습시켰습니다. 그래서 학습 데이터도 특정 문서가 아닌 문자가 인쇄된 종이와 배경이 있는 이미지라면 모두 활용할 수 있고요. 이렇게 학습시킨 모델은 다른 문서를 인식할 때도 재사용하고 있습니다.

반면 Layout Analysis에 사용되는 Detect는 영수증에 특화된 구조를 분석하는 것이기 때문에 학습 데이터 역시 영수증 이미지만을 활용했습니다.

TrOCR(Transformer-based OCR)

다음으로 OCR 태스크에는 Transformer 기반인 TrOCR을 활용했습니다. TrOCR은 HuggingFace에 공개된 사전 학습 모델들의 정확도가 우수하여 바로 서비스에 쓸 수 있는 모델들도 있습니다. TrOCR의 경우 Transformer 기반인 만큼 End-to-End 학습 방식을 갖고 있는데요. 이 특징 덕분에 타 OCR 모델 대비 학습 방법이 간편하여 운영하기에도 효율이 좋습니다.

모델 운영을 위한 서버 비용

사실 AI 서비스라고 하면 ‘운영 비용이 많이 들면 어쩌지?‘라는 비용 걱정을 빼놓을 수 없습니다. 그런데 걱정이 무색할 정도로 YOLO와 TrOCR을 실행하는 서버는 시간당 800원짜리 서버면 충분했습니다. 저희는 AWS의 g4dn.xlarge VM 장비를 사용하고 있는데 해당 서버 비용이 시간당 800원입니다. 당연하겠지만 안정적인 운영을 위해서 페이즈별로 서버를 구분해야 할 텐데요. 저희는 개발, 베타, 운영 총 3개의 페이즈를 운영하고 있어서 곱하기 3을 하면 됩니다. 즉, 시간당 2,400원이면 AI 기반의 문서 인식 기술을 개발할 수 있다는 것이죠.

마치며

보험 서비스의 최대 병목 구간인 문서 검토를 Document AI로 효율화한 사례에 대해서 소개해 드렸는데요. 사실 저는 AI를 전공하지 않은 백엔드 개발자입니다. 본문의 내용들은 제가 약 7개월간 구현한 사례인데요. 작금의 시대는 백엔드 개발자도 AI 서비스를 개발할 수 있는 시대라고 느꼈습니다. 이미 참고하고 활용할 수 있는 AI 관련 생태계들이 잘 갖춰져 있어서 서비스를 만들기에는 충분했습니다. 혹시 저와 같이 비전공자지만 AI 기반의 서비스 개발에 관심이 있으시다면 이번 글을 통해 과감히 도전해 보시라고 말씀드리고 싶네요. 감사합니다!

참고 자료

dalio.ray
dalio.ray

백엔드 엔지니어지만 보험 서비스에 필요한 AI 서비스를 개발하고 있는 달리오입니다.