eunzzang's picture
chore: sync space contents
2c1dae0
|
Raw
History Blame Contribute Delete
5.25 kB
# API ๋ช…์„ธ์„œ (v1)
Base URL
```
/api/v1
```
์š”์•ฝ
- ์ฃผ์š” ๋ฆฌ์†Œ์Šค: /posts, /predict, /uploads, /stats
- ์‘๋‹ต ํฌ๋งท: JSON (HTML ํŽ˜์ด์ง€๋Š” ์›น ๋ผ์šฐํŠธ๋กœ ๋ณ„๋„ ์ œ๊ณต)
- ํ•„๋“œ ๋„ค์ด๋ฐ: snake_case
- ๋‚ ์งœ/์‹œ๊ฐ„: ISO 8601 (์˜ˆ: 2026-04-28T12:34:56Z)
๊ณตํ†ต ์—๋Ÿฌ ์‘๋‹ต (์˜ˆ์‹œ)
```json
{
"success": false,
"error": {
"code": 400,
"message": "Bad Request",
"details": null
}
}
```
์ธ์ฆ / Rate limiting
- ์ธ์ฆ: ์„ ํƒ(์˜ˆ: JWT Authorization: Bearer <token>), ํ•„์š”ํ•œ ์—”๋“œํฌ์ธํŠธ์— ํ‘œ๊ธฐ
- Rate limit: ์˜ˆ์‹œ - 60 requests/min (๋ฌธ์„œํ™” ๊ถŒ์žฅ)
๋ชจ๋ธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(๊ถŒ์žฅ ์‘๋‹ต ํ•„๋“œ)
- model_name, model_version, inference_time_ms
---
## 1. ์›น ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… (HTML)
(์›น ์„œ๋ฒ„ ํ…œํ”Œ๋ฆฟ์šฉ; API Base URL ์ ์šฉ ์—†์Œ)
- GET / โ†’ 200 HTML (index.html)
- GET /board โ†’ 200 HTML (board.html)
- GET /posts/{post_id} โ†’ 200 HTML (post detail)
---
## 2. ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ API (routers/predict.py)
### [POST] ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜
POST /api/v1/predict
Headers:
- Content-Type: multipart/form-data
Request (form-data):
- file: (required) image file, field name `file` (max 10MB, allowed: .jpg, .jpeg, .png)
Response 200:
```json
{
"success": true,
"filename": "cat.jpg",
"predicted_class": "cat",
"confidence": 0.9821,
"top_k": [
{"label":"cat","score":0.9821},
{"label":"dog","score":0.0121}
],
"model": {
"name": "classifier",
"version": "v1.0.0"
},
"inference_time_ms": 123
}
```
Errors:
- 400: missing file / invalid file type
- 413: payload too large
- 500: model inference failure
---
### [POST] ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ + ๋ถ„๋ฅ˜ + ๊ฒŒ์‹œ๊ธ€ ์ž๋™ ์ƒ์„ฑ
POST /api/v1/predict/upload
Headers:
- Content-Type: multipart/form-data
Request (form-data):
- title: string (required)
- content: string (optional)
- image: file (required) field name `image`
Response 201:
```json
{
"success": true,
"post_id": 15,
"prediction": "cat",
"confidence": 0.98,
"model": {"name":"classifier","version":"v1.0.0"}
}
```
---
### [GET] ๋ชจ๋ธ ๋ผ๋ฒจ ๋ชฉ๋ก
GET /api/v1/predict/labels
Response 200:
```json
{
"classes": ["cat","dog","car","person"]
}
```
---
## 3. ๊ฒŒ์‹œ๊ธ€ API (routers/post.py)
### [GET] ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก (ํŽ˜์ด์ง•/ํ•„ํ„ฐ)
GET /api/v1/posts
Query params:
- page: int (default 1)
- size: int (default 10)
- category: string (optional)
Response 200:
```json
{
"items": [
{
"id": 1,
"title": "๊ณ ์–‘์ด ๋ถ„๋ฅ˜ ์„ฑ๊ณต",
"prediction": "cat",
"confidence": 0.98,
"created_at": "2026-04-28T12:00:00Z"
}
],
"page": 1,
"size": 10,
"total": 34
}
```
### [GET] ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ
GET /api/v1/posts/{id}
Response 200:
```json
{
"id": 1,
"title": "๊ณ ์–‘์ด ๋ถ„๋ฅ˜ ์„ฑ๊ณต",
"content": "ํ…Œ์ŠคํŠธ ๊ธ€",
"image_url": "/uploads/cat.jpg",
"prediction": "cat",
"confidence": 0.98,
"created_at": "2026-04-28T12:00:00Z"
}
```
404: post not found
### [POST] ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ
POST /api/v1/posts
Headers:
- Content-Type: application/json
Request body:
```json
{
"title":"์ƒˆ ๊ฒŒ์‹œ๊ธ€",
"content":"๋‚ด์šฉ",
"image_url":"/uploads/sample.jpg",
"prediction":"cat",
"confidence":0.95
}
```
Response 201:
```json
{"success": true, "id": 123}
```
Validation: title required, image_url optional, confidence 0.0-1.0
### [PUT] ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •
PUT /api/v1/posts/{id}
Request body (partial ํ—ˆ์šฉ):
```json
{"title":"์ˆ˜์ • ์ œ๋ชฉ","content":"์ˆ˜์ • ๋‚ด์šฉ"}
```
Response 200: {"success": true}
### [DELETE] ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ
DELETE /api/v1/posts/{id}
Response 200:
```json
{"success": true, "message": "์‚ญ์ œ ์™„๋ฃŒ"}
```
---
## 4. ์ข‹์•„์š” / ์ถ”์ฒœ
POST /api/v1/posts/{id}/like
Response 200:
```json
{"success": true, "likes": 12}
```
---
## 5. ํ†ต๊ณ„ API (๋Œ€์‹œ๋ณด๋“œ์šฉ)
GET /api/v1/stats/classes
Query params (optional):
- start_date, end_date (ISO 8601)
Response 200:
```json
{"cat":34,"dog":20,"car":14}
```
---
## ๋ฐ์ดํ„ฐ/์‘๋‹ต ์Šคํ‚ค๋งˆ (schemas.py)
PostCreate
- title: string (required)
- content: string (optional)
- image_url: string (optional, ๊ฒฝ๋กœ)
- prediction: string (optional)
- confidence: float (0.0 - 1.0, optional)
PostResponse
- id: int
- title: string
- content: string
- image_url: string
- prediction: string
- confidence: float
- created_at: datetime (ISO 8601)
PredictResponse
- success: bool
- filename: string
- predicted_class: string
- confidence: float
- top_k: [{label: string, score: float}]
- model: {name:string, version:string}
- inference_time_ms: int
ErrorResponse
- success: false
- error: {code:int, message:string, details:object|null}
---
## ๊ตฌํ˜„/์šด์˜ ๊ถŒ์žฅ์‚ฌํ•ญ
- ๋ชจ๋“  API๋Š” /api/v1/ ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฒ„์ „ ๊ด€๋ฆฌ
- ์š”์ฒญ/์‘๋‹ต ์˜ˆ์‹œ๋Š” OpenAPI(Swagger)๋กœ ์ž‘์„ฑํ•ด ์ž๋™ ๋ฌธ์„œํ™” ๊ถŒ์žฅ
- ํŒŒ์ผ ์—…๋กœ๋“œ๋Š” ์ €์žฅ์†Œ ์šฉ๋Ÿ‰, ํ™•์žฅ์ž ๊ฒ€์‚ฌ, ์•…์„ฑ ํŒŒ์ผ ๊ฒ€์‚ฌ ๊ตฌํ˜„
- ๋ฏผ๊ฐํ•œ ํŒŒ์ผ ์—…๋กœ๋“œ๋Š” ์ธ์ฆ/ACL ์ ์šฉ
- ๋ชจ๋ธ ๋ฒ„์ „ ๊ด€๋ฆฌ ๋ฐ A/B ํ…Œ์ŠคํŠธ ๋กœ๊ทธ ๋‚จ๊ธฐ๊ธฐ
- ์ž์„ธํ•œ ๋กœ๊น…(์š”์ฒญ id, inference time, model version)์œผ๋กœ ๋ฌธ์ œ ์ถ”์ 
---