feat : initial commit
HealthSync Intelligence CI / build-and-push (push) Has been cancelled

This commit is contained in:
hyerimmy
2025-06-20 05:28:30 +00:00
commit 910bd902b1
72 changed files with 6758 additions and 0 deletions
View File
+60
View File
@@ -0,0 +1,60 @@
"""
HealthSync AI 기본 컨트롤러 클래스
"""
from fastapi import HTTPException, status
from typing import Any
from fastapi.params import Depends
from app.core.dependencies import get_settings
from app.models.base import BaseResponse, ErrorResponse
from app.config.settings import settings, Settings
import logging
from datetime import datetime
class BaseController:
"""기본 컨트롤러 클래스"""
def __init__(self):
self.settings = settings
self.logger = logging.getLogger(self.__class__.__name__)
def create_success_response(self, data: Any = None, message: str = "성공적으로 처리되었습니다.") -> BaseResponse:
"""성공 응답 생성"""
return BaseResponse(success=True, message=message, data=data, timestamp=datetime.now())
def handle_service_error(self, error: Exception, operation: str = "unknown"):
"""서비스 에러 처리"""
self.logger.error(f"Service error in {operation}: {str(error)}", exc_info=True)
if isinstance(error, ValueError):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error))
else:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="서버 내부 오류가 발생했습니다.")
def log_request(self, endpoint: str, user_id: int = None, **kwargs):
"""요청 로그 기록"""
log_data = {"endpoint": endpoint, "controller": self.__class__.__name__, "timestamp": datetime.now().isoformat()}
if user_id:
log_data["user_id"] = user_id
log_data.update(kwargs)
self.logger.info(f"Request to {endpoint}", extra=log_data)
def handle_service_error(self, error: Exception, operation: str = "unknown"):
"""서비스 에러 처리"""
self.logger.error(f"Service error in {operation}: {str(error)}", exc_info=True)
if isinstance(error, ValueError):
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error))
elif "찾을 수 없습니다" in str(error) or "없음" in str(error):
# 데이터 조회 실패인 경우 404로 처리
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(error))
elif "Claude API" in str(error) or "AI" in str(error):
# AI 서비스 오류인 경우 구체적 메시지 전달
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"AI 서비스 오류: {str(error)}")
elif "데이터베이스" in str(error) or "쿼리" in str(error):
# 데이터베이스 오류인 경우
raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=f"데이터베이스 오류: {str(error)}")
else:
# 기타 오류는 구체적 메시지와 함께 500으로 처리
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(error))
+124
View File
@@ -0,0 +1,124 @@
# app/controllers/chat_controller.py
"""
HealthSync AI 챗봇 상담 컨트롤러
"""
from fastapi import APIRouter, status, HTTPException, Query
from app.controllers.base_controller import BaseController
from app.services.chat_service import ChatService
from app.dto.request.chat_request import ChatRequest
from app.dto.response.chat_response import ChatResponse
from app.dto.response.chat_history_response import ChatHistoryResponse
class ChatController(BaseController):
"""챗봇 상담 관련 컨트롤러"""
def __init__(self):
super().__init__()
self.chat_service = ChatService()
self.router = APIRouter()
self._setup_routes()
def _setup_routes(self):
"""라우트 설정"""
@self.router.post("/consultation",
response_model=ChatResponse,
status_code=status.HTTP_200_OK,
summary="💬 AI 건강 상담 챗봇",
description="""
사용자의 건강검진 데이터를 기반으로 AI가 개인화된 건강 상담을 제공합니다.
**처리 과정:**
1. 사용자 질문 데이터베이스에 저장
2. 사용자 기본 정보 조회 (직업, 나이 등)
3. 최신 건강검진 데이터 조회
4. 사용자 질문과 건강 데이터를 Claude AI로 분석
5. 맞춤형 건강 상담 답변 생성
6. 질문에 대한 응답 내용을 데이터베이스에 저장
**상담 특징:**
- 개인 건강 데이터 기반 맞춤형 답변
- 직업 특성을 고려한 건강 조언
- 의학적 근거에 기반한 정확한 정보 제공
- 실질적이고 실행 가능한 건강 관리 방법 제시
- 모든 상담 내용 자동 저장 및 이력 관리
**주의사항:**
- 이 서비스는 의학적 진단이나 치료를 대체하지 않습니다
- 심각한 증상이 있을 경우 반드시 의료진과 상담하세요
""")
async def health_consultation(request: ChatRequest) -> ChatResponse:
"""AI 기반 건강 상담 챗봇 (DB 저장 포함)"""
try:
self.log_request("health_consultation", user_id=request.user_id,
message_preview=request.message[:50] + "..." if len(request.message) > 50 else request.message)
# 챗봇 상담 서비스 호출 (DB 저장 포함)
response = await self.chat_service.get_health_consultation(
user_id=request.user_id,
message=request.message
)
self.logger.info(f"건강 상담 성공 - user_id: {request.user_id}, "
f"질문 길이: {len(request.message)}, 답변 길이: {len(response.response)}")
return response
except ValueError as e:
self.logger.warning(f"잘못된 요청 - user_id: {request.user_id}, error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"잘못된 요청입니다: {str(e)}"
)
except Exception as e:
self.handle_service_error(e, "health_consultation")
@self.router.get("/history",
response_model=ChatHistoryResponse,
status_code=status.HTTP_200_OK,
summary="📋 채팅 히스토리 조회",
description="""
사용자의 모든 채팅 기록을 조회합니다.
**처리 과정:**
1. 사용자 ID로 데이터베이스에서 채팅 기록 조회
2. 시간 역순으로 정렬하여 반환
3. 질문과 응답을 모두 포함한 전체 이력 제공
**응답 특징:**
- 최신 채팅이 먼저 표시됨 (시간 역순)
- 페이지네이션 없이 전체 기록 반환
- 메시지 타입별 구분 (상담, 축하, 독려 등)
- 각 채팅의 고유 ID와 생성 시간 포함
**활용 방안:**
- 이전 상담 내용 참고
- 건강 관리 진행 상황 확인
- AI 응답 품질 개선을 위한 피드백 수집
""")
async def get_chat_history(user_id: int = Query(..., gt=0, description="사용자 ID")) -> ChatHistoryResponse:
"""사용자 채팅 히스토리 조회"""
try:
self.log_request("get_chat_history", user_id=user_id)
# 채팅 이력 서비스 호출
response = await self.chat_service.get_chat_history(user_id)
self.logger.info(f"채팅 이력 조회 성공 - user_id: {user_id}, "
f"총 채팅 수: {response.total_count}")
return response
except ValueError as e:
self.logger.warning(f"잘못된 요청 - user_id: {user_id}, error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"잘못된 요청입니다: {str(e)}"
)
except Exception as e:
self.handle_service_error(e, "get_chat_history")
# 컨트롤러 인스턴스 생성
chat_controller = ChatController()
+70
View File
@@ -0,0 +1,70 @@
# app/controllers/health_controller.py
"""
HealthSync AI 건강 분석 컨트롤러
"""
from fastapi import APIRouter, status, HTTPException, Query
from app.controllers.base_controller import BaseController
from app.services.health_service import HealthService
from app.dto.response.health_response import HealthDiagnosisResponse
class HealthController(BaseController):
"""건강 분석 관련 컨트롤러"""
def __init__(self):
super().__init__()
self.health_service = HealthService()
self.router = APIRouter()
self._setup_routes()
def _setup_routes(self):
"""라우트 설정"""
@self.router.get("/diagnosis",
response_model=HealthDiagnosisResponse,
status_code=status.HTTP_200_OK,
summary="🔬 AI 건강검진 3줄 요약 진단",
description="""
사용자의 건강검진 데이터를 기반으로 AI가 3줄로 요약 진단을 제공합니다.
**처리 과정:**
1. 사용자 기본 정보 조회 (직업, 나이 등)
2. 최신 건강검진 데이터 조회
3. Claude AI를 통한 의학적 분석
4. 3문장으로 구성된 요약 진단 반환
**진단 특징:**
- 객관적이고 정확한 의학적 판단
- 가장 중요한 건강 지표 우선 분석
- 직업 특성을 고려한 맞춤형 조언
- 개선점과 긍정적 요소의 균형 있는 제시
""")
async def get_health_diagnosis(user_id: int = Query(..., gt=0, description="사용자 ID")) -> HealthDiagnosisResponse:
"""AI 기반 건강검진 3줄 요약 진단"""
try:
self.log_request("get_health_diagnosis", user_id=user_id)
# 건강 진단 서비스 호출
diagnosis = await self.health_service.get_three_sentence_diagnosis(user_id)
# 응답 생성
response = HealthDiagnosisResponse(threeSentenceSummary=diagnosis)
self.logger.info(f"건강 진단 성공 - user_id: {user_id}, "
f"진단 길이: {len(diagnosis)} 문자")
return response
except ValueError as e:
# 사용자나 데이터를 찾을 수 없는 경우
self.logger.warning(f"데이터 없음 - user_id: {user_id}, error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=str(e)
)
except Exception as e:
self.handle_service_error(e, "get_health_diagnosis")
# 컨트롤러 인스턴스 생성
health_controller = HealthController()
+295
View File
@@ -0,0 +1,295 @@
# app/controllers/mission_controller.py
"""
HealthSync AI 미션 관련 컨트롤러 (다층 특성 기반 AI 이모지 자동 매핑)
"""
from fastapi import APIRouter, status, HTTPException, Query
from app.controllers.base_controller import BaseController
from app.services.mission_service import MissionService
from app.dto.request.mission_request import MissionRecommendRequest
from app.dto.response.mission_response import MissionRecommendationResponse
from app.dto.request.celebration_request import CelebrationRequest
from app.dto.response.celebration_response import CelebrationResponse
from app.dto.response.similar_mission_news_response import SimilarMissionNewsResponse
from app.exceptions import (
UserNotFoundException,
HealthDataNotFoundException,
DatabaseException,
ClaudeAPIException
)
class MissionController(BaseController):
"""미션 관련 컨트롤러 (다층 특성 기반 AI 이모지 자동 매핑)"""
def __init__(self):
super().__init__()
self.mission_service = MissionService()
self.router = APIRouter()
self._setup_routes()
def _setup_routes(self):
"""라우트 설정"""
@self.router.post("/recommend",
response_model=MissionRecommendationResponse,
status_code=status.HTTP_200_OK,
summary="🎯 AI 건강 미션 추천",
description="""
사용자의 건강검진 데이터를 기반으로 AI가 맞춤형 건강 미션을 추천합니다.
**처리 과정:**
1. 사용자 기본 정보 조회 (직업, 나이 등)
2. 최신 건강검진 데이터 조회
3. Claude AI를 통한 개인화된 미션 생성
4. 미션별 추천 이유와 함께 반환
**추천 미션 특징:**
- 일일 목표 횟수 1-5회 범위
- 사용자 건강 상태에 맞춤화
- 일상에서 실행 가능한 건강 행동
- 각 미션별 상세한 추천 이유 제공
""")
async def recommend_missions(request: MissionRecommendRequest) -> MissionRecommendationResponse:
"""AI 기반 건강 미션 추천"""
try:
self.log_request("recommend_missions", user_id=request.user_id)
# 미션 추천 서비스 호출
response = await self.mission_service.recommend_missions(request.user_id)
self.logger.info(f"미션 추천 성공 - user_id: {request.user_id}, "
f"추천 미션 수: {len(response.missions)}")
return response
except ValueError as e:
self.logger.warning(f"잘못된 요청 - user_id: {request.user_id}, error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"잘못된 요청입니다: {str(e)}"
)
except Exception as e:
self.handle_service_error(e, "recommend_missions")
@self.router.post("/celebrate",
response_model=CelebrationResponse,
status_code=status.HTTP_200_OK,
summary="🎉 미션 달성 축하 메시지",
description="""
사용자가 달성한 미션에 대해 AI가 개인화된 축하 메시지를 생성합니다.
**처리 과정:**
1. 미션 ID(숫자)로 데이터베이스에서 미션 정보 조회 (미션명, 설명, 목표 등)
2. 조회된 미션 정보를 기반으로 Claude AI 호출
3. 미션 내용을 반영한 맞춤형 축하 메시지 생성
4. 생성된 축하 메시지를 Chat DB에 "celebration" 타입으로 저장
5. 이모지와 함께 1줄 축하 메시지 반환
**축하 메시지 특징:**
- DB에서 조회한 실제 미션 정보 반영
- 간결하고 따뜻한 1줄 메시지 (50자 내외)
- 다양한 이모지로 시각적 효과
- 미션별 맞춤형 축하 내용
- 지속적인 동기부여 유도
""")
async def celebrate_mission(request: CelebrationRequest) -> CelebrationResponse:
"""미션 달성 축하 메시지 생성 및 Chat DB 저장"""
try:
self.log_request("celebrate_mission",
user_id=request.userId, mission_id=request.missionId)
# 축하 메시지 서비스 호출 (Chat DB 저장 포함)
response = await self.mission_service.generate_celebration_message(
user_id=request.userId,
mission_id=request.missionId
)
self.logger.info(f"미션 축하 성공 (Chat DB 저장 완료) - user_id: {request.userId}, "
f"mission_id: {request.missionId}, "
f"메시지 길이: {len(response.congratsMessage)}")
return response
except HealthDataNotFoundException as e:
self.logger.warning(f"미션을 찾을 수 없음 - mission_id: {request.missionId}")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"미션 ID {request.missionId}를 찾을 수 없습니다."
)
except DatabaseException as e:
self.logger.error(f"데이터베이스 오류 - error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="데이터베이스 연결에 문제가 있습니다. 잠시 후 다시 시도해 주세요."
)
except ClaudeAPIException as e:
self.logger.error(f"Claude API 오류 - error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail="AI 서비스에 일시적인 문제가 있습니다. 잠시 후 다시 시도해 주세요."
)
except Exception as e:
self.handle_service_error(e, "celebrate_mission")
@self.router.get("/similar-news",
response_model=SimilarMissionNewsResponse,
status_code=status.HTTP_200_OK,
summary="🔔 유사 사용자 미션 완료 소식 (5가지 기준별 선별)",
description="""
**5가지 유사도 기준별로 각각 1명씩 총 5개의 미션 완료 소식을 조회합니다.**
### 🎯 5가지 유사도 기준:
1. **직업 유사도**: 동일 직업 또는 유사 직업군 (테크/케어/서비스)
2. **나이 유사도**: 연령대가 비슷한 사용자 (10세 차이 내)
3. **BMI/체형 유사도**: 체형이 비슷한 사용자 (마른/표준/통통)
4. **혈압 유사도**: 혈압 수치가 비슷한 사용자 (정상/주의/높음)
5. **혈당 유사도**: 혈당 수치가 비슷한 사용자 (정상/주의/높음)
### 📋 다양한 메시지 형태 (각 기준별 1개씩):
1. **직업 기준**: "IT직군 김OO님이 물마시기 미션을 완료했어요! 💧"
2. **나이 기준**: "23세 홍OO님이 산책을 완료했어요! 🚶‍♀️"
3. **체형 기준**: "통통한 박OO님이 스트레칭을 완료했어요! 🧘‍♂️"
4. **혈압 기준**: "혈압높은 이OO님이 명상을 완료했어요! 🧘‍♀️"
5. **혈당 기준**: "혈당주의 최OO님이 계단오르기를 완료했어요! 🏃‍♂️"
### ⚡ 성능 최적화:
- **빠른 이모지 매핑**: AI 대신 키워드 기반 매핑으로 빠른 응답
- **중복 제거**: 같은 사용자가 여러 기준에서 선정되는 것 방지
- **다양성 보장**: 5가지 다른 기준으로 다양한 유사성 표현
- **최소 유사도 임계값**: 0.3 이상의 유사도를 가진 사용자만 선별
### 🔄 선별 프로세스:
1. **후보 수집**: 벡터 유사도 기준 상위 30명 조회
2. **기준별 계산**: 각 후보에 대해 5가지 기준별 유사도 점수 계산
3. **최적 선별**: 각 기준별로 가장 높은 점수의 사용자 1명씩 선택
4. **중복 제거**: 동일 사용자가 여러 기준에서 선정될 경우 가장 높은 점수 기준만 적용
5. **결과 반환**: 최대 5개의 다양한 유사 사용자 소식 반환
### 💡 유사 직업군 분류:
- **테크 그룹**: 사무직(OFF001), IT직군(ENG001)
- **케어 그룹**: 의료진(MED001), 교육직(EDU001)
- **서비스 그룹**: 서비스직(SRV001)
### 🏥 건강 특성 분류:
- **BMI**: 마른(<18.5), 표준(18.5-25), 통통(≥25)
- **혈압**: 정상(<130), 주의(130-139), 높음(≥140)
- **혈당**: 정상(<100), 주의(100-125), 높음(≥126)
### 🔒 개인정보 보호:
- 이름 마스킹 처리 (김OO 형식)
- 구체적인 수치 노출 없이 특성만 표시
- 다양한 기준으로 분산하여 개인 식별 위험 최소화
**이제 5가지 다른 기준으로 선별된 다양한 유사 사용자들의 미션 완료 소식을 빠르게 확인할 수 있습니다!**
""")
async def get_similar_mission_news(
user_id: int = Query(..., gt=0, description="사용자 ID")) -> SimilarMissionNewsResponse:
"""유사 사용자 미션 완료 소식 조회 (다층 특성 기반 AI 이모지)"""
try:
self.log_request("get_similar_mission_news", user_id=user_id)
response = await self.mission_service.get_similar_mission_news(user_id)
return response
except Exception as e:
self.handle_service_error(e, "get_similar_mission_news")
@self.router.post("/upsert-vector",
status_code=status.HTTP_200_OK,
summary="📊 모든 사용자 벡터 일괄 저장/업데이트",
description="""
**모든 사용자의 건강 중심 벡터를 Pinecone DB에 일괄 저장/업데이트합니다.**
### 🔄 처리 과정:
1. **전체 사용자 조회**: PostgreSQL에서 모든 사용자 목록 조회
2. **기존 벡터 확인**: Pinecone에서 이미 저장된 벡터 ID 목록 조회
3. **신규 사용자 필터링**: 벡터가 없는 사용자만 필터링
4. **건강 데이터 조회**: 각 사용자별 최신 건강검진 데이터 조회
5. **건강 중심 벡터 생성**: 1024차원 건강 특성 벡터 생성
6. **벡터 저장**: Pinecone에 저장
7. **진행상황 로깅**: 실시간 처리 현황 로그 출력
### 🎯 건강 중심 벡터 구성 (1024차원):
- **나이 특성** (50차원): 연령대별 유사도 강화
- **건강 위험도** (300차원): BMI, 혈압, 혈당, 콜레스테롤 등 주요 지표
- **상세 건강 특성** (500차원): 세부 건강 데이터 정교한 벡터화
- **직업 특성** (100차원): 직업별 건강 위험 프로필
- **생활습관** (74차원): 흡연, 음주 상태
### ⚡ 성능 최적화:
- **스킵 로직**: 이미 벡터가 있는 사용자는 건너뛰기
- **배치 처리**: 여러 사용자를 한 번에 처리
- **에러 핸들링**: 개별 사용자 실패 시에도 전체 프로세스 계속 진행
- **진행률 표시**: 전체 진행 상황 실시간 확인
### 📊 응답 정보:
- **총 사용자 수**: 전체 사용자 수
- **기존 벡터 수**: 이미 저장된 벡터 수
- **신규 처리 수**: 새로 저장된 벡터 수
- **성공/실패 수**: 처리 결과 통계
- **소요 시간**: 전체 처리 시간
### 🔧 사용 시점:
- 초기 시스템 구축 시 모든 사용자 벡터 생성
- 정기적인 벡터 데이터 동기화
- 새로운 사용자 대량 등록 후 벡터 일괄 생성
- 벡터 알고리즘 업데이트 후 재생성
### ⚠️ 주의사항:
- 대량 데이터 처리로 시간이 오래 걸릴 수 있음
- Pinecone API 요청 한도 고려 필요
- 처리 중 중단되어도 부분적으로 완료된 데이터는 유지됨
""")
async def upsert_all_user_vectors():
"""모든 사용자 건강 중심 벡터 일괄 저장/업데이트 (기존 벡터 스킵)"""
try:
self.log_request("upsert_all_user_vectors")
# 모든 사용자 벡터 일괄 처리 서비스 호출
result = await self.mission_service.upsert_all_user_vectors()
if result["success"]:
self.logger.info(f"✅ 모든 사용자 건강 중심 벡터 일괄 처리 완료 - "
f"총 사용자: {result['total_users']}, "
f"기존 벡터: {result['existing_vectors']}, "
f"신규 저장: {result['new_vectors']}, "
f"실패: {result['failed']}")
return self.create_success_response(
data=result,
message=f"건강 중심 벡터 일괄 처리 완료! 신규 {result['new_vectors']}개 저장, "
f"기존 {result['existing_vectors']}개 스킵"
)
else:
self.logger.warning(f"⚠️ 벡터 일괄 처리 부분 실패 - "
f"성공: {result['new_vectors']}, 실패: {result['failed']}")
return self.create_success_response(
data=result,
message=f"벡터 일괄 처리 부분 완료. 일부 사용자 처리 실패: {result['failed']}"
)
except DatabaseException as e:
self.logger.error(f"❌ 데이터베이스 오류 - error: {str(e)}")
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="데이터베이스 연결에 문제가 있습니다. 잠시 후 다시 시도해 주세요."
)
except Exception as e:
self.logger.error(f"❌ 벡터 일괄 처리 중 예상치 못한 오류: {str(e)}", exc_info=True)
# 일괄 처리 실패해도 서비스는 계속 동작 가능하도록 처리
return self.create_success_response(
data={
"success": False,
"total_users": 0,
"existing_vectors": 0,
"new_vectors": 0,
"failed": 0,
"error_message": "벡터 일괄 처리에 실패했지만 개별 기능은 정상 이용 가능합니다.",
"error_type": type(e).__name__
},
message="벡터 일괄 처리에 실패했지만 서비스는 계속 이용 가능합니다."
)
# 컨트롤러 인스턴스 생성
mission_controller = MissionController()
+98
View File
@@ -0,0 +1,98 @@
# app/controllers/status_controller.py
"""
HealthSync AI 헬스체크 컨트롤러 (DB 연결 기능 추가)
"""
from fastapi import APIRouter, Depends, status, Query, HTTPException
from app.controllers.base_controller import BaseController
from app.models.base import BaseResponse
from app.core.dependencies import get_settings
from app.config.settings import Settings
from app.utils.database_utils import simple_db
import time, psutil
from datetime import datetime
from typing import Dict, Any, List
class StatusController(BaseController):
"""상태체크 관련 컨트롤러 (DB 기능 포함)"""
def __init__(self):
super().__init__()
self.router = APIRouter()
self._setup_routes()
def _setup_routes(self):
"""라우트 설정"""
@self.router.get("/check", response_model=BaseResponse,
status_code=status.HTTP_200_OK,
summary="🔧 시스템 상태 확인")
async def get_system_status(app_settings: Settings = Depends(get_settings)):
"""시스템 상태 확인"""
try:
self.log_request("system_status")
try:
memory_mb = round(psutil.Process().memory_info().rss / 1024 / 1024, 2)
except:
memory_mb = 0.0
status_data = {
"status": "running",
"service": app_settings.app_name,
"version": app_settings.app_version,
"memory_mb": memory_mb,
"environment": "development" if app_settings.debug else "production"
}
return self.create_success_response(
data=status_data,
message="서비스가 정상 동작 중입니다! 🚀"
)
except Exception as e:
self.handle_service_error(e, "system_status")
@self.router.get("/database",
response_model=BaseResponse[Dict[str, Any]],
status_code=status.HTTP_200_OK,
summary="🗄️ 데이터베이스 연결 테스트")
async def test_database_connection():
"""PostgreSQL 데이터베이스 연결 상태 확인"""
try:
self.log_request("database_connection_test")
connection_info = await simple_db.test_connection()
if connection_info.get("status") == "connected":
return self.create_success_response(
data=connection_info,
message="데이터베이스 연결이 정상입니다! 🎉"
)
else:
return self.create_success_response(
data=connection_info,
message="데이터베이스 연결에 문제가 있습니다. ⚠️"
)
except Exception as e:
self.handle_service_error(e, "database_connection_test")
@self.router.get("/tables",
response_model=BaseResponse[List[Dict[str, Any]]],
status_code=status.HTTP_200_OK,
summary="📋 테이블 목록 조회")
async def list_database_tables():
"""데이터베이스 테이블 목록 조회"""
try:
self.log_request("database_tables_list")
tables = await simple_db.list_tables()
return self.create_success_response(
data=tables,
message=f"{len(tables)}개의 테이블을 조회했습니다. 📊"
)
except Exception as e:
self.handle_service_error(e, "database_tables_list")
status_controller = StatusController()