DOCS/plans/250907_company_x_news_implementation.md
happybell80 c394de474f 문서 구조 정리 - 폴더 통합
- plan/* -> plans/ 폴더로 통합 (3개 파일 이동)
- 300_architecture/integrations/* -> ideas/ 이동
- 300_architecture/plans/* -> plans/ 이동
- 빈 폴더 삭제 (plan, integrations, 300_architecture/plans)
2025-09-11 21:40:00 +09:00

6.9 KiB

Company-X 뉴스 시스템 구현 완료

작성일: 2025-09-07 (최종 업데이트: 2025-09-08)

작성자: Claude & happybell80

목적: Company-X 뉴스 포스팅 시스템 구현 내역 기록

1. 구현 완료 사항

1.1 Slack Interactive 시스템

  • news_posting_skill.py: Company-X 뉴스 채널 포스팅 기능 구현
    • Block Kit 메시지 형식 (버튼 포함)
    • 홈페이지 게시 / 건너뛰기 버튼
    • skill-publish 연동 코드
    • JSON 기반 상태 관리

1.2 Interactive Endpoint

  • main.py: /api/slack/interactive 엔드포인트 추가
  • slack_handler.py: handle_interactive() 함수 구현
    • Slack 서명 검증
    • 버튼 액션 처리
    • 3초 내 ACK 응답

1.3 환경 설정

  • 채널 ID 관리: 환경변수 방식 채택
    • COMPANY_X_NEWS_CHANNEL_ID=C09CP4MDX71
  • /home/heejae/rb8001/.env: 환경변수 추가
  • /home/admin/ivada_project/rb8001/.env: 동일 설정 동기화

1.4 중복 뉴스 방지 시스템

  • sent_news_tracker.py: 전송된 뉴스 추적
    • 30일 히스토리 유지
    • JSON 파일 기반 저장
    • 사용자별 중복 필터링
  • Dockerfile 수정: sent_news_tracker.py 포함

2. 해결한 문제들

2.1 sent_news_tracker 모듈 에러

  • 문제: No module named 'sent_news_tracker'
  • 원인: Docker 이미지에 파일 미포함
  • 해결: Dockerfile에 COPY 명령 추가

2.2 채널 ID 하드코딩 이슈

  • 문제: 채널 ID가 코드에 하드코딩됨
  • 초기 설계: DB 테이블 방식
  • 최종 결정: 환경변수 방식

2.3 Git 충돌 해결

  • 충돌 파일: news_posting_skill.py, slack_handler.py, main.py
  • 해결 방식: 기존 코드 최대한 보존하며 새 기능 통합

3. 테스트 방법

수동 테스트

4. 환경 설정 요약

필수 환경변수

5. 주의사항

  • Docker 재시작시: docker compose down && up 사용
  • 환경변수 변경시 두 곳 모두 수정 필요
  • 운영 전환시 COMPANY_X_NEWS_CHANNEL_ID만 변경

6. 향후 개선 사항

  • Slack App Interactive URL 실제 설정
  • skill-email 500 에러 해결
  • 운영 채널 전환 테스트
  • 게시 완료 후 메시지 업데이트 기능

7. 2025-09-08 업데이트

7.1 구현 완료

  • Gateway /slack/interactive 프록시: 헤더 소문자 변환 문제 해결 (x-slack-signature)
  • skill-news GET /api/news/google/companyx/{article_id} 엔드포인트 추가
  • skill-news PATCH /api/news/google/companyx/{article_id} 상태 업데이트 추가
  • rb8001 news_id → article_id 변경
  • rb8001 skill-news에서 전체 데이터 조회 후 skill-publish 전송
  • 강원일보 스크래핑: div[itemprop='articleBody'] 셀렉터 추가
  • 강원도민일보 스크래핑: #article-view-content-div 셀렉터 추가
  • 날짜 추출: HTML 전체에서 "입력 2025.09.02" 패턴 검색 추가
  • parsed_date 필드 스크래핑 후 업데이트
  • Slack 메시지: 3개 제한 제거, 모든 뉴스 표시
  • 버튼 상태: 에러시에도 버튼 유지, 성공시 상태 텍스트만 추가

8. 2025-09-08 주요 문제 해결

8.1 Slack 메시지 전체 사라짐 문제

증상

  • 홈페이지 게시 버튼 클릭시 원본 메시지 전체가 사라지고 텍스트만 남음
  • "(편집됨)" 표시와 함께 버튼과 뉴스 내용이 모두 제거됨

원인

  1. Slack Interactive 응답에 JSON 메시지 포함시 원본 교체로 해석
  2. response_url 사용시 replace_original 기본값이 true일 수 있음
  3. chat_update() 호출이 blocks 전체를 잘못 전달

해결

  • rb8001/app/router/slack_handler.py Line 342: 빈 JSONResponse({}) 반환
  • rb8001/app/router/slack_handler.py Line 396-397: replace_original=False, delete_original=False 명시
  • chat_update() 호출 전면 제거

8.2 skill-publish 422 에러

증상

  • rb8001이 skill-publish 호출시 422 Unprocessable Entity 에러

원인

  • rb8001이 news_id, title, url만 전송
  • content, summary, thumbnail_url 필수 필드 누락

해결

  • rb8001/app/skills/news_posting_skill.py Line 282-285: skill-news에서 전체 데이터 조회
  • skill-news/app/api/news_endpoints.py Line 149-160: GET /api/news/google/companyx/{article_id} 추가
  • skill-news/app/api/news_endpoints.py Line 163-181: PATCH /api/news/google/companyx/{article_id} 추가

8.3 Gateway /slack/interactive 프록시 실패

증상

  • Slack Interactive 이벤트가 rb8001에 도달하지 않음

원인

  • robeing-gateway에 /slack/interactive 엔드포인트 없음
  • FastAPI/Starlette가 헤더를 소문자로 변환 (X-Slack-Signature → x-slack-signature)

해결

  • robeing-gateway/app/main.py Line 239-283: /slack/interactive 프록시 엔드포인트 추가
  • Line 254-257: 헤더 소문자로 접근 (request.headers.get("x-slack-signature"))

8.4 article_id None 문제

증상

  • skill-news GET /api/news/google/companyx/None 404 에러

원인

  • 버튼 value에서 article_id 추출 실패
  • news_posting_skill.py Line 273: value_str이 이미 string인데 json.loads() 실패

해결

  • rb8001/app/skills/news_posting_skill.py Line 107: article_id 사용
  • Line 150: action_data에 article_id 포함
  • Line 273: isinstance(value_str, str) 체크 추가

8.5 강원일보/강원도민일보 스크래핑 실패

증상

  • 본문 0자, 날짜 추출 실패

원인

  • 기존 article/main/p 태그 셀렉터로 찾을 수 없음
  • 사이트별 특수한 HTML 구조 사용

해결

  • skill-news/app/services/companyx_news_scraper.py Line 159-160: 특수 셀렉터 추가
    • 강원일보: div[itemprop='articleBody']
    • 강원도민일보: #article-view-content-div
  • Line 266-277: HTML 전체에서 날짜 패턴 검색 추가

8.6 날짜 표시 오류

증상

  • Slack에 "강원도민일보 | 2025-09-08" (실제 기사는 2025-09-02)

원인

  1. Google News에서 "3일 전" 같은 상대 시간만 제공
  2. 스크래핑 후 실제 날짜 추출했지만 parsed_date 필드 업데이트 안 함

해결

  • skill-news/app/services/companyx_news_scraper.py Line 106: parsed_date 전달
  • skill-news/app/services/companyx_news_collector.py Line 364: parsed_date 저장

8.7 Slack 요약 200자 제한

증상

  • 요약이 "..." 으로 끝남

원인

  • rb8001/app/skills/news_posting_skill.py Line 110-111: 200자 초과시 197자로 자름

현재 상태

  • 수정하지 않음 (가독성 위해 유지)

9. 핵심 교훈

9.1 Slack Interactive 응답 규칙

  • 3초 내 빈 200 OK 응답 필수
  • JSON 메시지 반환시 원본 교체됨
  • response_url 사용시 replace_original=False 명시 필수

9.2 데이터 흐름

  • skill-news를 single source of truth로 사용
  • rb8001은 orchestrator 역할만
  • 모든 데이터는 skill-news에서 관리