docs: 뉴스 스킬 키워드 문제 분석 및 DB 기반 설정 관리 방안 추가
- 매일 같은 AI 뉴스 반복 문제 원인 분석 - 하드코딩된 키워드를 동적 시스템으로 개선 방안 제시 - DB 기반 환경변수 관리 방법 문서화 - 사용자별 맞춤 키워드 시스템 설계
This commit is contained in:
parent
f02a34726c
commit
dba82ab596
@ -168,4 +168,214 @@ WHERE slack_id IS NOT NULL AND slack_user_id IS NULL;
|
||||
|
||||
---
|
||||
|
||||
*작성 완료: 2025-08-26 21:30*
|
||||
## 10. 뉴스 스킬 키워드 문제 분석
|
||||
|
||||
### 10.1 발견된 문제
|
||||
**매일 같은 AI 뉴스만 반복되는 현상**
|
||||
|
||||
#### 원인 분석
|
||||
1. **하드코딩된 키워드**
|
||||
- 위치: `/home/admin/ivada_project/rb8001/app/skills/dm_skill.py:309`
|
||||
- 코드: `["AI", "기술", "IT"]`로 고정
|
||||
- 문제: 매일 동일한 키워드로만 검색
|
||||
|
||||
2. **환경변수 미활용**
|
||||
- 설정: `NEWS_KEYWORDS=keyword1,keyword2`
|
||||
- 실제: 사용되지 않음
|
||||
|
||||
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 기반 키워드 관리
|
||||
```sql
|
||||
-- 키워드 설정 테이블 생성
|
||||
CREATE TABLE news_keywords (
|
||||
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,
|
||||
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: 사용자별 맞춤 키워드
|
||||
```python
|
||||
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()
|
||||
```
|
||||
|
||||
### 10.3 환경변수 DB 저장 방식
|
||||
|
||||
#### 설정 테이블 구조
|
||||
```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)
|
||||
);
|
||||
|
||||
-- 예시 데이터
|
||||
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 설정 읽기
|
||||
```python
|
||||
from typing import Optional, Any
|
||||
import json
|
||||
|
||||
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)
|
||||
```
|
||||
|
||||
### 10.4 구현 우선순위
|
||||
|
||||
1. **즉시 적용 가능**: 요일별 키워드 로테이션
|
||||
2. **중기 목표**: DB 기반 키워드 관리
|
||||
3. **장기 목표**: 사용자별 맞춤 키워드 + AI 추천
|
||||
|
||||
### 10.5 효과
|
||||
|
||||
- **다양성**: 매일 다른 뉴스 제공
|
||||
- **맞춤화**: 사용자별 관심사 반영
|
||||
- **유연성**: DB에서 키워드 실시간 변경 가능
|
||||
- **확장성**: 새로운 키워드 세트 쉽게 추가
|
||||
|
||||
---
|
||||
|
||||
*작성 완료: 2025-08-26 21:30*
|
||||
*뉴스 스킬 분석 추가: 2025-08-26 21:45*
|
||||
Loading…
x
Reference in New Issue
Block a user