smarteye-backend / README.md
AkJeond's picture
chore(backend): add HF Spaces README config
9c8d959
metadata
title: SmartEyeSsen Backend
emoji: ๐Ÿ”
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
pinned: false

SmartEyeSsen Backend

FastAPI ยท MySQL ยท DocLayout-YOLO ๊ธฐ๋ฐ˜ AI ๋ฌธ์„œ ๋ถ„์„ ๋ฐฑ์—”๋“œ

๐Ÿ“š ๋ชฉ์ฐจ


๐ŸŽฏ ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

  • PDF/์ด๋ฏธ์ง€ ์—…๋กœ๋“œ โ†’ DocLayout-YOLO + Tesseract๋กœ ๋ ˆ์ด์•„์›ƒ๊ณผ ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•˜๊ณ , OpenAI Vision์œผ๋กœ ๋„ํ‘œยทํ‘œ ์„ค๋ช…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฐ๊ณผ๋ฌผ์€ SmartEye ์ •๋ ฌ ๊ทœ์น™์„ ๊ฑฐ์ณ ํ”„๋กœ์ ํŠธ/ํŽ˜์ด์ง€/์š”์†Œ ๋‹จ์œ„๋กœ ์ €์žฅ๋˜๋ฉฐ, DOCX ๋‹ค์šด๋กœ๋“œ๊นŒ์ง€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.
  • ์šด์˜ ํ™˜๊ฒฝ์€ DigitalOcean Droplet์—์„œ docker-compose.prod.yml์„ ํ†ตํ•ด MySQL + Backend + Frontend + Certbot ์ปจํ…Œ์ด๋„ˆ๋กœ ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ—‚ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ตฌ์กฐ

Backend/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ main.py            # FastAPI ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
โ”‚   โ”œโ”€โ”€ database.py        # ์„ธ์…˜/์—”์ง„, MySQL ์—ฐ๊ฒฐ
โ”‚   โ”œโ”€โ”€ models.py          # SQLAlchemy ORM
โ”‚   โ”œโ”€โ”€ schemas.py         # Pydantic v2 ์Šคํ‚ค๋งˆ
โ”‚   โ”œโ”€โ”€ crud.py            # DB ์ ‘๊ทผ ํ—ฌํผ
โ”‚   โ”œโ”€โ”€ routers/           # ํ”„๋กœ์ ํŠธ/ํŽ˜์ด์ง€/๋ถ„์„/๋‹ค์šด๋กœ๋“œ ๋ผ์šฐํ„ฐ
โ”‚   โ””โ”€โ”€ services/          # OCRยท๋ ˆ์ด์•„์›ƒยท์ •๋ ฌยทAI ์„ค๋ช… ๋ชจ๋“ˆ
โ”œโ”€โ”€ scripts/
โ”‚   โ”œโ”€โ”€ init_db_complete.sql   # 12๊ฐœ ํ…Œ์ด๋ธ” + ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ
โ”‚   โ””โ”€โ”€ reset_db.sh (์˜ต์…˜)     # ๊ฐœ๋ฐœ์šฉ ์ดˆ๊ธฐํ™” ์Šคํฌ๋ฆฝํŠธ
โ”œโ”€โ”€ uploads/, static/          # ์—…๋กœ๋“œ/์ •์  ๊ฒฐ๊ณผ (์ปจํ…Œ์ด๋„ˆ ๋ณผ๋ฅจ ์—ฐ๊ฒฐ)
โ”œโ”€โ”€ Dockerfile                 # ๋ฉ€ํ‹ฐ ์Šคํ…Œ์ด์ง€ ํ”„๋กœ๋•์…˜ ์ด๋ฏธ์ง€
โ”œโ”€โ”€ docker-compose.yml         # ๋ฐฑ์—”๋“œ ๋‹จ๋… MySQL ์ปจํ…Œ์ด๋„ˆ
โ”œโ”€โ”€ requirements.txt           # Python ์˜์กด์„ฑ
โ””โ”€โ”€ README.md                  # ๋ณธ ๋ฌธ์„œ

โš™ ์‹คํ–‰ ๋ชจ๋“œ

1. ๋กœ์ปฌ ๊ฐœ๋ฐœ (venv + Uvicorn)

cd Backend
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

ํ•„์š” ์‹œ OPENAI_API_KEY๋ฅผ .env์— ์„ค์ •ํ•˜๋ฉด AI ์„ค๋ช… ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

2. ๋ฐฑ์—”๋“œ ์ „์šฉ Docker Compose (MySQL ํฌํ•จ)

Backend/docker-compose.yml์€ MySQL 8.0 ์ปจํ…Œ์ด๋„ˆ๋งŒ ๋„์›Œ FastAPI๋ฅผ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

cd Backend
docker compose up -d                      # smart_mysql ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ (๊ธฐ๋ณธ ํฌํŠธ 3308โ†’3306)
uvicorn app.main:app --reload

์ข…๋ฃŒ ๋˜๋Š” ์ดˆ๊ธฐํ™”:

docker compose down                       # ์ปจํ…Œ์ด๋„ˆ๋งŒ ์ข…๋ฃŒ
docker compose down -v                    # smart_mysql_data ๋ณผ๋ฅจ๊นŒ์ง€ ์‚ญ์ œ (โš  ์ „์ฒด ๋ฐ์ดํ„ฐ ์‚ญ์ œ)

3. ํ”„๋กœ๋•์…˜ Docker Compose (์ „์ฒด ์Šคํƒ)

๋ฃจํŠธ docker-compose.prod.yml์˜ backend ์„œ๋น„์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

backend:
  build:
    context: ./Backend
    dockerfile: Dockerfile
  env_file:
    - Backend/.env
  environment:
    DB_HOST: mysql
    DB_PORT: 3306
    ENVIRONMENT: production
  volumes:
    - ./Backend/uploads:/app/uploads
    - ./Backend/static:/app/static
  depends_on:
    mysql:
      condition: service_healthy

๋ฐฐํฌ ์‹œ ์„œ๋ฒ„์—์„œ:

git checkout main && git pull --ff-only origin main
docker compose -f docker-compose.prod.yml build backend
docker compose -f docker-compose.prod.yml up -d --force-recreate backend

๐Ÿ” ํ™˜๊ฒฝ ๋ณ€์ˆ˜

.env.example์„ ๊ธฐ๋ฐ˜์œผ๋กœ .env๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ์„ค๋ช… ๋น„๊ณ 
DB_HOST, DB_PORT MySQL ์ ‘์† ์ •๋ณด Docker ์‚ฌ์šฉ ์‹œ mysql/3306์œผ๋กœ ์ž๋™ override
DB_USER, DB_PASSWORD, DB_NAME DB ๊ณ„์ • ์ดˆ๊ธฐ ์Šคํฌ๋ฆฝํŠธ ๊ธฐ๋ณธ๊ฐ’: root / change_this_password / smarteyessen_db
DATABASE_URL SQLAlchemy ์ ‘์† URL ๋ณ€๊ฒฝ ๋ถˆํ•„์š” (ํ…œํ”Œ๋ฆฟ ์ž๋™ ์กฐํ•ฉ)
API_HOST, API_PORT FastAPI ์„œ๋ฒ„ ํ˜ธ์ŠคํŠธ/ํฌํŠธ ๊ธฐ๋ณธ 0.0.0.0:8000
ENVIRONMENT development / production Compose์—์„œ production์œผ๋กœ ๊ฐ•์ œ
OPENAI_API_KEY ์„ ํƒ ํ•ญ๋ชฉ ์—†์œผ๋ฉด AI ์„ค๋ช… ๋น„ํ™œ์„ฑํ™”
UPLOAD_DIR, MAX_FILE_SIZE, ALLOWED_EXTENSIONS ์—…๋กœ๋“œ ์„ค์ • ๊ธฐ๋ณธ 100 MB, jpg/jpeg/png/pdf
SECRET_KEY, ALGORITHM JWT/๋ณด์•ˆ ์˜ต์…˜ ํ•„์š” ์‹œ ์—…๋ฐ์ดํŠธ
USE_ADAPTIVE_SORTER, PDF_PROCESSOR_DPI ๋“ฑ ํŒŒ์ดํ”„๋ผ์ธ ๋™์ž‘ ์ œ์–ด .env.example ์ฐธ๊ณ 

๐Ÿณ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค & Docker ๊ตฌ์„ฑ

Backend/docker-compose.yml (๋กœ์ปฌ MySQL)

ํ•ญ๋ชฉ ๊ฐ’
์ด๋ฏธ์ง€ mysql:8.0
์ปจํ…Œ์ด๋„ˆ ์ด๋ฆ„ smart_mysql
ํฌํŠธ ํ˜ธ์ŠคํŠธ ${MYSQL_PORT:-3308} โ†’ 3306
๋ณผ๋ฅจ smart_mysql_data:/var/lib/mysql (Named Volume)
์ดˆ๊ธฐํ™” ./scripts/init_db_complete.sql โ†’ /docker-entrypoint-initdb.d/01_init.sql
๋ฌธ์ž์…‹ utf8mb4 / utf8mb4_unicode_ci
ํ—ฌ์Šค์ฒดํฌ mysqladmin ping (10์ดˆ ๊ฐ„๊ฒฉ, 5ํšŒ ์žฌ์‹œ๋„)

Backend/Dockerfile (ํ”„๋กœ๋•์…˜ ์ด๋ฏธ์ง€)

  1. Builder ๋‹จ๊ณ„ (python:3.9-slim)
    • Tesseract(ko/en), OpenCV ์˜์กด ํŒจํ‚ค์ง€ ์„ค์น˜
    • pip install -r requirements.txt + doclayout-yolo
  2. Runtime ๋‹จ๊ณ„ (python:3.9-slim)
    • ๋Ÿฐํƒ€์ž„ ํŒจํ‚ค์ง€ ์„ค์น˜ ํ›„ Builder์—์„œ site-packages ๋ณต์‚ฌ
    • ko_KR.UTF-8 ๋กœ์ผ€์ผ ์ƒ์„ฑ
    • /app/uploads, /app/static, /app/test_pipeline_outputs ์ƒ์„ฑ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ
    • Healthcheck: requests.get('http://localhost:8000/health')
    • CMD: Gunicorn + UvicornWorker (1 worker, timeout 300์ดˆ)

DB ์ดˆ๊ธฐ ์Šคํ‚ค๋งˆ

  • scripts/init_db_complete.sql์ด 12๊ฐœ ํ…Œ์ด๋ธ”(users, projects, pages, โ€ฆ combined_results)๊ณผ ์‹œ๋“œ ๋ฐ์ดํ„ฐ(document_types 2๊ฑด, formatting_rules 25๊ฑด)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • combined_results.combined_text ํƒ€์ž…์€ LONGTEXT๋กœ 4GB๊นŒ์ง€ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿง  FastAPI ๋ชจ๋“ˆ ๊ตฌ์„ฑ

์˜์—ญ ์„ค๋ช…
routers/projects.py ํ”„๋กœ์ ํŠธ CRUD, ๋ถ„์„ ํŠธ๋ฆฌ๊ฑฐ
routers/pages.py ํŽ˜์ด์ง€ ์—…๋กœ๋“œ, ํ…์ŠคํŠธ ๋ฒ„์ „ API
routers/analyze.py DocLayout-YOLO ์‹คํ–‰, Tesseract OCR, AI ์„ค๋ช…
routers/download.py ํ†ตํ•ฉ ํ…์ŠคํŠธ/WORD ์ƒ์„ฑ
services/layout_service.py ๋ชจ๋ธ ๋กœ๋”ฉ, ๋ ˆ์ด์•„์›ƒ ํ›„์ฒ˜๋ฆฌ
services/ocr_service.py PDF ๋ถ„๋ฆฌ, ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ, Tesseract ํ˜ธ์ถœ
services/sorter_service.py ๋ฌธ์ œ์ง€/์ผ๋ฐ˜ ๋ฌธ์„œ๋ณ„ ์ •๋ ฌ ๋กœ์ง
services/ai_description_service.py OpenAI Vision ํ˜ธ์ถœ ๋ฐ ์บ์‹ฑ

๋ชจ๋“  ๋ผ์šฐํ„ฐ๋Š” app/main.py์—์„œ FastAPI ์ธ์Šคํ„ด์Šค์— ๋“ฑ๋ก๋˜๋ฉฐ, database.SessionLocal ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•ด ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


๐Ÿงช ํ…Œ์ŠคํŠธ & ์Šคํฌ๋ฆฝํŠธ

  • Pytest: ๋ฃจํŠธ์—์„œ pytest -c Project/pytest.ini ์‹คํ–‰ (ํšŒ๊ท€/ํ†ตํ•ฉ ์‹œ -m regression ์‚ฌ์šฉ)
  • start_backend.sh: ์˜์กด์„ฑ ์ฒดํฌ ํ›„ Uvicorn ์‹คํ–‰ (๋ฃจํŠธ ์Šคํฌ๋ฆฝํŠธ)
  • scripts/reset_db.sh: ๊ฐœ๋ฐœ DB ์ดˆ๊ธฐํ™” (๋ฐ์ดํ„ฐ ์ „์ฒด ์‚ญ์ œ)
  • api_server.py: ๋ ˆ๊ฑฐ์‹œ ๋‹จ์ผ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰(ํ•„์š” ์‹œ๋งŒ ์‚ฌ์šฉ)

๐Ÿšจ ์ž์ฃผ ๋ฌป๋Š” ๋ฌธ์ œ

์ฆ์ƒ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
MySQL ์ปจํ…Œ์ด๋„ˆ ํ—ฌ์Šค์ฒดํฌ ์‹คํŒจ docker compose logs mysql ํ™•์ธ, ํฌํŠธ ์ถฉ๋Œ ์‹œ MYSQL_PORT ๋ณ€๊ฒฝ, docker compose down -v๋กœ ์žฌ์ƒ์„ฑ
DataError: ... combined_text scripts/init_db_complete.sql ์ตœ์‹  ๋ฒ„์ „ ์ ์šฉ ํ›„ reset_db.sh ์‹คํ–‰
Tesseract ์–ธ์–ด ๋ฏธํƒ‘์žฌ Dockerfile ์ด๋ฏธ์ง€๋Š” tesseract-ocr-kor/eng๋ฅผ ํฌํ•จํ•จ. ๋กœ์ปฌ ์ˆ˜๋™ ์„ค์น˜ ์‹œ sudo apt install tesseract-ocr-kor
OpenAI ์˜ค๋ฅ˜ .env์˜ OPENAI_API_KEY ํ™•์ธ, ์š”์ฒญ ์ˆ˜ ์ œํ•œ ์‹œ OPENAI_MAX_CONCURRENCY ๊ฐ’ ์กฐ์ •
์—…๋กœ๋“œ ํŒŒ์ผ ๋ฏธ์ €์žฅ ์ปจํ…Œ์ด๋„ˆ ๋ณผ๋ฅจ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งˆ์šดํŠธ๋˜์—ˆ๋Š”์ง€ (./Backend/uploads:/app/uploads) ํ™•์ธ

๐Ÿ“Ž ์ฐธ๊ณ  ์ž๋ฃŒ

  • ../README.md โ€“ ์ „์ฒด ์‹œ์Šคํ…œ ๊ฐœ์š” ๋ฐ ๋ฐฐํฌ ์ „๋žต
  • Backend/docs/Backend API ๋ฌธ์„œ/ โ€“ ์„ธ๋ถ€ API ์ŠคํŽ™