사용자가 업로드한 사진의 개인정보 위험을 분석하고, 버전형 보호 결과와 프롬프트 기반 이미지 후처리 작업을 관리하는 모바일 앱의 백엔드 서버.
| 컴포넌트 | 역할 |
|---|---|
| backend (FastAPI) | 프론트엔드 REST API, S3 관리, Celery task 발행 |
| worker (Celery) | 비동기 이미지 처리 — AI 서버 HTTP API 호출 |
| beat (Celery Beat) | 타임아웃 스위퍼 스케줄러 (매 1분) |
| db (PostgreSQL 15) | 분석 태스크, 비동기 operation, 버전별 이미지 결과 |
| rabbitmq (RabbitMQ 3) | 메시지 브로커 |
- 운영 서버:
http://3.34.99.130:8000· Swagger: /docs · OpenAPI: /openapi.json - 계약 문서: docs/INTERFACE-FOR-FRONTEND.md · docs/INTERFACE-FOR-AISERVER.md
- AI 서버 API 명세: docs/images-analyze.md · docs/images-process.md
[React Native] --REST--> [FastAPI :8000] --Celery task--> [RabbitMQ :5672]
| |
v v
[PostgreSQL] [Celery Worker]
| |
v v
[AWS S3] <-- presigned URL --> [AI Server :8001]
플로우: v1 업로드·분석 → v2 보호 처리 operation 생성 → AI 서버 v2 /process 호출 → 버전 1
결과 저장 → 사용자 프롬프트와 기준 output 선택 → 새 edit operation 생성 → AI 서버 v2 /edit
호출 → 개인정보 보호가 재적용된 다음 결과 버전 저장. 프론트는 operation API를 폴링한다.
요구사항: uv, Docker + Docker Compose.
uv sync --dev # 의존성 설치 (Python 3.12 자동 관리)
uv run ruff check . # 린트
uv run ruff format --check . # 포맷 검사
uv run pytest # 단위 테스트 (외부 서비스 불필요)AWS/AI 서버 없이 MinIO(S3 호환) + 모의 AI 서버로 전체 플로우를 실행:
cp .env.example .env
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d --build| 서비스 | 주소 |
|---|---|
| Backend API / Swagger | http://localhost:8000 · http://localhost:8000/docs |
| RabbitMQ 관리 UI | http://localhost:15672 (bw_user / strongpassword) |
| MinIO 콘솔 | http://localhost:9001 (minioadmin / minioadmin) |
| Mock AI 서버 | http://localhost:8001/health |
운영 배포에서는 docker-compose.local.yml 없이 실제 AWS S3(IAM/환경변수 자격증명)와 실제 AI 서버(AI_SERVER_URL)를 사용한다.
BASE를 환경에 맞게 설정: 로컬 http://localhost:8000, 운영 http://3.34.99.130:8000.
BASE=http://localhost:8000
# 0) 서버 living 확인 (ping)
curl -s $BASE/api/v1/health
# → {"status":"ok","database":"connected"}
# 0-1) AI 서버 프록시 헬스체크
curl -s $BASE/api/v1/health/ai
# → {"ai_server":"ok","gpu_available":true,"model_loaded":true} 또는 {"ai_server":"down"}
# 1) 이미지 업로드 (JPEG/PNG, ≤10MB) → task_id 수신
curl -s -X POST $BASE/api/v1/images/upload \
-F "file=@photo.jpg" \
-F "remove_metadata=true"
# → {"task_id":"<uuid>","status":"PENDING"}
# 2) 상태 폴링 (3초 간격 권장) — ANALYZED가 되면 analysis 필드에 분석 결과 포함
TASK_ID=<uuid>
curl -s $BASE/api/v1/images/$TASK_ID/status
# 3) 처리 요청 (ANALYZED 상태에서만 가능; 빈 배열이면 딥페이크 방지만 적용)
curl -s -X POST $BASE/api/v1/images/$TASK_ID/process \
-H "Content-Type: application/json" \
-d '{
"selected_regions": [
{
"detection_id": "det_plate_001",
"risk_group": "VEHICLE",
"polygon": [[820,750],[1100,750],[1100,840],[820,840]]
}
]
}'
# → {"task_id":"<uuid>","status":"PROCESSING"}
# 4) 상태 폴링 → SUCCESS가 되면 result_url 포함
curl -s $BASE/api/v1/images/$TASK_ID/status
# 5) 결과 이미지 다운로드 (result_url은 1시간 만료 presigned URL — 매 조회마다 새로 서명됨)
curl -s "$RESULT_URL" -o protected.png업로드와 최초 분석은 위 v1 API를 그대로 사용한다.
# Step 2) 버전형 보호 처리 요청
curl -s -X POST $BASE/api/v2/images/$TASK_ID/process \
-H "Content-Type: application/json" \
-d '{"selected_regions": []}'
# → {"operation_id":"<uuid>","operation_type":"PRIVACY_PROCESS","status":"QUEUED",...}
OPERATION_ID=<uuid>
curl -s $BASE/api/v2/image-operations/$OPERATION_ID
# SUCCESS 응답의 output.output_id를 다음 편집 기준으로 사용
# Step 3) 사용자 프롬프트 기반 후처리
BASE_OUTPUT_ID=<uuid>
curl -s -X POST $BASE/api/v2/images/$TASK_ID/edits \
-H "Content-Type: application/json" \
-d "{\"base_output_id\":\"$BASE_OUTPUT_ID\",\"prompt\":\"배경을 따뜻하게 바꿔줘\"}"
# → 새 operation_id와 output_version 반환v2는 image_outputs에 부모 결과와 버전을, image_operations에 비동기 상태를 저장한다.
결과 객체는 protected/v2/{task_id}/{output_id}.png에 저장하며 기존 결과를 덮어쓰지 않는다.
에러 응답 형식: {"error": {"code": "...", "message": "..."}} — 전체 에러코드 목록은 docs/INTERFACE-FOR-FRONTEND.md 참조.
uv run alembic upgrade head # 적용 (compose에서는 backend 시작 시 자동 실행)
uv run alembic revision --autogenerate -m "message" # 새 마이그레이션 생성.github/workflows/cicd.yml — main 브랜치 push / PR 시 실행:
- quality — ruff 린트/포맷 + pytest + Alembic 마이그레이션 왕복 검증
- container —
ghcr.io/tech4good-one-t/backend(API),ghcr.io/tech4good-one-t/backend-worker(worker/beat) 이미지 빌드·푸시 (latest+sha-<commit>태그) - deploy — GitHub OIDC → AWS SSM으로 backend EC2에
deploy/ec2-deploy.sh실행 (compose pull & up + 헬스체크)
deploy 활성화에 필요한 설정 (미설정 시 deploy job은 자동 skip):
| 종류 | 이름 | 값 |
|---|---|---|
| Repository variable | AWS_ROLE_ARN |
GitHub OIDC로 assume할 IAM Role ARN (SSM SendCommand + Parameter Store 권한) |
| Repository variable | EC2_INSTANCE_ID |
backend EC2 인스턴스 ID (SSM Agent 필요) |
| EC2 파일 | /opt/bridgework-backend/.env |
.env.example 기반 운영 환경변수 (최초 1회 수동 배치) |
EC2 사전 요구사항: Docker + Docker Compose + AWS CLI + SSM Agent, S3 접근용 IAM Role(infra/aws-infra-commands.sh 참조).
├── app/ # FastAPI 앱 (api/, models/, schemas/, services/, worker/)
├── alembic/ # DB 마이그레이션
├── deploy/ # 운영 배포 스크립트 + prod compose
├── docs/ # 인터페이스 계약서, AI API 명세
├── infra/ # AWS 인프라 설정 명령어 모음
├── local/mock-ai/ # 로컬 E2E용 모의 AI 서버
├── scripts/ # RabbitMQ 초기화 등
└── tests/ # pytest 단위 테스트
- Presigned URL은 절대 로깅 금지 (임시 서명 포함) — OCR 원문/EXIF/GPS도 로깅 금지
- 사용자 편집 프롬프트를 로그나 Celery 메시지 인자에 기록하지 않는다. worker는 DB에서 읽는다.
- Celery result backend 미사용 (
task_ignore_result=True) — worker가 DB에 직접 결과 기록 - 상태 전이는
SELECT ... FOR UPDATE로 직렬화, 스위퍼가 15분 이상 정체된 task를FAILURE(TASK_TIMEOUT)처리 - API 스키마 변경 시
docs/INTERFACE-FOR-*.md를 반드시 함께 갱신하고 담당자에게 공유