From dba82ab5961031f78d010e862122d6d7c00078f6 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Tue, 26 Aug 2025 22:07:58 +0900 Subject: [PATCH 1/4] =?UTF-8?q?docs:=20=EB=89=B4=EC=8A=A4=20=EC=8A=A4?= =?UTF-8?q?=ED=82=AC=20=ED=82=A4=EC=9B=8C=EB=93=9C=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EB=B0=8F=20DB=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EA=B4=80=EB=A6=AC=20=EB=B0=A9=EC=95=88=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 매일 같은 AI 뉴스 반복 문제 원인 분석 - 하드코딩된 키워드를 동적 시스템으로 개선 방안 제시 - DB 기반 환경변수 관리 방법 문서화 - 사용자별 맞춤 키워드 시스템 설계 --- .../250826_slack_id_column_standardization.md | 212 +++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/troubleshooting/250826_slack_id_column_standardization.md b/troubleshooting/250826_slack_id_column_standardization.md index b1a7fd2..cee388b 100644 --- a/troubleshooting/250826_slack_id_column_standardization.md +++ b/troubleshooting/250826_slack_id_column_standardization.md @@ -168,4 +168,214 @@ WHERE slack_id IS NOT NULL AND slack_user_id IS NULL; --- -*작성 완료: 2025-08-26 21:30* \ No newline at end of file +## 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* \ No newline at end of file From aff9ab1c0e72fc82090f61595fd9277365e9107e Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Tue, 26 Aug 2025 22:12:03 +0900 Subject: [PATCH 2/4] =?UTF-8?q?docs:=20=EB=89=B4=EC=8A=A4=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EB=AC=B8=EC=84=9C=20=EA=B0=84=EC=86=8C?= =?UTF-8?q?=ED=99=94=20=EB=B0=8F=20=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94?= =?UTF-8?q?=EB=93=9C=20=EC=97=B0=EB=8F=99=20=EB=B0=A9=EC=95=88=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불필요한 코드와 우선순위 섹션 제거 - 사용자별 키워드 설정 방안으로 통합 - 프론트엔드 기존 UI 활용 방안 추가 (250825 문서 참조) - user_preferences 테이블로 통합 관리 --- .../250826_slack_id_column_standardization.md | 225 ++++-------------- 1 file changed, 44 insertions(+), 181 deletions(-) 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* From faa9ce7ba91bf89da6904022ae4899c4828447f7 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Tue, 26 Aug 2025 22:14:51 +0900 Subject: [PATCH 3/4] =?UTF-8?q?docs:=20=EB=AC=B8=EC=84=9C=20=EC=A0=84?= =?UTF-8?q?=EB=A9=B4=20=EC=9E=AC=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EA=B0=84?= =?UTF-8?q?=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 제목 변경: ID 체계 표준화 및 사용자 설정 시스템 - 핵심 2가지 문제와 해결책만 정리 - 불필요한 내용 모두 제거 - 65줄로 압축 --- .../250826_slack_id_column_standardization.md | 235 +++--------------- 1 file changed, 29 insertions(+), 206 deletions(-) diff --git a/troubleshooting/250826_slack_id_column_standardization.md b/troubleshooting/250826_slack_id_column_standardization.md index b91c9b5..c4edd69 100644 --- a/troubleshooting/250826_slack_id_column_standardization.md +++ b/troubleshooting/250826_slack_id_column_standardization.md @@ -1,244 +1,67 @@ -# Slack ID 컬럼명 표준화 작업 +# ID 체계 표준화 및 사용자 설정 시스템 -## 작성일: 2025-08-26 21:30 -## 작성자: 51123 서버 관리자 -## 상태: 🔴 작업 필요 -## 영향: 데이터 일관성, JOIN 쿼리 성능, 코드 유지보수성 -## 관련: 250826_id_체계_정리_및_conversation_logs_문제_해결.md에서 분리 +## 작성일: 2025-08-26 22:00 +## 작성자: 51124 서버 담당 +## 상태: 작업 필요 +## 영향: ID 일관성, 사용자 맞춤화 --- -## 1. 문제 정의 +## 1. Slack ID 컬럼명 불일치 -### 1.1 핵심 문제 -동일한 Slack 사용자 ID가 테이블마다 다른 컬럼명으로 저장되어 있음 +### 현재 상태 +| 테이블 | 컬럼명 | 타입 | +|--------|--------|------| +| slack_user_mapping | slack_user_id | VARCHAR(100) | +| gmail_tokens | **slack_id** ❌ | VARCHAR(100) | +| conversation_logs | slack_user_id | VARCHAR(100) | -### 1.2 현재 상태 -| 테이블 | 컬럼명 | 데이터 예시 | 타입 | -|--------|--------|------------|------| -| slack_user_mapping | **slack_user_id** | U091UNVE41M | VARCHAR(100) | -| gmail_tokens | **slack_id** ❌ | U091UNVE41M | VARCHAR(100) | -| conversation_logs | **slack_user_id** | U091UNVE41M | VARCHAR(100) | - ---- - -## 2. 시스템 영향도 - -### 2.1 데이터 흐름도 -``` -[Slack 사용자: U091UNVE41M] - │ - ├─→ slack_user_mapping.slack_user_id ✅ - │ ↓ (JOIN 시 컬럼명 불일치) - ├─→ gmail_tokens.slack_id ❌ - │ ↓ (JOIN 시 컬럼명 불일치) - └─→ conversation_logs.slack_user_id ✅ -``` - -### 2.2 JOIN 복잡도 증가 +### 해결 방안 ```sql --- 현재: 컬럼명이 달라서 복잡 -SELECT * FROM gmail_tokens g -JOIN slack_user_mapping s ON g.slack_id = s.slack_user_id -JOIN conversation_logs c ON s.slack_user_id = c.slack_user_id - --- 목표: 모든 테이블 동일 컬럼명 -SELECT * FROM gmail_tokens g -JOIN slack_user_mapping s USING (slack_user_id) -JOIN conversation_logs c USING (slack_user_id) -``` - ---- - -## 3. 해결 방안 - -### 3.1 작업 순서 - -#### Phase 1: DB 스키마 변경 (51123 서버) -```sql --- 1. 컬럼 추가 +-- gmail_tokens 컬럼명 변경 ALTER TABLE gmail_tokens ADD COLUMN slack_user_id VARCHAR(100); - --- 2. 데이터 복사 UPDATE gmail_tokens SET slack_user_id = slack_id; - --- 3. 제약조건 이동 ALTER TABLE gmail_tokens DROP COLUMN slack_id; - --- 4. 인덱스 재생성 -CREATE INDEX idx_gmail_tokens_slack_user_id ON gmail_tokens(slack_user_id); ``` -#### Phase 2: 코드 수정 (로컬 개발자) -| 파일 | 수정 내용 | -|------|----------| -| auth-server/models.py | slack_id → slack_user_id | -| robeing-monitor/database.py | slack_id → slack_user_id | -| skill-email/db_client.py | slack_id → slack_user_id | - -#### Phase 3: 배치 매핑 (선택사항) -Slack ID를 가진 사용자를 UUID와 매핑하여 통합 관리 - --- -## 4. 현재 데이터 현황 +## 2. 뉴스 키워드 하드코딩 문제 + +### 현재 상태 +- rb8001이 `["AI", "기술", "IT"]`만 사용 (dm_skill.py:309) +- 매일 같은 뉴스 반복 + +### 해결 방안: user_preferences 테이블 -### 4.1 영향받는 레코드 수 ```sql --- gmail_tokens 테이블 -SELECT COUNT(*) FROM gmail_tokens WHERE slack_id IS NOT NULL; --- 결과: 3건 (U091UNVE41M, U0925SXQFDK, U092F7FQ55L) - --- slack_user_mapping 테이블 -SELECT COUNT(*) FROM slack_user_mapping; --- 결과: 3건 (동일 사용자) -``` - -### 4.2 서비스별 영향 -| 서비스 | 영향도 | 수정 필요 | -|--------|--------|----------| -| auth-server | 높음 | Gmail 토큰 조회 로직 | -| robeing-monitor | 중간 | 토큰 관리 UI | -| skill-email | 높음 | 토큰 검증 로직 | -| rb8001 | 낮음 | 이미 slack_user_id 사용 | - ---- - -## 5. 위험 요소 및 대응 - -### 5.1 위험 요소 -- **서비스 중단**: 컬럼명 변경 중 API 오류 가능 -- **데이터 손실**: ALTER TABLE 실행 중 실수 -- **캐시 문제**: 기존 ORM 캐시가 old 컬럼명 참조 - -### 5.2 대응 방안 -1. **백업 우선**: `pg_dump main_db > backup_20250826.sql` -2. **점진적 마이그레이션**: 새 컬럼 추가 → 이중 운영 → 구 컬럼 제거 -3. **캐시 초기화**: Docker 재시작으로 ORM 캐시 클리어 - ---- - -## 6. 검증 계획 - -### 6.1 변경 전 테스트 -```sql --- 데이터 무결성 확인 -SELECT COUNT(*) FROM gmail_tokens -WHERE slack_id IS NOT NULL AND slack_user_id IS NULL; -``` - -### 6.2 변경 후 검증 -- Gmail 토큰 조회 API 테스트 -- Slack 사용자 매핑 확인 -- JOIN 쿼리 성능 비교 - ---- - -## 7. 예상 효과 - -### 7.1 개발 효율성 -- **Before**: 테이블마다 다른 컬럼명 기억 필요 -- **After**: 모든 곳에서 `slack_user_id` 통일 - -### 7.2 쿼리 성능 -- **Before**: 복잡한 ON 조건 -- **After**: USING 절로 간단한 JOIN - -### 7.3 유지보수성 -- 신규 개발자 학습 곡선 감소 -- 버그 발생 가능성 감소 -- 코드 일관성 향상 - ---- - -## 8. 작업 체크리스트 - -- [ ] PostgreSQL 백업 수행 -- [ ] gmail_tokens 테이블 스키마 변경 -- [ ] 로컬 개발자에게 코드 수정 지시 -- [ ] 테스트 환경에서 검증 -- [ ] 프로덕션 배포 -- [ ] 모니터링 및 롤백 준비 - ---- - -## 9. 관련 문서 -- 원본: `/home/admin/DOCS/troubleshooting/250826_id_체계_정리_및_conversation_logs_문제_해결.md` -- 이 문서는 Slack ID 컬럼명 표준화 부분만 분리하여 작성됨 - ---- - -## 10. 뉴스 스킬 키워드 문제 분석 - -### 10.1 발견된 문제 -**매일 같은 AI 뉴스만 반복되는 현상** - -#### 원인 -- rb8001의 dm_skill.py:309에 `["AI", "기술", "IT"]` 하드코딩 -- 환경변수 NEWS_KEYWORDS 미사용 -- 중복 방지로 인해 같은 뉴스 반복 표시 - -### 10.2 해결 방안: 사용자별 키워드 설정 - -#### DB 스키마 -```sql --- 사용자 선호도 테이블 (프론트엔드 설정 UI와 연동) CREATE TABLE user_preferences ( id SERIAL PRIMARY KEY, user_id UUID REFERENCES users(id), slack_user_id VARCHAR(100), - news_keywords TEXT[], -- 뉴스 관심 키워드 - email_filter TEXT[], -- 이메일 필터 키워드 + 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() ); ``` -#### rb8001 수정 필요 코드 ```python -# dm_skill.py 수정 +# rb8001/dm_skill.py 수정 async def get_user_keywords(slack_user_id: str) -> List[str]: - """사용자 설정에서 키워드 조회""" 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"] # 기본값 + return result[0] if result else ["AI", "기술", "IT"] ``` -### 10.3 프론트엔드 연동 - -#### 기존 UI 활용 (250825 문서 참조) -- **위치**: frontend-customer의 ActivityPanel 설정 섹션 -- **기능**: 관심 키워드 입력/수정 -- **저장**: user_preferences 테이블로 직접 저장 - -#### API 엔드포인트 -```python -# 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 - -@router.get("/api/users/preferences") -async def get_preferences( - user_id: str = Depends(get_current_user) -): - # user_preferences 조회 - pass -``` +### 프론트엔드 연동 +- ActivityPanel 설정 UI 활용 (250825 문서 참조) +- Gateway API로 user_preferences CRUD 구현 --- -*작성 완료: 2025-08-26 21:30* -*뉴스 스킬 분석 추가: 2025-08-26 21:45* \ No newline at end of file +*작성: 2025-08-26 22:00* \ No newline at end of file From 3069b2cdf553154ef431d92806ac725c53b4da89 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Tue, 26 Aug 2025 22:22:27 +0900 Subject: [PATCH 4/4] =?UTF-8?q?docs:=20Slack=20ID=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EC=8B=9C=20=EC=88=98=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EB=B0=8F=20=EC=8A=AC=EB=9E=99=20=EB=AA=85=EB=A0=B9?= =?UTF-8?q?=EC=96=B4=20=EC=84=A4=EA=B3=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gmail_tokens 컬럼 변경 시 수정해야 할 4개 파일 명시 - 슬랙에서 뉴스 키워드 설정하는 명령어 설계 - 일반 메시지 명령어와 슬래시 명령어 대안 제시 - 코드 제거하고 설명으로 대체 --- .../250826_slack_id_column_standardization.md | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/troubleshooting/250826_slack_id_column_standardization.md b/troubleshooting/250826_slack_id_column_standardization.md index c4edd69..fd9b02e 100644 --- a/troubleshooting/250826_slack_id_column_standardization.md +++ b/troubleshooting/250826_slack_id_column_standardization.md @@ -17,6 +17,8 @@ | conversation_logs | slack_user_id | VARCHAR(100) | ### 해결 방안 + +#### DB 스키마 변경 ```sql -- gmail_tokens 컬럼명 변경 ALTER TABLE gmail_tokens ADD COLUMN slack_user_id VARCHAR(100); @@ -24,6 +26,14 @@ UPDATE gmail_tokens SET slack_user_id = slack_id; ALTER TABLE gmail_tokens DROP COLUMN slack_id; ``` +#### 코드 수정 필요 +| 파일 경로 | 변경 내용 | +|-----------|----------| +| auth-server/models.py | slack_id → slack_user_id | +| robeing-monitor/database.py | slack_id → slack_user_id | +| skill-email/db_client.py | slack_id → slack_user_id | +| rb8001/app/brain/state_client.py | gmail_tokens 조회 시 컬럼명 | + --- ## 2. 뉴스 키워드 하드코딩 문제 @@ -47,20 +57,31 @@ CREATE TABLE user_preferences ( ); ``` -```python -# rb8001/dm_skill.py 수정 -async def get_user_keywords(slack_user_id: str) -> List[str]: - db = SessionLocal() - result = db.execute( - text("SELECT news_keywords FROM user_preferences WHERE slack_user_id = :sid"), - {"sid": slack_user_id} - ).fetchone() - return result[0] if result else ["AI", "기술", "IT"] -``` +### rb8001 코드 수정 +- dm_skill.py의 get_news_content() 메서드에서 사용자별 키워드 조회 +- 하드코딩된 ["AI", "기술", "IT"] 대신 user_preferences 테이블에서 조회 +- 없으면 기본값 사용 + +### 슬랙 명령어 설계 + +#### 일반 메시지 명령어 +- **설정**: "@로빙 뉴스 키워드 설정: 삼성, 반도체, AI" +- **확인**: "@로빙 내 뉴스 키워드" +- **초기화**: "@로빙 뉴스 키워드 초기화" + +#### 슬래시 명령어 (대안) +- **/news-keywords set** 삼성, 반도체, AI +- **/news-keywords list** +- **/news-keywords reset** + +#### 구현 방법 +1. rb8001이 메시지에서 "뉴스 키워드 설정:" 패턴 감지 +2. user_preferences 테이블에 키워드 저장 (INSERT ON CONFLICT UPDATE) +3. 다음 브리핑부터 해당 키워드로 뉴스 검색 ### 프론트엔드 연동 -- ActivityPanel 설정 UI 활용 (250825 문서 참조) -- Gateway API로 user_preferences CRUD 구현 +- ActivityPanel 설정 UI에서도 동일하게 user_preferences 수정 +- Gateway API 엔드포인트로 CRUD 구현 ---