ํ๊ตญ์ด ๊ฐ์ธ์ ๋ณด(PII) ํ์ง๋ฅผ ์ํ ์ ๊ท์ + BERT NER ๊ธฐ๋ฐ FastAPI ๋ฐฑ์๋ ์๋น์ค์ ๋๋ค.
ํ๊น
ํ์ด์ค์ psh3333/roberta-large-korean-pii5 ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์ค์๊ฐ PII ํ์ง ๋ฐ ์ฐจ๋จ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- โ JWT ๊ธฐ๋ฐ ์ธ์ฆ ์์คํ : ํ์๊ฐ์ , ๋ก๊ทธ์ธ, ํ ํฐ ์ธ์ฆ
- โ ์ ๊ท์ ๊ธฐ๋ฐ PII ํ์ง: ์ ํ๋ฒํธ, ์ด๋ฉ์ผ ๋ฑ ํจํด ๋งค์นญ
- โ BERT NER ๊ธฐ๋ฐ PII ํ์ง: RoBERTa ๋ชจ๋ธ์ ํ์ฉํ ๊ฐ์ธ์ ๋ณด ์ํฐํฐ ์ธ์
- โ ์ค์๊ฐ ์ฐจ๋จ ํ๋จ: ํ์ง๋ PII ๊ธฐ๋ฐ ์๋ ์ฐจ๋จ ์ฌ๋ถ ๊ฒฐ์
- โ RESTful API: FastAPI ๊ธฐ๋ฐ ๊ณ ์ฑ๋ฅ API
- โ ์๋ ๋ฌธ์ํ: Swagger UI ์ ๊ณต
- โ PostgreSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค: ์ฌ์ฉ์ ์ ๋ณด ๋ฐ ์ธ์ฆ ๊ด๋ฆฌ
DLP-BE/
โโโ app/
โ โโโ main.py # FastAPI ์ง์
์
โ โโโ api/routers/
โ โ โโโ auth.py # ์ธ์ฆ API (ํ์๊ฐ์
, ๋ก๊ทธ์ธ)
โ โ โโโ pii.py # PII ํ์ง API (์ธ์ฆ ํ์)
โ โโโ services/
โ โ โโโ pii_service.py # ๋น์ฆ๋์ค ๋ก์ง
โ โโโ ai/
โ โ โโโ pii_detector.py # RoBERTa PII ํ์ง ๋ชจ๋ธ
โ โ โโโ model_manager.py # ๋ชจ๋ธ ์ฑ๊ธํค ๊ด๋ฆฌ
โ โโโ schemas/
โ โ โโโ auth.py # ์ธ์ฆ ์คํค๋ง
โ โ โโโ pii.py # PII ์คํค๋ง
โ โโโ models/
โ โ โโโ user.py # User ๋ฐ์ดํฐ ๋ชจ๋ธ
โ โโโ repository/
โ โ โโโ user_repo.py # User ๋ฐ์ดํฐ ์ ๊ทผ ๋ ์ด์ด
โ โโโ db/
โ โ โโโ base.py # SQLAlchemy Base
โ โ โโโ session.py # DB ์ธ์
๊ด๋ฆฌ
โ โโโ core/
โ โ โโโ config.py # ์ค์
โ โ โโโ security.py # JWT ๋ฐ ์ํธํ
โ โ โโโ dependencies.py # ์ธ์ฆ ์์กด์ฑ
โ โโโ utils/
โ โโโ entity_extractor.py # BIO ํ๊ทธ ์ํฐํฐ ์ถ์ถ
โโโ alembic/ # DB ๋ง์ด๊ทธ๋ ์ด์
โ โโโ versions/ # ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ๋ค
โโโ docker-compose.yml # PostgreSQL ์ปจํ
์ด๋
โโโ alembic.ini # Alembic ์ค์
โโโ .env # ํ๊ฒฝ ๋ณ์ (์์ฑ ํ์)
โโโ pyproject.toml # ์์กด์ฑ ๊ด๋ฆฌ
โโโ CLAUDE.md # ๊ฐ๋ฐ ๋ฌธ์
- Python 3.13+
- Docker & Docker Compose
- uv (๋๋ pip)
git clone <repository-url>
cd DLP-BE.env ํ์ผ์ ์์ฑํ๊ณ ๋ค์ ๋ด์ฉ์ ์์ฑํฉ๋๋ค:
# ๋ฐ์ดํฐ๋ฒ ์ด์ค
DATABASE_URL=postgresql+asyncpg://admin:password123@localhost:5432/ai_tlsdlp
# JWT ์ธ์ฆ
SECRET_KEY=dlp-secret-key-change-in-production-minimum-32-characters-required
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# AI ๋ชจ๋ธ ์ค์
PII_MODEL_NAME=psh3333/roberta-large-korean-pii5
DEFAULT_PII_THRESHOLD=0.59
# ์ฑ ์ค์
DEBUG=True# uv ์ฌ์ฉ (๊ถ์ฅ)
uv sync
# ๋๋ pip ์ฌ์ฉ
pip install -e .# Docker ๋ฐ๋ชฌ์ด ์คํ ์ค์ธ์ง ํ์ธ ํ
docker-compose up -d
# ์ปจํ
์ด๋ ์ํ ํ์ธ
docker-compose ps# Alembic์ผ๋ก users ํ
์ด๋ธ ์์ฑ
alembic upgrade headuv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
์์๋๋ก ์คํํ์ธ์:
# 1. ํ๋ก์ ํธ ํด๋ก
git clone <repository-url> && cd DLP-BE
# 2. .env ํ์ผ ์์ฑ (์ ๋ด์ฉ ๋ณต์ฌ)
nano .env
# 3. ์์กด์ฑ ์ค์น
uv sync
# 4. PostgreSQL ์์
docker-compose up -d
# 5. DB ๋ง์ด๊ทธ๋ ์ด์
(ํ
์ด๋ธ ์์ฑ)
alembic upgrade head
# 6. ์๋ฒ ์คํ
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000์ด์ http://localhost:8000/docs ์์ API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค!
์๋ํฌ์ธํธ: POST /api/v1/auth/register
curl -X POST "http://localhost:8000/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"email": "test@example.com",
"password": "password123",
"full_name": "ํ
์คํธ ์ฌ์ฉ์"
}'์๋ต:
{
"id": 1,
"username": "testuser",
"email": "test@example.com",
"full_name": "ํ
์คํธ ์ฌ์ฉ์",
"is_active": true,
"is_superuser": false
}์๋ํฌ์ธํธ: POST /api/v1/auth/login
curl -X POST "http://localhost:8000/api/v1/auth/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=testuser&password=password123"์๋ต:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}์๋ํฌ์ธํธ: GET /api/v1/auth/me (์ธ์ฆ ํ์)
curl -X GET "http://localhost:8000/api/v1/auth/me" \
-H "Authorization: Bearer <access_token>"์๋ํฌ์ธํธ: POST /api/v1/pii/detect
curl -X POST "http://localhost:8000/api/v1/pii/detect" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"text": "์ ์ด๋ฆ์ ํ๊ธธ๋์ด๊ณ ์ ํ๋ฒํธ๋ 010-1234-5678์
๋๋ค"}'์๋ต ์์:
{
"has_pii": true,
"reason": "๊ฐ์ธ์ ๋ณด 2๊ฐ ํ์ง๋จ (PERSON, PHONE_NUM)",
"details": "ํ์ง๋ ๊ฐ์ธ์ ๋ณด: PERSON 'ํ๊ธธ๋' (์ ๋ขฐ๋: 95.0%), PHONE_NUM '010-1234-5678' (์ ๋ขฐ๋: 89.0%)",
"entities": [
{
"type": "PERSON",
"value": "ํ๊ธธ๋",
"confidence": 0.95,
"token_count": 2
},
{
"type": "PHONE_NUM",
"value": "010-1234-5678",
"confidence": 0.89,
"token_count": 7
}
]
}์๋ํฌ์ธํธ: GET /api/v1/pii/health
curl -X GET "http://localhost:8000/api/v1/pii/health" \
-H "Authorization: Bearer <access_token>"- ๋ฐฑ์๋: FastAPI + Python 3.13
- ๋ฐ์ดํฐ๋ฒ ์ด์ค: PostgreSQL 15 + SQLAlchemy 2.0 (Async)
- ์ธ์ฆ: JWT (python-jose) + bcrypt (passlib)
- ๋ง์ด๊ทธ๋ ์ด์ : Alembic
- AI ๋ชจ๋ธ: Transformers + PyTorch
- PII ๋ชจ๋ธ:
psh3333/roberta-large-korean-pii5 - ํจํค์ง ๊ด๋ฆฌ: uv
- ์ปจํ ์ด๋: Docker + Docker Compose
- ์ฒซ ์์ฒญ: ~2์ด (๋ชจ๋ธ ๋ก๋ฉ ํฌํจ)
- ์ดํ ์์ฒญ: 100-300ms
- ์ฒ๋ฆฌ ๊ฐ๋ฅ ํ ์คํธ: ์ต๋ 512 ํ ํฐ (์ฝ 1000์)
- RoBERTa ๋ชจ๋ธ ํตํฉ
- ์ ๊ท์ ๊ธฐ๋ฐ ํจํด ๋งค์นญ
- BIO ํ๊น ์ ํ๋ ๊ฐ์
- ๋ชจ๋ธ ์ฑ๋ฅ ์ต์ ํ
- JWT ๊ธฐ๋ฐ ์ธ์ฆ/์ธ๊ฐ ์์คํ
- PostgreSQL + Alembic ๋ง์ด๊ทธ๋ ์ด์
- ๋ฌธ์ ์ ๋ก๋ ๋ฐ ํ์ฑ (PDF, DOCX)
- ์ ์ฌ๋ ๊ธฐ๋ฐ ๋ฌธ์ ๋น๊ต (KoSimCSE)
- ๋ฒกํฐ DB ์ฐ๋ (ChromaDB)
- ๊ด๋ฆฌ์ ๋์๋ณด๋
- ๋จ์/ํตํฉ ํ ์คํธ
- ๋ก๊น ๋ฐ ๋ชจ๋ํฐ๋ง
- Rate limiting ๋ฐ ๋ณด์ ๊ฐํ
- Docker ์ปจํ ์ด๋ํ (์ ์ฒด ์ฑ)
# ๋ชจ๋ธ ๋ณ๊ฒฝ ํ ๋ง์ด๊ทธ๋ ์ด์
ํ์ผ ์๋ ์์ฑ
alembic revision --autogenerate -m "์ค๋ช
"
# ๋ง์ด๊ทธ๋ ์ด์
์ ์ฉ
alembic upgrade head# ์ด์ ๋ฒ์ ์ผ๋ก ๋๋๋ฆฌ๊ธฐ
alembic downgrade -1
# ํน์ ๋ฒ์ ์ผ๋ก ๋๋๋ฆฌ๊ธฐ
alembic downgrade <revision_id>alembic history
alembic current์์ธํ ๊ฐ๋ฐ ๋ฌธ์๋ CLAUDE.md๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ด ํ๋ก์ ํธ๋ KISIA ํ๋ก์ ํธ์ ์ผ๋ถ์ ๋๋ค.
์ด ํ๋ก์ ํธ์ ๋ผ์ด์ ์ค๋ ํ๋ก์ ํธ ์์ ์์ ํ์ํ์ธ์.
ํ๋ก์ ํธ ๊ด๋ จ ๋ฌธ์์ฌํญ์ด ์์ผ์๋ฉด ์ด์๋ฅผ ์์ฑํด์ฃผ์ธ์.
AI-TLS-DLP Backend v1.1.0 - JWT ์ธ์ฆ + ์ ๊ท์ + BERT NER ๊ธฐ๋ฐ PII ํ์ง ์์คํ