DOCS/journey/plans/archive/260129_동남아_스타트업_뉴스_아침브리핑.md
Claude-51124 5a1fab4297 docs: 동남아 아침브리핑 계획문서 archive 이동, 링크·README 반영
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-30 10:25:14 +09:00

12 KiB

동남아 스타트업 뉴스 아침 브리핑

작성일: 2026-01-29
수정일: 2026-01-30 (하이브리드 선별 보강, Phase 1~4 구현 완료)
작성자: happybell80
관련: rb8001, skill-news, daily_headlines, 560_컴퍼니엑스_개요.md
이전 아이디어: journey/ideas/260125_동남아_스타트업_뉴스.md
구현 상세: → troubleshooting/260130_sea_headlines_implementation.md


1. UX 기대효과

  • 매일 아침 뉴스 브리핑에 「동남아 소식」 섹션을 넣어, 컴퍼니엑스가 동남아 기회를 탐색하는 데 도움이 되는 뉴스를 3개 꼭지로 제공한다.
  • 깡프로 헤드라인과 동일한 채널·동일한 아침 스케줄에 포함되며, 별도 채널·별도 job 없이 기존 daily_headlines 메시지 안에 섹션으로 삽입된다.

2. UI (깡프로 뉴스와 동일한 단순 형식)

  • 동남아 소식 섹션만 추가하고, 나머지 구조(오프닝, 출처, 클로징, 명언)는 깡프로 포맷 유지.
  • 동남아 뉴스 3건: 01. <url|제목>, 02. <url|제목>, 03. <url|제목> 한 줄씩. 제목은 한국어로 번역하여 표기(원문 영문인 경우). 날짜 병기·출판사/신문사·부가 설명 없음.
  • 삽입 위치: 깡프로 헤드라인 목록 끝 → 빈 줄 2개 → *동남아 소식*01. ~ 03. → 빈 줄 2개 → *오늘의 키워드* (있으면) → 빈 줄 2개 → 클로징 → 명언.

표시 예시 (24시간 이내 수집, 컴퍼니엑스 투자 분야 기준 선별):

*동남아 소식*

01. <url|싱가포르 Elev8.vc, AI·의료기술·로봇·첨단제조 딥테크 펀드 3천만 달러 마감>
02. <url|싱가포르 헬스테크 Mesh Bio, 동남아 확장용 시리즈 A 350만 달러 유치>
03. <url|TikTok, 태국 데이터센터에 38억 달러 투자 확정>
  • 참고: skill_news/app/services/naver_startup_news_service.py format_startup_news_for_slack, rb8001/app/services/skills/startup_news_skill.py run_headlines_job.

3. 수집·선별 상세

3.1 수집 (skill-news)

신규 파일: skill_news/app/services/sea_news_collector.py

구현 방식: google_news_collector.py:55-91 패턴 재사용

  • Playwright로 Google News 검색
  • URL 파라미터: q={keyword}%20when%3A1d&hl=en&gl=SG (24시간 필터)
  • 키워드: Singapore startup funding, Malaysia startup investment, Indonesia startup VC, SEA biotech healthcare

환경변수 (.env):

SEA_NEWS_KEYWORDS=Singapore startup funding,Malaysia startup investment,Indonesia startup VC,SEA biotech healthcare
SEA_NEWS_REGION=SG
SEA_NEWS_DAYS_BACK=1

데이터 모델: news_models.py:6-26 NewsArticle 재사용

3.2 선별 (skill-news) — 하이브리드: 1차 키워드 → 2차 LLM 적합도

신규 파일: skill_news/app/services/sea_news_filter.py (1차 키워드 + 2차 LLM 호출), 필요 시 sea_news_ranker.py (LLM 전용, 311 원칙 한 파일 500줄 이하)

3.2.1 1차: 키워드 필터

  • 키워드 매칭: 제목/본문에 기회·분야 키워드 1개 이상 포함 시 통과
    • 기회 키워드: funding, investment, VC, accelerator, Series A/B, M&A, expansion, policy
    • 분야 키워드: biotech, healthcare, medical, manufacturing, e-commerce
  • 본문 검증: companyx_news_collector.py:396-413 _remove_duplicates 패턴 참고. 제목/본문 문자열에 키워드 리스트 in 검사.
  • 후보 수: 통과한 기사 중 최대 10건 (다음 단계 LLM 입력). 10건 미만이면 전부 전달.

3.2.2 2차: LLM 적합도 선정

  • 입력: 1차 통과 후보(최대 10건)의 제목·URL(또는 제목만). 컴액 컨텍스트 문단(아래 참조)을 프롬프트에 포함.
  • 컴액 컨텍스트: DOCS/book/500_business/560_컴퍼니엑스_개요.md 2.1·2.2·뉴스 선별 컨텍스트 절 요약.
    • skill_news는 DOCS를 직접 읽지 않음. 배포 시 skill_news/app/data/companyx_context.txt 또는 환경변수 SEA_COMPANYX_CONTEXT로 동기화(311: 민감 정보 하드코딩 금지, 설정은 .env/파일).
    • 요약 핵심: 시드·프리A 투자·육성·펀딩, TIPS·LIPS·오늘전통, 해외 기회 탐색 시 VC·액셀·펀딩·M&A·진출 뉴스가 도움 됨.
  • LLM 요구 응답: 각 기사에 대해 적합도 0~100한 줄 이유. 응답은 JSON 배열 예: [{"index":0,"score":85,"reason":"..."}, ...]
  • 선정: 점수 내림차순 정렬 후 상위 3건 선택. 동점 시 입력 순서 유지.
  • 폴백: LLM 실패·타임아웃 시 1차 키워드 통과 건을 매칭 키워드 개수 기준 정렬해 상위 3건 사용 (graceful degradation).

3.2.3 데이터·설정 원칙

  • 컴액 컨텍스트: 코드에 문단 하드코딩 금지. companyx_context.txt 또는 SEA_COMPANYX_CONTEXT에서 로드.
  • 키워드 리스트: 환경변수 SEA_NEWS_OPPORTUNITY_KEYWORDS(기회), SEA_NEWS_FIELD_KEYWORDS(분야) 권장. 기본값은 계획서 키워드.

3.3 제목 번역 (LLM)

구현 위치: skill_news/app/services/sea_news_filter.py (또는 sea_news_ranker.py에서 2차 호출 후 sea_news_service.py에서 번역)

LLM 호출: Gemini API 사용 (311 원칙: LLM 우선 접근)

  • 입력: 2차 적합도 선정으로 확정된 3건의 제목만.
  • 프롬프트: "Translate the following news title to Korean. Return only the translated title without explanation: {title}"
  • 3건 배치 처리 (단일 호출로 통합, 311 원칙 섹션 14)

3.4 포맷 및 중복 제거

신규 파일: skill_news/app/services/sea_news_service.py

  • format_sea_news_for_slack(): naver_startup_news_service.py:333-343 패턴 참조
  • 중복 제거: companyx_news_collector.py:396-413 패턴 (URL + 제목 기준)
  • 이력 관리: skill_news/data/sea_news_posting.json (날짜, URL, 제목)

4. API 연동 (rb8001 ↔ skill-news)

4.1 skill-news 신규 엔드포인트

파일: skill_news/app/router/news_endpoints.py 엔드포인트: POST /api/news/sea/headlines (참조: /api/news/naver/startup-headlines) 응답: { "success": true, "count": 3, "items": [...], "text": "*동남아 소식*\n\n01. <url|제목>..." }

4.2 rb8001 수정

파일 수정 내용
skill_commands.py:223 fetch_sea_headlines() 신규 추가 (fetch_naver_headlines() 패턴 복사)
startup_news_skill.py:11-93 run_headlines_job()에서 동남아 뉴스 호출 + 섹션 삽입 (명언 앞, :67-76 패턴)

에러 핸들링: 동남아 수집 실패 시 try-except로 생략, 깡프로만 전송


5. Phase 및 필요 작업

Phase 필요 작업
Phase 1 skill-news: sea_news_collector.py 신규 생성. google_news_collector.py:55-91 패턴 복사, 키워드·지역(hl=en&gl=SG) 변경. .envSEA_NEWS_* 추가.
Phase 2 skill-news: sea_news_filter.py(1차 키워드 + 2차 LLM 적합도) + sea_news_service.py 신규 생성. 1차: 키워드 매칭·본문 검증 → 후보 최대 10건. 2차: 컴액 컨텍스트 + Gemini로 적합도 0~100·이유 JSON → 상위 3건. 폴백: LLM 실패 시 키워드 개수 기준 상위 3건. app/data/companyx_context.txt 또는 SEA_COMPANYX_CONTEXT 로드. 3건 확정 후 LLM 제목 번역(Gemini) + Slack 포맷.
Phase 3 skill-news: news_endpoints.pyPOST /api/news/sea/headlines 추가. 요청 body: {} 또는 {"format":"json"} (naver/startup-headlines와 동일).
Phase 4 rb8001: skill_commands.pyfetch_sea_headlines() 추가. startup_news_skill.py run_headlines_job()에서 동남아 뉴스 호출 + 섹션 삽입 (명언 앞).
Phase 5 배포: skill-news 먼저 배포 (git push) → rb8001 배포 (git push). 순서 중요 (의존성).

6. 테스트 계획

315 원칙 준수: pytest 자동 테스트, conftest.py fixtures 사용 TDD 접근: 테스트 먼저 작성(Red) → 구현(Green) → 리팩터 순서 유지 (AGENTS.md TDD 원칙)

테스트 파일 내용
수집 단위 테스트 skill_news/tests/test_sea_news_collector.py 키워드 검색, 24시간 필터, NewsArticle 반환 확인
1차 키워드 필터 단위 skill_news/tests/test_sea_news_filter.py 기회·분야 키워드 1개 이상 포함 시 통과, 후보 최대 10건
2차 LLM 적합도 단위 skill_news/tests/test_sea_news_filter.py 또는 test_sea_news_ranker.py Gemini 모킹, 적합도 JSON 파싱, 상위 3건 반환 확인. 폴백: LLM 실패 시 키워드 개수 기준 3건
제목 번역 단위 skill_news/tests/test_sea_news_filter.py 3건 제목 LLM 번역 모킹
포맷 단위 테스트 skill_news/tests/test_sea_news_service.py 01. <url|제목> 형식 확인
API 통합 테스트 skill_news/tests/test_sea_news_endpoint.py POST /api/news/sea/headlines 응답 확인
연동 E2E 테스트 rb8001/tests/e2e/test_sea_news_headlines.py 깡프로 + 동남아 섹션 통합 Slack 메시지 확인

E2E 테스트 시나리오:

  1. run_headlines_job() 호출 → skill-news API 호출 → 동남아 섹션 삽입 → Slack 전송 확인
  2. 동남아 수집 실패 시 → 깡프로만 전송되는지 확인 (graceful degradation)

conftest.py fixtures:

  • mock_playwright: Playwright 모킹
  • mock_gemini: Gemini API 모킹 (적합도 JSON 응답, 제목 번역 응답)
  • sample_sea_articles: 테스트용 NewsArticle 5~10건 (1차 후보)
  • sample_companyx_context: 컴액 컨텍스트 요약 문자열 (560 기반)

7. 로깅 전략

311 원칙 섹션 11: INFO(시작/종료), DEBUG(중간 과정)

단계 로그 레벨 메시지 예시
수집 시작 INFO 동남아 뉴스 수집 시작: keywords={keywords}
수집 완료 INFO 동남아 뉴스 수집 완료: {count}개
1차 키워드 통과 DEBUG 기회 키워드 매칭: {title} → 통과, 후보 {n}건
2차 LLM 적합도 INFO LLM 적합도 선정 완료: 상위 3건 (scores=...)
2차 폴백 WARNING LLM 적합도 실패, 키워드 개수 기준 상위 3건 사용
번역 INFO 제목 번역 완료: {count}건
실패 WARNING 동남아 뉴스 수집 실패 (생략): {error}

8. 주의사항 (트러블슈팅 교훈)

교훈 출처 적용
검색어 부분 매칭 → 무관 기사 수집 250916_claude_companyx_wrong_news.md 본문 검증 로직 필수
OOM → 리소스 경합 250908_headline_failure_memory_error.md 깡프로(09:10) 이후 동남아 수집 (동일 job 내 순차 처리)
좀비 프로세스 250904_admin_skill-news_zombie_process_gitea_actions.md docker-compose.yml init: true 확인
워크스페이스별 토큰 분리 250909_slack_briefing_failure.md COMPANYX_SLACK_BOT_TOKEN 사용 확인
API 엔드포인트 확인 필수 250914_happybell80_깡프로뉴스_용어추출_기능추가.md skill-news API 스펙 먼저 확인

9. 참고 파일

파일 참조 내용
skill_news/app/services/google_news_collector.py:55-91 뉴스 검색 패턴
skill_news/app/services/google_news_collector.py:100 URL 파라미터 (when:Nd)
skill_news/app/services/companyx_news_collector.py:396-413 중복 제거 패턴
skill_news/app/services/naver_startup_news_service.py:333-343 Slack 포맷 (01. <url|제목>)
skill_news/app/router/news_endpoints.py 기존 /api/news/naver/* 엔드포인트 패턴
rb8001/app/commands/skill_commands.py:223-250 fetch_naver_headlines() 패턴
rb8001/app/services/skills/startup_news_skill.py:11-93 run_headlines_job 구조
rb8001/app/services/skills/startup_news_skill.py:67-76 섹션 삽입 로직 (명언 앞)
DOCS/book/500_business/560_컴퍼니엑스_개요.md 컴퍼니엑스 컨텍스트(2.1·2.2·뉴스 선별). 2차 LLM 적합도 프롬프트용 요약문 동기화 원본.