# API 레퍼런스 > Base URL: `http://localhost:8000/api/v1` > 인증: `Authorization: Bearer ` --- ## 인증 (Auth) ### POST `/auth/register` 회원가입 후 토큰을 발급한다. **Request Body:** ```json { "email": "user@example.com", "password": "securepassword", "full_name": "홍길동" } ``` **Response (201):** ```json { "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer" } ``` **에러:** - `409` — 이미 등록된 이메일 --- ### POST `/auth/login` 이메일/비밀번호로 로그인한다. **Request Body:** ```json { "email": "user@example.com", "password": "securepassword" } ``` **Response (200):** ```json { "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer" } ``` **에러:** - `401` — 잘못된 이메일/비밀번호 또는 비활성 계정 --- ### POST `/auth/refresh` 리프레시 토큰으로 새 토큰 쌍을 발급한다. 기존 리프레시 토큰은 폐기된다. **Request Body:** ```json { "refresh_token": "eyJ..." } ``` **Response (200):** ```json { "access_token": "eyJ...(new)", "refresh_token": "eyJ...(new)", "token_type": "bearer" } ``` --- ### POST `/auth/logout` 현재 사용자의 모든 리프레시 토큰을 폐기한다. **Headers:** `Authorization: Bearer ` **Response:** `204 No Content` --- ## 사용자 (Users) ### GET `/users/me` 현재 로그인한 사용자의 정보를 조회한다. **Response (200):** ```json { "id": 1, "email": "user@example.com", "role": "user", "is_active": true, "is_verified": false, "full_name": "홍길동", "phone": "010-1234-5678", "organization": "ACME Corp", "avatar_url": "", "created_at": "2025-01-01T00:00:00" } ``` --- ### PATCH `/users/me` 자신의 프로필 정보를 수정한다. `role`과 `is_active`는 변경할 수 없다. **Request Body (partial):** ```json { "full_name": "김철수", "phone": "010-9999-8888" } ``` --- ### GET `/users` 사용자 목록을 페이징 조회한다. **권한:** SUPERADMIN, ADMIN **Query Parameters:** | 파라미터 | 타입 | 기본값 | 설명 | |---------|------|--------|------| | page | int | 1 | 페이지 번호 | | size | int | 20 | 페이지 크기 (max 100) | **Response (200):** ```json { "items": [{ ... }], "total": 150, "page": 1, "size": 20, "pages": 8 } ``` --- ### GET `/users/{user_id}` 특정 사용자를 조회한다. **권한:** SUPERADMIN, ADMIN --- ### POST `/users` 사용자를 생성한다. **권한:** SUPERADMIN, ADMIN **Request Body:** ```json { "email": "new@example.com", "password": "password123", "role": "manager", "full_name": "박매니저", "phone": "010-1111-2222", "organization": "Dev Team" } ``` --- ### PATCH `/users/{user_id}` 사용자 정보를 수정한다. 관리자는 역할과 활성 상태도 변경할 수 있다. **권한:** SUPERADMIN, ADMIN --- ### DELETE `/users/{user_id}` 사용자를 소프트 삭제한다. **권한:** SUPERADMIN, ADMIN **Response:** `204 No Content` --- ## 디바이스 (Devices) ### GET `/devices` 디바이스 목록을 페이징 조회한다. **Query Parameters:** | 파라미터 | 타입 | 기본값 | 설명 | |---------|------|--------|------| | page | int | 1 | 페이지 번호 | | size | int | 20 | 페이지 크기 (max 100) | **Response (200):** ```json { "items": [ { "id": 1, "device_uid": "sensor-temp-001", "name": "1층 온도센서", "device_type": "temperature", "status": "online", "firmware_version": "1.2.0", "ip_address": "192.168.1.100", "group_id": 1, "owner_id": 2, "last_seen_at": "2025-01-15T12:00:00", "created_at": "2025-01-01T00:00:00" } ], "total": 50, "page": 1, "size": 20, "pages": 3 } ``` --- ### GET `/devices/{device_id}` 특정 디바이스 상세를 조회한다. --- ### POST `/devices` 디바이스를 등록한다. **권한:** SUPERADMIN, ADMIN, MANAGER **Request Body:** ```json { "device_uid": "sensor-temp-001", "name": "1층 온도센서", "device_type": "temperature", "group_id": 1, "owner_id": 2, "firmware_version": "1.0.0" } ``` **에러:** - `409` — 이미 등록된 device_uid --- ### PATCH `/devices/{device_id}` 디바이스 정보를 수정한다. **권한:** SUPERADMIN, ADMIN, MANAGER **Request Body (partial):** ```json { "name": "수정된 센서명", "status": "maintenance" } ``` --- ### DELETE `/devices/{device_id}` 디바이스를 소프트 삭제한다. **권한:** SUPERADMIN, ADMIN **Response:** `204 No Content` --- ## 모니터링 (Monitoring) ### GET `/monitoring/health` 시스템 상태를 상세 조회한다. **권한:** SUPERADMIN, ADMIN, MANAGER **Response (200):** ```json { "status": "ok", "mariadb": "connected", "mongodb": "connected", "redis": "connected", "mqtt": "connected", "active_devices": 42, "active_alerts": 3 } ``` --- ### GET `/monitoring/alerts` 미확인 알림 목록을 조회한다. **권한:** SUPERADMIN, ADMIN, MANAGER **Query Parameters:** | 파라미터 | 타입 | 기본값 | 설명 | |---------|------|--------|------| | skip | int | 0 | 건너뛸 수 | | limit | int | 50 | 최대 개수 (max 200) | **Response (200):** ```json [ { "id": 1, "rule_id": 3, "device_id": 5, "severity": "warning", "message": "Temperature exceeded threshold", "is_acknowledged": false, "acknowledged_by": null, "acknowledged_at": null, "created_at": "2025-01-15T10:30:00" } ] ``` --- ### POST `/monitoring/alerts/{alert_id}/acknowledge` 알림을 확인 처리한다. --- ### GET `/monitoring/alert-rules` 알림 규칙 목록을 조회한다. --- ### POST `/monitoring/alert-rules` 알림 규칙을 생성한다. **Request Body:** ```json { "name": "고온 경고", "description": "온도가 40도를 초과하면 알림", "metric": "temperature", "condition": "gt", "threshold": 40.0, "severity": "warning", "device_group_id": 1 } ``` --- ## 분석 (Analytics) ### GET `/analytics/telemetry/{device_id}` 특정 디바이스의 텔레메트리 데이터를 시간 간격별로 집계한다. **권한:** SUPERADMIN, ADMIN, MANAGER **Query Parameters:** | 파라미터 | 타입 | 필수 | 설명 | |---------|------|------|------| | start | datetime | O | 시작 시각 (ISO 8601) | | end | datetime | O | 종료 시각 (ISO 8601) | | interval | string | X | 집계 간격 (기본값: `1h`) | **Response (200):** ```json { "device_id": "sensor-temp-001", "records": [ {"timestamp": "2025-01-15T10:00:00", "temperature": 23.5, "humidity": 45.2}, {"timestamp": "2025-01-15T11:00:00", "temperature": 24.1, "humidity": 44.8} ], "count": 2 } ``` --- ### POST `/analytics/reports/{device_id}` 디바이스 종합 리포트를 생성한다 (상태 분석 + 추세 분석). **Query Parameters:** `start`, `end` (ISO 8601) **Response (200):** ```json { "report_id": "65a1b2c3...", "device_id": "sensor-temp-001", "status": { "total_events": 150, "status_counts": {"online": 140, "offline": 10}, "uptime_ratio": 0.9333 }, "trends": { "count": 720, "mean": 23.5, "std": 1.2, "min": 20.1, "max": 28.3, "slope": 0.0023, "trend": "stable" }, "created_at": "2025-01-15T12:00:00" } ``` --- ### GET `/analytics/status/{device_id}` 디바이스 상태 변경 이력을 분석한다. --- ### GET `/analytics/trends/{device_id}` 텔레메트리 데이터의 추세를 분석한다 (선형 회귀). --- ### GET `/analytics/results` 저장된 분석 결과를 조회한다. **Query Parameters:** | 파라미터 | 타입 | 필수 | 설명 | |---------|------|------|------| | analysis_type | string | O | 분석 유형 | | device_id | string | X | 디바이스 ID | | skip | int | X | 건너뛸 수 (기본 0) | | limit | int | X | 최대 개수 (기본 20) | --- ## 시스템 (System) ### GET `/system/health` 서비스 헬스체크. 인증 불필요. **Response (200):** ```json { "status": "ok", "service": "core-api", "version": "0.1.0" } ``` --- ### GET `/system/info` 시스템 설정 정보를 조회한다. **권한:** SUPERADMIN --- ## 공통 에러 응답 모든 에러는 다음 형식으로 반환된다: ```json { "detail": "에러 메시지" } ``` | 상태 코드 | 설명 | |----------|------| | 401 | 인증 실패 (토큰 없음/만료/유효하지 않음) | | 403 | 권한 부족 | | 404 | 리소스를 찾을 수 없음 | | 409 | 리소스 충돌 (중복) | | 422 | 요청 데이터 검증 실패 | | 429 | 요청 속도 제한 초과 | | 500 | 서버 내부 오류 | --- ## Socket.IO 이벤트 > 연결: `io("http://localhost:8000", { path: "/socket.io/" })` ### 네임스페이스: `/monitoring` | 이벤트 | 방향 | 데이터 | 설명 | |--------|------|--------|------| | `subscribe_device` | Client → Server | `{ device_uid }` | 디바이스 모니터링 구독 | | `unsubscribe_device` | Client → Server | `{ device_uid }` | 구독 해제 | | `telemetry` | Server → Client | `{ device_uid, data }` | 실시간 텔레메트리 | | `device_status` | Server → Client | `{ device_uid, status }` | 상태 변경 | ### 네임스페이스: `/device` | 이벤트 | 방향 | 데이터 | 설명 | |--------|------|--------|------| | `send_command` | Client → Server | `{ device_uid, command }` | 디바이스 명령 전송 | | `device_response` | Server → Client | `{ device_uid, data }` | 명령 응답 | ### 네임스페이스: `/notification` | 이벤트 | 방향 | 데이터 | 설명 | |--------|------|--------|------| | `join_user_room` | Client → Server | `{ user_id }` | 알림 수신 등록 | | `notification` | Server → Client | `{ title, message, type }` | 알림 푸시 | --- ## MQTT 토픽 > 브로커: `mqtt://localhost:1883` ### Device → Server | 토픽 | 페이로드 | 처리 | |------|---------|------| | `devices/{uid}/telemetry` | `{ temperature: 23.5, ... }` | MongoDB 저장 + Socket.IO 브로드캐스트 | | `devices/{uid}/status` | `{ status: "online" }` | MongoDB 로그 + Socket.IO 전송 | | `devices/{uid}/log` | `{ event_type: "...", ... }` | MongoDB 저장 | | `devices/{uid}/response` | `{ command_id: "...", ... }` | Socket.IO 전송 | ### Server → Device | 토픽 | 페이로드 | 용도 | |------|---------|------| | `devices/{uid}/command` | `{ action: "restart" }` | 원격 명령 | | `devices/{uid}/config` | `{ interval: 30 }` | 설정 변경 | | `devices/{uid}/ota` | `{ url: "...", action: "update" }` | 펌웨어 업데이트 |