본문 바로가기
Azure AI Services Engineering/Document

[ Azure AI Services #5 ] [실습] Document Intelligence REST API와 Gradio로 문서 분석 앱 만들기

by yunalee-dev 2026. 6. 19.

이번 글에서는 Azure AI Document Intelligence를 사용해 PDF와 이미지 문서를 분석하고, 그 결과를 Gradio 웹 화면에서 확인하는 실습을 정리해보겠습니다.

이전 단계에서 Document Intelligence Studio를 통해 문서 분석 결과를 직접 확인했다면, 이번 글에서는 Python 코드로 REST API를 호출하고, 마지막에는 사용자가 파일을 업로드할 수 있는 간단한 웹앱까지 만들어보겠습니다.

이번 글의 핵심
Document Intelligence는 문서 안의 텍스트와 표 구조를 읽어 JSON으로 반환하고, Gradio는 이 기능을 사용자가 쉽게 테스트할 수 있는 웹 화면으로 만들어줍니다.

전체 코드는 아래 GitHub 저장소에서 확인할 수 있습니다.

https://github.com/yunalee-dev/Azure-AI-Services-Labs

 

GitHub - yunalee-dev/Azure-AI-Services-Labs

Contribute to yunalee-dev/Azure-AI-Services-Labs development by creating an account on GitHub.

github.com



1. 실습 목표

이번 실습의 목표는 단순히 “Azure API를 한 번 호출해봤다”에서 끝나는 것이 아닙니다. 최종 목표는 사용자가 PDF나 이미지 파일을 업로드하면, Azure Document Intelligence가 문서를 분석하고, 그 결과를 웹 화면에서 확인할 수 있는 작은 문서 분석 앱을 만드는 것입니다.

일상적인 상황으로 비유하면 이렇습니다. 사용자가 문서를 제출하면, AI 비서가 문서를 읽고 텍스트와 표를 정리해서 결과지로 돌려주는 구조입니다. 여기서 Document Intelligence는 문서를 읽는 AI 비서이고, Gradio는 사용자가 문서를 제출하고 결과를 확인하는 창입니다.

실습 항목 설명
REST API 호출 Python requests로 Azure Document Intelligence API 호출
Read 모델 문서 안의 텍스트를 OCR로 추출
Layout 모델 문서의 텍스트, 표, 행과 열 구조 추출
Invoice 모델 청구서나 영수증에서 주요 필드 추출
Gradio 앱 파일 업로드, 모델 선택, 분석 결과 출력을 웹 화면으로 구현

 

2. 전체 프로젝트 구조

이번 실습에서는 Document Intelligence 실습을 하나의 폴더 안에서 단계별로 나누어 구성했습니다. 폴더를 이렇게 나누면 Studio 실습, REST API 실습, 웹앱 실습이 서로 섞이지 않아서 나중에 GitHub에 올렸을 때도 구조를 이해하기 쉽습니다.

azure-ai-services-labs
├── .env
├── .env.example
├── requirements.txt
├── 01-document-intelligence
│   ├── 01-studio-practice
│   ├── 02-rest-api
│   │   ├── common.py
│   │   ├── analyze_read.py
│   │   ├── analyze_layout.py
│   │   ├── analyze_invoice.py
│   │   └── README.md
│   ├── 03-gradio-app
│   │   ├── app.py
│   │   └── README.md
│   ├── notebooks
│   ├── outputs
│   ├── sample-data
│   │   ├── database_basic.pdf
│   │   └── receipt.jpg
│   └── README.md
└── README.md

이 중에서 이번 글의 핵심은 02-rest-api03-gradio-app입니다. 먼저 REST API로 문서 분석이 제대로 되는지 확인한 다음, 그 기능을 Gradio 웹앱에서 재사용하는 방식으로 진행했습니다.

파일 구조

폴더 역할
01-studio-practice Azure Document Intelligence Studio에서 직접 실습한 내용 정리
02-rest-api Python으로 REST API를 호출하는 코드
03-gradio-app 파일 업로드와 결과 출력을 제공하는 웹앱
sample-data 분석에 사용할 PDF, 이미지 샘플 파일
outputs 분석 결과 JSON 파일 저장 위치

 

3. 환경 변수와 API Key 관리

Azure Document Intelligence를 사용하려면 EndpointAPI Key가 필요합니다. Endpoint는 API 요청을 보낼 주소이고, API Key는 이 리소스를 사용할 권한이 있음을 증명하는 비밀번호 같은 값입니다.

처음 실습할 때는 각 폴더 안에 .env 파일을 둘 수도 있습니다. 하지만 이 레포처럼 Document Intelligence뿐 아니라 AI Language, Speech, OpenAI 같은 여러 서비스를 함께 실습할 계획이라면, 루트 폴더에 .env를 하나만 두는 방식이 더 관리하기 쉽습니다.

AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=your_endpoint
AZURE_DOCUMENT_INTELLIGENCE_KEY=your_key
주의
.env 파일에는 실제 API Key가 들어갑니다. 따라서 GitHub에 절대 올리면 안 됩니다. 대신 .env.example 파일에는 예시 변수명만 넣어두면 됩니다.
# .gitignore

.env
.venv/
__pycache__/
outputs/
**/outputs/

4. REST API 호출 흐름 이해하기

REST API는 쉽게 말해 정해진 주소로 요청을 보내고, 그 결과를 JSON으로 받는 방식입니다. 웹사이트 주소를 입력하면 화면이 열리는 것처럼, 프로그램은 Azure가 제공하는 API 주소로 문서 분석 요청을 보냅니다.

다만 Document Intelligence의 문서 분석은 바로 결과가 나오지 않습니다. PDF나 이미지 안의 텍스트, 표, 위치 정보를 분석해야 하므로 시간이 조금 걸릴 수 있습니다. 그래서 요청을 보내면 Azure는 최종 결과 대신 먼저 Operation-Location이라는 결과 조회 주소를 돌려줍니다.

단계 역할 쉽게 말하면
1. 파일 전송 문서를 바이너리로 읽어 API에 전달 문서를 제출함
2. 분석 요청 선택한 모델로 문서 분석 시작 AI에게 읽어달라고 요청함
3. 결과 주소 받기 Operation-Location 응답 수신 접수 번호를 받음
4. 결과 조회 분석 완료 여부를 반복 확인 처리가 끝났는지 확인함
5. JSON 파싱 결과에서 텍스트, 표, 필드 추출 결과지에서 필요한 내용만 꺼냄
왜 한 번에 결과를 주지 않을까?
문서 분석은 이미지 처리와 구조 분석이 함께 들어가는 작업입니다. 그래서 Azure는 요청을 받으면 먼저 “접수 완료”를 알려주고, 분석이 끝났을 때 다시 결과를 조회하도록 합니다.

5. common.py로 공통 기능 분리하기

REST API를 호출하려면 매번 비슷한 코드가 필요합니다. 파일을 열고, 요청을 보내고, 결과 조회 주소를 받고, 분석이 끝날 때까지 기다린 다음 JSON을 저장해야 합니다.

이 코드를 analyze_read.py, analyze_layout.py, analyze_invoice.py마다 반복해서 쓰면 코드가 금방 지저분해집니다. 그래서 공통 기능을 common.py에 따로 분리했습니다.

analyze_read.py
analyze_layout.py
analyze_invoice.py
        ↓
common.py
        ↓
Azure Document Intelligence REST API
        ↓
JSON Result

common.py의 핵심 함수는 analyze_document()입니다. 이 함수는 모델 이름과 파일 경로를 받아 Azure Document Intelligence에 분석 요청을 보냅니다.

def analyze_document(model_id: str, file_path: str):
    if not ENDPOINT or not KEY:
        raise ValueError("루트 `.env`에 Endpoint와 Key를 설정하세요.")

    file_path = Path(file_path)

    if not file_path.exists():
        raise FileNotFoundError(f"파일을 찾을 수 없습니다: {file_path}")

    url = (
        f"{ENDPOINT}/documentintelligence/documentModels/"
        f"{model_id}:analyze?api-version={API_VERSION}"
    )

    headers = {
        "Ocp-Apim-Subscription-Key": KEY,
        "Content-Type": "application/octet-stream",
    }

    with open(file_path, "rb") as f:
        response = requests.post(url, headers=headers, data=f)

    if response.status_code != 202:
        print(response.text)
        response.raise_for_status()

    operation_location = response.headers["Operation-Location"]

    result_headers = {
        "Ocp-Apim-Subscription-Key": KEY
    }

    while True:
        result_response = requests.get(operation_location, headers=result_headers)
        result_response.raise_for_status()

        result = result_response.json()
        status = result.get("status")

        if status == "succeeded":
            return result

        if status == "failed":
            raise RuntimeError(result)

        time.sleep(1)

이렇게 공통 함수를 만들어두면 모델만 바꿔서 여러 분석을 실행할 수 있습니다. 즉, 실제 API 호출 로직은 한 곳에만 두고, 각 실행 파일에서는 어떤 모델을 사용할지만 정하면 됩니다.

6. Read, Layout, Invoice 모델 실행하기

이번 실습에서는 Document Intelligence의 사전 제작 모델 세 가지를 사용했습니다. 사전 제작 모델은 Azure가 미리 만들어둔 문서 분석 모델입니다. 직접 학습 데이터를 준비하지 않아도 바로 사용할 수 있다는 장점이 있습니다.

모델 ID 용도 사용 예시
prebuilt-read 텍스트 OCR PDF나 이미지에서 글자 추출
prebuilt-layout 문서 구조와 표 추출 강의자료, 보고서, 표가 있는 문서 분석
prebuilt-invoice 청구서 필드 추출 영수증, 청구서, 거래명세서 분석

analyze_read.py

from common import analyze_document, save_json, print_content

file_path = "../sample-data/database_basic.pdf"

result = analyze_document(
    model_id="prebuilt-read",
    file_path=file_path
)

save_json(result, "../outputs/read_result.json")
print_content(result)

analyze_layout.py

from common import analyze_document, save_json, print_content

file_path = "../sample-data/database_basic.pdf"

result = analyze_document(
    model_id="prebuilt-layout",
    file_path=file_path
)

save_json(result, "../outputs/layout_result.json")
print_content(result)

tables = result.get("analyzeResult", {}).get("tables", [])

print(f"\n추출된 표 개수: {len(tables)}")

for table_idx, table in enumerate(tables):
    print(f"\n[Table {table_idx + 1}]")
    print(f"rows: {table.get('rowCount')}, columns: {table.get('columnCount')}")

    for cell in table.get("cells", []):
        row = cell.get("rowIndex")
        col = cell.get("columnIndex")
        text = cell.get("content")
        print(f"({row}, {col}) {text}")

analyze_invoice.py

from common import analyze_document, save_json, print_content

file_path = "../sample-data/receipt.jpg"

result = analyze_document(
    model_id="prebuilt-invoice",
    file_path=file_path
)

save_json(result, "../outputs/invoice_result.json")
print_content(result)

7. Layout 모델로 PDF 표 추출하기

이번 실습에서는 database_basic.pdf 파일을 사용해 Layout 모델을 실행했습니다. Layout 모델은 단순히 텍스트만 읽는 것이 아니라, 문서 안에 있는 표의 행과 열 구조까지 분석합니다.

cd 01-document-intelligence/02-rest-api
python analyze_layout.py

실행 결과, PDF 안의 텍스트가 출력되고 결과 JSON 파일이 저장되었습니다. 또한 문서 안에서 총 7개의 표가 추출되었습니다.

저장 완료: ..\outputs\layout_result.json

추출된 표 개수: 7

[Table 1]
rows: 2, columns: 2

[Table 2]
rows: 11, columns: 4

표 데이터는 셀 단위로 반환됩니다. 예를 들어 (0, 0)은 0번째 행, 0번째 열에 있는 값을 의미합니다.

(0, 0) 주문 번호
(0, 1) 주문 일자
(0, 2) 제품명
(0, 3) 판매 금액
(1, 0) 1
(1, 1) 2022-01-10
(1, 2) 냉장고
(1, 3) 50만 원
중요한 포인트
Layout 모델은 문서를 단순 이미지로 보지 않습니다. 문서 안의 텍스트, 표, 행, 열 같은 구조를 데이터로 바꿔줍니다. 그래서 나중에 표를 DataFrame으로 변환하거나 검색 시스템에 넣는 데 활용할 수 있습니다.

8. Gradio 웹앱 만들기

REST API가 정상적으로 동작하는 것을 확인했다면, 이제 같은 기능을 웹 화면에서 실행할 수 있게 만들 차례입니다. 이때 사용하는 도구가 Gradio입니다.

Gradio는 파이썬 함수에 웹 화면을 붙여주는 도구입니다. 즉, Gradio가 문서를 분석하는 것이 아니라, 사용자가 업로드한 파일을 파이썬 함수로 넘겨주고, 그 함수가 Azure Document Intelligence를 호출한 뒤 결과를 화면에 보여주는 구조입니다.

파일 업로드
    ↓
모델 선택
    ↓
common.py의 analyze_document() 호출
    ↓
Azure Document Intelligence 분석
    ↓
텍스트 / 상세 결과 / Raw JSON 출력

이번 Gradio 앱에서는 사용자가 분석 모델을 선택할 수 있게 구성했습니다.

MODEL_OPTIONS = {
    "Read - 텍스트 OCR": "prebuilt-read",
    "Layout - 문서 구조/표 추출": "prebuilt-layout",
    "Invoice - 청구서/영수증 분석": "prebuilt-invoice",
}
Gradio 화면 요소 역할
파일 업로드 PDF, JPG, PNG 파일 입력
모델 선택 Read, Layout, Invoice 중 선택
분석 실행 버튼 업로드된 파일을 Azure API로 분석
추출 텍스트 탭 문서 전체 OCR 결과 출력
상세 결과 탭 표 정보 또는 Invoice 필드 출력
Raw JSON 탭 Azure API 원본 응답 확인

실행은 03-gradio-app 폴더에서 진행합니다.

cd 01-document-intelligence/03-gradio-app
python app.py

실행 후 터미널에 표시되는 주소로 접속하면 Gradio 웹 화면을 확인할 수 있습니다.

http://127.0.0.1:7860

 

9. 실행 결과 확인하기

Gradio 앱에서는 파일을 업로드하고 모델을 선택한 뒤 분석 버튼을 누르면 결과를 확인할 수 있습니다. 이번 실습에서는 database_basic.pdfreceipt.jpg를 사용했습니다.

테스트 파일 선택 모델 확인한 결과
database_basic.pdf prebuilt-layout 텍스트와 표 7개 추출
database_basic.pdf prebuilt-read 문서 전체 텍스트 OCR 결과 확인
receipt.jpg prebuilt-invoice 영수증 또는 청구서 필드 추출 테스트

특히 Layout 모델을 선택하면 표의 개수와 각 셀의 위치 정보를 확인할 수 있습니다. 이 결과는 단순히 화면에 보여주는 데서 끝나지 않고, 나중에 pandas DataFrame으로 바꾸거나 문서 검색 시스템에 넣을 수 있습니다.

Gradio 실행 화면



상세 결과 화면
JSON 추출 화면



10. 오류와 해결 방법

이번 실습에서 오류는 대부분 코드 로직보다 환경 설정, 파일 경로, GitHub 인증 문제에서 발생했습니다. 오류가 발생하면 전체 코드를 한꺼번에 의심하기보다 어느 단계에서 실패했는지 나누어 보는 것이 좋습니다.

오류 원인 해결 방법
No module named requests requests 패키지가 설치되지 않음 python -m pip install requests
No module named dotenv python-dotenv 패키지가 설치되지 않음 python -m pip install python-dotenv
FileNotFoundError 파일 경로가 실행 위치 기준과 맞지 않음 상대경로를 ../sample-data/file.pdf 형태로 수정
401 Unauthorized API Key가 잘못되었거나 누락됨 Azure Portal에서 Key 재확인
403 GitHub Permission denied GitHub 로그인 계정과 레포 권한 불일치 Windows 자격 증명 관리자에서 GitHub 인증 삭제 후 재로그인
git push rejected 원격 레포에 이미 README 등 기존 커밋이 있음 git pull origin main --allow-unrelated-histories 후 push
파일 경로에서 특히 주의할 점
현재 실행 위치가 02-rest-api라면 01-document-intelligence/sample-data/database_basic.pdf처럼 쓰면 안 됩니다. Python은 현재 폴더 안에서 다시 01-document-intelligence 폴더를 찾으려고 하기 때문입니다.

올바른 상대경로는 다음과 같습니다.

file_path = "../sample-data/database_basic.pdf"

11. 정리

이번 글에서는 Azure AI Document Intelligence를 사용해 문서를 분석하는 전체 흐름을 구현했습니다. 처음에는 Studio에서 직접 문서를 올려 분석 결과를 확인했고, 그 다음에는 Python REST API로 같은 작업을 코드화했습니다. 마지막으로 Gradio를 사용해 파일 업로드와 결과 확인을 웹 화면으로 연결했습니다.

이번 실습의 핵심은 기능을 단계별로 분리했다는 점입니다. API 호출 로직은 common.py에 모아두고, 각 모델 실행 파일과 Gradio 앱은 이 공통 함수를 재사용했습니다. 덕분에 코드가 반복되지 않고, 나중에 새로운 모델이나 기능을 추가하기도 쉬워졌습니다.

  • Document Intelligence Studio에서 문서 분석 결과를 먼저 확인했습니다.
  • Python REST API로 Document Intelligence를 직접 호출했습니다.
  • common.py를 만들어 공통 API 호출 로직을 분리했습니다.
  • prebuilt-read, prebuilt-layout, prebuilt-invoice 모델을 실행할 수 있도록 구성했습니다.
  • database_basic.pdf를 Layout 모델로 분석해 텍스트와 표 7개를 추출했습니다.
  • Gradio 앱으로 파일 업로드, 모델 선택, 결과 출력을 웹 화면에 연결했습니다.
  • 분석 결과를 outputs 폴더에 JSON 파일로 저장했습니다.
  • GitHub 저장소에 프로젝트 구조와 코드를 정리했습니다.

12. 전체 흐름 한 번에 정리

순서 작업 설명
1 Azure 리소스 준비 Endpoint와 API Key 확인
2 환경 변수 설정 루트 .env에서 Key 관리
3 common.py 작성 API 호출, 결과 조회, JSON 저장 기능 분리
4 모델별 실행 파일 작성 Read, Layout, Invoice 모델 테스트
5 Layout 결과 확인 PDF에서 텍스트와 표 7개 추출
6 Gradio 앱 구현 파일 업로드, 모델 선택, 결과 출력 화면 구성
7 GitHub 정리 코드와 README를 저장소에 업로드
한 줄로 정리하면, Gradio는 사용자가 문서를 올리는 화면을 만들고, Document Intelligence는 그 문서를 읽어 JSON 결과로 돌려주며, 우리는 그 JSON에서 필요한 텍스트와 표를 꺼내 사용자에게 보여줍니다.

13. 핵심 키워드 정리

키워드 의미
Document Intelligence 문서에서 텍스트와 구조화 데이터를 추출하는 Azure AI 서비스
REST API 정해진 URL로 요청을 보내고 응답을 받는 방식
Endpoint Azure API 요청을 보낼 리소스 주소
API Key Azure 리소스 사용 권한을 확인하는 비밀 값
Operation-Location 비동기 분석 결과를 조회할 수 있는 주소
JSON Parsing JSON 응답에서 필요한 값만 꺼내는 과정
prebuilt-read 문서 텍스트를 OCR로 추출하는 모델
prebuilt-layout 문서의 구조, 표, 행과 열 정보를 추출하는 모델
prebuilt-invoice 청구서나 영수증의 주요 필드를 추출하는 모델
Gradio 파이썬 함수에 웹 기반 입력과 출력을 연결해주는 라이브러리

14. 다음 글 예고

이번 글에서는 Document Intelligence REST API와 Gradio를 연결해 문서 분석 앱을 만드는 흐름을 살펴봤습니다. 여기까지 하면 문서를 업로드하고, 텍스트와 표를 추출하고, 결과 JSON까지 확인할 수 있습니다.

다음 글에서는 분석 결과를 단순히 출력하는 수준을 넘어, Document Intelligence가 반환한 JSON 구조를 자세히 살펴보고, 추출된 표 데이터를 pandas DataFrame으로 변환하는 방법을 알아보겠습니다.