Spaces:
Sleeping
Sleeping
| title: SmartEyeSsen Backend | |
| emoji: "๐" | |
| colorFrom: blue | |
| colorTo: green | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| # SmartEyeSsen Backend | |
| > FastAPI ยท MySQL ยท DocLayout-YOLO ๊ธฐ๋ฐ AI ๋ฌธ์ ๋ถ์ ๋ฐฑ์๋ | |
| ## ๐ ๋ชฉ์ฐจ | |
| - [ํ๋ก์ ํธ ๊ฐ์](#-ํ๋ก์ ํธ-๊ฐ์) | |
| - [๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ](#-๋๋ ํฐ๋ฆฌ-๊ตฌ์กฐ) | |
| - [์คํ ๋ชจ๋](#-์คํ-๋ชจ๋) | |
| - [ํ๊ฒฝ ๋ณ์](#-ํ๊ฒฝ-๋ณ์) | |
| - [๋ฐ์ดํฐ๋ฒ ์ด์ค & Docker ๊ตฌ์ฑ](#-๋ฐ์ดํฐ๋ฒ ์ด์ค--docker-๊ตฌ์ฑ) | |
| - [FastAPI ๋ชจ๋ ๊ตฌ์ฑ](#-fastapi-๋ชจ๋-๊ตฌ์ฑ) | |
| - [ํ ์คํธ & ์คํฌ๋ฆฝํธ](#-ํ ์คํธ--์คํฌ๋ฆฝํธ) | |
| - [์์ฃผ ๋ฌป๋ ๋ฌธ์ ](#-์์ฃผ-๋ฌป๋-๋ฌธ์ ) | |
| - [์ฐธ๊ณ ์๋ฃ](#-์ฐธ๊ณ -์๋ฃ) | |
| --- | |
| ## ๐ฏ ํ๋ก์ ํธ ๊ฐ์ | |
| - 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) | |
| ```bash | |
| 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๋ฅผ ๋ก์ปฌ์์ ์คํํ ๋ ์ฌ์ฉํฉ๋๋ค. | |
| ```bash | |
| cd Backend | |
| docker compose up -d # smart_mysql ์ปจํ ์ด๋ ์์ (๊ธฐ๋ณธ ํฌํธ 3308โ3306) | |
| uvicorn app.main:app --reload | |
| ``` | |
| ์ข ๋ฃ ๋๋ ์ด๊ธฐํ: | |
| ```bash | |
| docker compose down # ์ปจํ ์ด๋๋ง ์ข ๋ฃ | |
| docker compose down -v # smart_mysql_data ๋ณผ๋ฅจ๊น์ง ์ญ์ (โ ์ ์ฒด ๋ฐ์ดํฐ ์ญ์ ) | |
| ``` | |
| ### 3. ํ๋ก๋์ Docker Compose (์ ์ฒด ์คํ) | |
| ๋ฃจํธ `docker-compose.prod.yml`์ `backend` ์๋น์ค๋ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑ๋ฉ๋๋ค. | |
| ```yaml | |
| 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 | |
| ``` | |
| ๋ฐฐํฌ ์ ์๋ฒ์์: | |
| ```bash | |
| 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 ์คํ |