diff --git a/troubleshooting/250826_slack_id_column_standardization.md b/troubleshooting/250826_slack_id_column_standardization.md index cee388b..b91c9b5 100644 --- a/troubleshooting/250826_slack_id_column_standardization.md +++ b/troubleshooting/250826_slack_id_column_standardization.md @@ -173,208 +173,71 @@ WHERE slack_id IS NOT NULL AND slack_user_id IS NULL; ### 10.1 발견된 문제 **매일 같은 AI 뉴스만 반복되는 현상** -#### 원인 분석 -1. **하드코딩된 키워드** - - 위치: `/home/admin/ivada_project/rb8001/app/skills/dm_skill.py:309` - - 코드: `["AI", "기술", "IT"]`로 고정 - - 문제: 매일 동일한 키워드로만 검색 +#### 원인 +- rb8001의 dm_skill.py:309에 `["AI", "기술", "IT"]` 하드코딩 +- 환경변수 NEWS_KEYWORDS 미사용 +- 중복 방지로 인해 같은 뉴스 반복 표시 -2. **환경변수 미활용** - - 설정: `NEWS_KEYWORDS=keyword1,keyword2` - - 실제: 사용되지 않음 +### 10.2 해결 방안: 사용자별 키워드 설정 -3. **중복 방지 로직의 부작용** - - 이미 수집된 뉴스는 건너뜀 - - 새 뉴스 없으면 최근 저장된 뉴스 5개 반복 표시 - - 결과: 매일 같은 뉴스 표시 - -### 10.2 개선 방안 - -#### 방안 1: 동적 키워드 시스템 -```python -# dm_skill.py 수정 예시 -import random -from datetime import datetime - -def get_daily_keywords(): - """날짜별로 다른 키워드 세트 반환""" - keyword_sets = [ - ["AI", "인공지능", "ChatGPT"], - ["반도체", "삼성", "SK하이닉스"], - ["전기차", "테슬라", "현대차"], - ["빅테크", "구글", "애플"], - ["스타트업", "유니콘", "투자"], - ["바이오", "제약", "헬스케어"], - ["핀테크", "블록체인", "가상자산"] - ] - # 요일별로 다른 키워드 세트 사용 - day_of_week = datetime.now().weekday() - return keyword_sets[day_of_week] - -# 사용 -keywords = get_daily_keywords() # ["AI", "기술", "IT"] 대신 -``` - -#### 방안 2: DB 기반 키워드 관리 +#### DB 스키마 ```sql --- 키워드 설정 테이블 생성 -CREATE TABLE news_keywords ( +-- 사용자 선호도 테이블 (프론트엔드 설정 UI와 연동) +CREATE TABLE user_preferences ( id SERIAL PRIMARY KEY, user_id UUID REFERENCES users(id), slack_user_id VARCHAR(100), - keywords TEXT[], -- PostgreSQL 배열 타입 - priority INTEGER DEFAULT 0, - active BOOLEAN DEFAULT true, + news_keywords TEXT[], -- 뉴스 관심 키워드 + email_filter TEXT[], -- 이메일 필터 키워드 + briefing_enabled BOOLEAN DEFAULT true, + briefing_time TIME DEFAULT '09:00', created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); - --- 기본 키워드 설정 -INSERT INTO news_keywords (slack_user_id, keywords, priority) VALUES -('U091UNVE41M', ARRAY['AI', '스타트업', '투자'], 1), -('U0925SXQFDK', ARRAY['반도체', '삼성', 'IT'], 1), -('U092F7FQ55L', ARRAY['전기차', '배터리', '에너지'], 1); ``` -#### 방안 3: 사용자별 맞춤 키워드 +#### rb8001 수정 필요 코드 ```python +# dm_skill.py 수정 async def get_user_keywords(slack_user_id: str) -> List[str]: - """사용자별 맞춤 키워드 조회""" - try: - db = SessionLocal() - result = db.execute( - text("SELECT keywords FROM news_keywords WHERE slack_user_id = :sid"), - {"sid": slack_user_id} - ).fetchone() - - if result and result[0]: - return result[0] # PostgreSQL 배열 반환 - else: - # 기본값 또는 랜덤 키워드 - return get_daily_keywords() - finally: - db.close() + """사용자 설정에서 키워드 조회""" + db = SessionLocal() + result = db.execute( + text("SELECT news_keywords FROM user_preferences WHERE slack_user_id = :sid"), + {"sid": slack_user_id} + ).fetchone() + + if result and result[0]: + return result[0] + return ["AI", "기술", "IT"] # 기본값 ``` -### 10.3 환경변수 DB 저장 방식 +### 10.3 프론트엔드 연동 -#### 설정 테이블 구조 -```sql --- 시스템 설정 테이블 -CREATE TABLE system_config ( - id SERIAL PRIMARY KEY, - service_name VARCHAR(50) NOT NULL, - key VARCHAR(100) NOT NULL, - value TEXT, - description TEXT, - updated_at TIMESTAMP DEFAULT NOW(), - updated_by VARCHAR(100), - UNIQUE(service_name, key) -); +#### 기존 UI 활용 (250825 문서 참조) +- **위치**: frontend-customer의 ActivityPanel 설정 섹션 +- **기능**: 관심 키워드 입력/수정 +- **저장**: user_preferences 테이블로 직접 저장 --- 예시 데이터 -INSERT INTO system_config (service_name, key, value, description) VALUES -('news_skill', 'default_keywords', '["AI", "기술", "IT"]', '기본 뉴스 검색 키워드'), -('news_skill', 'max_items', '5', '최대 뉴스 개수'), -('news_skill', 'search_days', '7', '검색 기간 (일)'), -('rb8001', 'morning_briefing_time', '09:00', '모닝 브리핑 시간'); -``` - -#### Python에서 DB 설정 읽기 +#### API 엔드포인트 ```python -from typing import Optional, Any -import json +# Gateway 또는 auth-server에 추가 +@router.post("/api/users/preferences") +async def update_preferences( + keywords: List[str], + user_id: str = Depends(get_current_user) +): + # user_preferences 업데이트 + pass -class ConfigManager: - """DB 기반 설정 관리자""" - - def __init__(self, service_name: str): - self.service_name = service_name - self._cache = {} - - def get(self, key: str, default: Any = None) -> Any: - """설정값 조회""" - # 캐시 확인 - if key in self._cache: - return self._cache[key] - - try: - db = SessionLocal() - result = db.execute( - text(""" - SELECT value FROM system_config - WHERE service_name = :service AND key = :key - """), - {"service": self.service_name, "key": key} - ).fetchone() - - if result: - # JSON 파싱 시도 - try: - value = json.loads(result[0]) - except: - value = result[0] - - self._cache[key] = value - return value - - return default - - finally: - db.close() - - def set(self, key: str, value: Any, description: str = None): - """설정값 저장""" - try: - db = SessionLocal() - - # JSON 직렬화 가능한 경우 - if isinstance(value, (list, dict)): - value = json.dumps(value, ensure_ascii=False) - else: - value = str(value) - - db.execute( - text(""" - INSERT INTO system_config (service_name, key, value, description) - VALUES (:service, :key, :value, :desc) - ON CONFLICT (service_name, key) - DO UPDATE SET value = :value, updated_at = NOW() - """), - { - "service": self.service_name, - "key": key, - "value": value, - "desc": description - } - ) - db.commit() - - # 캐시 업데이트 - self._cache[key] = value - - finally: - db.close() - -# 사용 예시 -config = ConfigManager("news_skill") -keywords = config.get("default_keywords", ["AI", "IT"]) -max_items = config.get("max_items", 5) +@router.get("/api/users/preferences") +async def get_preferences( + user_id: str = Depends(get_current_user) +): + # user_preferences 조회 + pass ``` -### 10.4 구현 우선순위 - -1. **즉시 적용 가능**: 요일별 키워드 로테이션 -2. **중기 목표**: DB 기반 키워드 관리 -3. **장기 목표**: 사용자별 맞춤 키워드 + AI 추천 - -### 10.5 효과 - -- **다양성**: 매일 다른 뉴스 제공 -- **맞춤화**: 사용자별 관심사 반영 -- **유연성**: DB에서 키워드 실시간 변경 가능 -- **확장성**: 새로운 키워드 세트 쉽게 추가 - --- *작성 완료: 2025-08-26 21:30*