Nebula AI API는 Spring Boot 서버와 AI 서버(FastAPI) 간의 통신을 위한 RESTful API입니다. CQRS 패턴을 기반으로 하여 읽기와 쓰기 작업을 효율적으로 분리했습니다.
- 기본 URL:
http://localhost:8000 - API 버전:
v1 - 인증: API 키 기반 (개발 중)
- Content-Type:
application/json - 문자 인코딩:
UTF-8
- User Profile API - 사용자 프로필 관리 (CQRS Query Side)
- Chat Stream API - 실시간 채팅 및 RAG 검색
- Health Check API - 서비스 상태 확인
사용자의 프로필 정보를 조회합니다.
엔드포인트
GET /api/v1/profiles/{user_id}
요청 매개변수
| 매개변수 | 타입 | 필수 | 설명 |
|---|---|---|---|
user_id |
integer | 필수 | 사용자 ID (경로 매개변수) |
include_metadata |
boolean | 선택 | 메타데이터 포함 여부 (기본값: false) |
응답 스키마
{
"user_id": 123,
"profile_vector": [0.1, 0.2, ...],
"last_updated": "2024-01-15T10:30:00Z",
"vector_strength": 0.85,
"completeness_score": 0.92,
"created_at": "2024-01-01T00:00:00Z",
"vector_metadata": {
"source": "bookmark_analysis",
"update_count": 15
},
"update_count": 15,
"last_similarity_update": "2024-01-15T08:20:00Z"
}응답 코드
200 OK: 성공404 Not Found: 사용자 프로필을 찾을 수 없음500 Internal Server Error: 서버 오류
사용 예시
curl -X GET "http://localhost:8000/api/v1/profiles/123?include_metadata=true"현재 사용자와 유사한 관심사를 가진 사용자들을 검색합니다.
엔드포인트
GET /api/v1/profiles/{user_id}/similar
요청 매개변수
| 매개변수 | 타입 | 필수 | 설명 |
|---|---|---|---|
user_id |
integer | 필수 | 기준 사용자 ID |
limit |
integer | 선택 | 반환할 사용자 수 (1-50, 기본값: 10) |
min_similarity |
float | 선택 | 최소 유사도 임계값 (0.0-1.0, 기본값: 0.5) |
응답 스키마
{
"user_id": 123,
"similar_users": [
{
"user_id": 456,
"similarity_score": 0.78,
"shared_interests": ["AI", "Machine Learning", "Python"],
"last_updated": "2024-01-15T10:30:00Z"
}
],
"total_found": 5,
"search_criteria": {
"min_similarity": 0.5,
"limit": 10
}
}사용 예시
curl -X GET "http://localhost:8000/api/v1/profiles/123/similar?limit=20&min_similarity=0.7"사용자별 맞춤 추천 콘텐츠를 조회합니다.
엔드포인트
GET /api/v1/profiles/{user_id}/recommendations
요청 매개변수
| 매개변수 | 타입 | 필수 | 설명 |
|---|---|---|---|
user_id |
integer | 필수 | 사용자 ID |
category |
string | 선택 | 추천 카테고리 필터 |
max_age_hours |
integer | 선택 | 추천 최대 나이(시간) (1-168, 기본값: 24) |
응답 스키마
{
"user_id": 123,
"recommendations": [
{
"id": "rec_001",
"type": "content",
"title": "머신러닝 트렌드 분석",
"description": "2024년 최신 ML 동향",
"score": 0.92,
"metadata": {
"source": "bookmark_analysis",
"category": "technology"
},
"created_at": "2024-01-15T10:00:00Z"
}
],
"generated_at": "2024-01-15T10:00:00Z",
"cache_status": "HIT",
"refresh_requested": false
}사용자의 관심사를 키워드와 토픽 수준에서 분석합니다.
엔드포인트
GET /api/v1/profiles/{user_id}/interests
요청 매개변수
| 매개변수 | 타입 | 필수 | 설명 |
|---|---|---|---|
user_id |
integer | 필수 | 사용자 ID |
include_keywords |
boolean | 선택 | 키워드 분석 포함 (기본값: true) |
include_topics |
boolean | 선택 | 토픽 분석 포함 (기본값: true) |
응답 스키마
{
"user_id": 123,
"keyword_analysis": {
"top_keywords": [
{"keyword": "AI", "weight": 0.95, "frequency": 45},
{"keyword": "Python", "weight": 0.87, "frequency": 32}
],
"trending_keywords": ["GPT-4", "LangChain"],
"keyword_evolution": {
"emerging": ["Vector DB", "RAG"],
"declining": ["TensorFlow 1.x"]
}
},
"topic_analysis": {
"primary_topics": [
{"topic": "Machine Learning", "confidence": 0.89},
{"topic": "Software Development", "confidence": 0.76}
],
"topic_distribution": {
"technology": 0.65,
"science": 0.25,
"business": 0.10
}
},
"analysis_metadata": {
"last_updated": "2024-01-15T10:30:00Z",
"data_points": 150,
"confidence": 0.87
}
}사용자 프로필의 상세 메트릭 정보를 조회합니다.
엔드포인트
GET /api/v1/profiles/{user_id}/metrics
응답 스키마
{
"user_id": 123,
"quality_metrics": {
"completeness_score": 0.92,
"vector_strength": 0.85,
"activity_level": 0.78,
"diversity_score": 0.91,
"recency_score": 0.88,
"overall_quality": 0.87
},
"activity_metrics": {
"total_bookmarks": 245,
"recent_activity": 15,
"engagement_score": 0.76,
"session_count": 89
},
"update_metrics": {
"last_updated": "2024-01-15T10:30:00Z",
"update_frequency": "daily",
"next_scheduled_update": "2024-01-16T02:00:00Z",
"update_count": 15
}
}비동기 작업의 진행 상태를 조회합니다.
엔드포인트
GET /api/v1/profiles/jobs/{job_id}/status
응답 스키마
{
"job_id": "job_12345",
"status": "PENDING",
"progress": 45,
"message": "프로필 벡터 업데이트 중...",
"started_at": "2024-01-15T10:00:00Z",
"estimated_completion": "2024-01-15T10:05:00Z",
"result": null
}작업 상태
PENDING: 대기 중RUNNING: 실행 중SUCCESS: 완료FAILED: 실패CANCELLED: 취소됨
RAG 기반 스트리밍 채팅 응답을 제공합니다.
엔드포인트
POST /api/v1/chat/stream
요청 스키마
{
"user_id": 123,
"message": "AI에 대해 설명해주세요",
"session_id": "session_abc123",
"context": {
"include_history": true,
"max_history": 10,
"search_similar": true
}
}응답 (Server-Sent Events)
data: {"type": "token", "content": "AI는", "timestamp": "2024-01-15T10:30:00Z"}
data: {"type": "token", "content": " 인공지능으로", "timestamp": "2024-01-15T10:30:01Z"}
data: {"type": "reference", "content": {"source": "bookmark_123", "title": "AI 기초"}}
data: {"type": "complete", "total_tokens": 150, "session_id": "session_abc123"}
요청 매개변수
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
user_id |
integer | 필수 | 사용자 ID |
message |
string | 필수 | 사용자 메시지 |
session_id |
string | 선택 | 세션 ID (연속 대화용) |
context.include_history |
boolean | 선택 | 대화 히스토리 포함 |
context.max_history |
integer | 선택 | 최대 히스토리 수 |
context.search_similar |
boolean | 선택 | 유사 콘텐츠 검색 |
스트리밍 이벤트 타입
token: 텍스트 토큰reference: 참조 정보complete: 응답 완료error: 오류 발생
엔드포인트
GET /health
응답 스키마
{
"status": "healthy",
"services": {
"database": "connected",
"rabbitmq": "connected",
"redis": "connected",
"vector_db": "connected"
},
"version": "1.0.0",
"uptime": "2 days, 3 hours",
"last_check": "2024-01-15T10:30:00Z"
}엔드포인트
GET /
응답 스키마
{
"message": "Nebula AI - User Profile API",
"version": "1.0.0",
"endpoints": {
"profiles": "/api/v1/profiles",
"docs": "/docs",
"health": "/health"
}
}모든 API는 다음 형식의 에러 응답을 반환합니다:
{
"detail": "User profile not found",
"error_code": "PROFILE_NOT_FOUND",
"timestamp": "2024-01-15T10:30:00Z",
"request_id": "req_12345"
}| 코드 | HTTP 상태 | 설명 |
|---|---|---|
PROFILE_NOT_FOUND |
404 | 사용자 프로필을 찾을 수 없음 |
INVALID_USER_ID |
400 | 잘못된 사용자 ID |
VECTOR_NOT_READY |
404 | 프로필 벡터가 아직 생성되지 않음 |
SIMILARITY_CALCULATION_FAILED |
500 | 유사도 계산 실패 |
RECOMMENDATION_SERVICE_ERROR |
503 | 추천 서비스 오류 |
DATABASE_CONNECTION_ERROR |
503 | 데이터베이스 연결 오류 |
curl -X GET "http://localhost:8000/api/v1/profiles/123" \
-H "Authorization: Bearer YOUR_API_KEY"- 기본 제한: 100 요청/분
- 버스트 제한: 10 요청/초
- 헤더:
X-RateLimit-Remaining,X-RateLimit-Reset
- 허용 Origin: 개발 시
*, 프로덕션에서는 특정 도메인으로 제한 - 허용 메소드:
GET,POST,PUT,DELETE - 허용 헤더:
Content-Type,Authorization
@Service
public class ProfileService {
@Value("${ai.server.base-url}")
private String aiServerUrl;
private final RestTemplate restTemplate;
public UserProfile getUserProfile(Long userId) {
String url = aiServerUrl + "/api/v1/profiles/" + userId;
try {
ResponseEntity<UserProfileResponse> response =
restTemplate.getForEntity(url, UserProfileResponse.class);
return response.getBody();
} catch (HttpClientErrorException.NotFound e) {
throw new UserProfileNotFoundException(userId);
}
}
public List<SimilarUser> getSimilarUsers(Long userId, int limit) {
String url = aiServerUrl + "/api/v1/profiles/" + userId + "/similar";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("limit", limit)
.queryParam("min_similarity", 0.7);
ResponseEntity<SimilarUsersResponse> response =
restTemplate.getForEntity(builder.toUriString(), SimilarUsersResponse.class);
return response.getBody().getSimilarUsers();
}
}// 사용자 프로필 조회
async function getUserProfile(userId) {
const response = await fetch(`/api/v1/profiles/${userId}?include_metadata=true`);
if (!response.ok) {
throw new Error(`Failed to fetch profile: ${response.status}`);
}
return response.json();
}
// 스트리밍 채팅
async function startChatStream(userId, message) {
const response = await fetch('/api/v1/chat/stream', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: userId,
message: message,
context: {
include_history: true,
search_similar: true
}
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
handleStreamEvent(data);
}
}
}
}
function handleStreamEvent(event) {
switch (event.type) {
case 'token':
appendToken(event.content);
break;
case 'reference':
addReference(event.content);
break;
case 'complete':
finalizeResponse(event);
break;
}
}- URL:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc - OpenAPI JSON:
http://localhost:8000/openapi.json
# API 테스트 실행
pytest tests/integration/test_api.py -v
# 특정 엔드포인트 테스트
pytest tests/integration/test_profile_api.py::test_get_user_profile -v
# 성능 테스트
pytest tests/performance/test_api_performance.py -v- Health Check:
/health엔드포인트를 통한 서비스 상태 확인 - 메트릭: Prometheus 메트릭 수집 (개발 중)
- 로그: 구조화된 JSON 로그 형식
이 API 문서는 Nebula AI 시스템의 모든 외부 인터페이스를 다루며, 지속적으로 업데이트됩니다. 추가 질문이나 지원이 필요한 경우 개발팀에 문의해주세요.