docs: NAVER WORKS 콜드메일 자동 감지 계획 추가 및 Tailwind 모바일 반응형 이슈 해결
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
56f0360844
commit
220d9b77d7
@ -1,143 +0,0 @@
|
||||
# NAVER WORKS → Slack 연동 [3/3] 콜드메일 리스트업
|
||||
|
||||
## 날짜: 2025-09-19
|
||||
## 작성자: Claude (51123 서버 관리자)
|
||||
## 관련 서비스: rb8001, skill-email, skill-slack(선택)
|
||||
## 상태: 미구현 (02 문서 변경사항 반영)
|
||||
|
||||
## 관련 문서
|
||||
- [1/3 기본 구성](./250919_naverworks_slack_01_base_configuration.md)
|
||||
- [2/3 일일 브리핑](./250919_naverworks_slack_02_daily_briefing.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 콜드메일 리스트업 개요
|
||||
|
||||
### 목적
|
||||
스타트업 콜드메일을 자동으로 수집하여 Slack 리스트 형식으로 전달
|
||||
|
||||
### 핵심 기능
|
||||
- 콜드메일 패턴 감지 (발신자 도메인, 제목 키워드)
|
||||
- 구조화된 리스트 생성 (회사명, 담당자, 제안내용)
|
||||
- 첨부파일 정보 표시
|
||||
- Slack 지정 채널 자동 포스팅
|
||||
|
||||
---
|
||||
|
||||
## 2. 구현 방식
|
||||
|
||||
### 2.1 트리거 방식 (권장: 푸시 알림)
|
||||
- **현재 계획**: 주기적 폴링
|
||||
- **권장 변경**: NAVER WORKS 푸시 알림
|
||||
- Developer Console에서 Webhook URL 등록
|
||||
- 새 메일 수신 시 즉시 알림
|
||||
- API 호출 최소화
|
||||
|
||||
### 2.2 처리 흐름 (현행 기준 + 계획)
|
||||
1. 새 메일 수신 이벤트 발생 (또는 주기적 체크)
|
||||
2. rb8001이 skill-email 호출
|
||||
- 현행: GET `/messages?provider=naverworks&user_id={UUID}&limit=100` 후 클라이언트(receivedTime) 기준 24시간 필터
|
||||
- 계획: POST `/cold-mail-list` (필터·구조화까지 일괄 처리)
|
||||
3. 콜드메일 필터링/구조화
|
||||
- 현행: rb8001에서 키워드/도메인 기반 필터 후 목록 구성
|
||||
- 계획: skill-email 내부 `filter_cold_mails()`로 위임
|
||||
4. Slack 포맷팅 후 전송
|
||||
- 현행: rb8001이 Block Kit 직접 구성 후 전송(WebClient)
|
||||
- 계획: skill-slack POST `/format-cold-mail`로 포맷 위임
|
||||
5. 전송 대상: 네이버웍스 등록 사용자 DM(기본) — 필요 시 전용 채널 옵션
|
||||
|
||||
---
|
||||
|
||||
## 3. 콜드메일 필터링 규칙
|
||||
|
||||
### 3.1 발신자 도메인 패턴
|
||||
```python
|
||||
COLD_MAIL_DOMAINS = [
|
||||
"*.vc", # VC 도메인
|
||||
"*capital.com", # 투자사
|
||||
"*ventures.com", # 벤처 캐피털
|
||||
"*startup.com" # 스타트업
|
||||
]
|
||||
```
|
||||
|
||||
### 3.2 제목 키워드
|
||||
```python
|
||||
COLD_MAIL_KEYWORDS = [
|
||||
"투자", "제안", "협업", "파트너십",
|
||||
"investment", "proposal", "partnership"
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 구현 파일 구조
|
||||
|
||||
### skill-email 현황/계획
|
||||
- 현행: GET `/messages`로 NAVER WORKS 메일 조회 (날짜 파라미터 미지원 → 클라이언트 필터 필요)
|
||||
- 계획:
|
||||
- `routers/naverworks_mail.py`: POST `/cold-mail-list` 엔드포인트
|
||||
- `services/naverworks_mail_service.py`: `filter_cold_mails()`
|
||||
- `schemas/naverworks_schemas.py`: ColdMailRequest/Response
|
||||
- (선택) `models/repositories`로 캐시 테이블 분리
|
||||
|
||||
### skill-slack 현황/계획
|
||||
- 현행: 전용 포맷터 엔드포인트 없음 (rb8001이 직접 Block Kit 구성)
|
||||
- 계획: POST `/format-cold-mail` — 테이블 Block Kit(회사명 | 담당자 | 제안 | 첨부)
|
||||
|
||||
### rb8001 오케스트레이션
|
||||
- 콜드메일 감지 시 skill-email에서 데이터 조회 → (현행) rb8001이 필터/포맷 → Slack 전송
|
||||
- 라우팅: 기본은 등록 사용자 DM, 필요 시 전용 채널 라우팅 옵션화
|
||||
|
||||
---
|
||||
|
||||
## 5. 구현 체크리스트
|
||||
|
||||
### 5.1 skill-email 구현
|
||||
- [ ] 응답 후 receivedTime 기준 클라이언트 필터 구현(타임존/RFC3339 주의)
|
||||
- [ ] 콜드메일 필터링/패턴 매칭 알고리즘 (`filter_cold_mails()`)
|
||||
- [ ] 메일 정보 구조화(회사/담당/제안/첨부)
|
||||
- [ ] (선택) POST `/cold-mail-list` 일괄 처리 엔드포인트
|
||||
|
||||
- [ ] 네이버웍스 등록 사용자 조회(DB)로 대상자 결정
|
||||
- [ ] skill-email `/messages` 호출 시 provider=naverworks만 전달(날짜 파라미터 제거), 클라이언트 필터 적용
|
||||
- [ ] Block Kit 포맷/전송 (현행) 또는 skill-slack 포맷터 연계(계획)
|
||||
- [ ] 라우팅 정책: DM 기본, 채널 옵션 지원
|
||||
|
||||
### 5.3 푸시 알림 설정 (권장)
|
||||
- [ ] NAVER WORKS Webhook URL 등록
|
||||
- [ ] 이벤트 수신 엔드포인트 구현
|
||||
- [ ] 실시간 처리 로직
|
||||
|
||||
---
|
||||
|
||||
## 6. 보안 및 개선사항
|
||||
|
||||
### 6.1 정보 최소화
|
||||
- **문제**: 메일 본문 전체 노출 위험
|
||||
- **해결**:
|
||||
- 발신자, 제목, 회사명만 표시
|
||||
- 첨부파일은 파일명/크기만
|
||||
- 상세 내용은 원본 메일 링크
|
||||
|
||||
### 6.2 첨부파일 처리
|
||||
- **문제**: 악성코드 위험
|
||||
- **해결**:
|
||||
- 직접 다운로드 금지
|
||||
- "첨부파일 있음" 표시만
|
||||
- 파일 형식과 크기 정보만 제공
|
||||
|
||||
---
|
||||
|
||||
## 7. 예상 출력 형식
|
||||
|
||||
```
|
||||
📨 새로운 콜드메일 (3건)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
┌─────────────┬──────────┬─────────────────┬────────┐
|
||||
│ 회사명 │ 담당자 │ 제안 내용 │ 첨부 │
|
||||
├─────────────┼──────────┼─────────────────┼────────┤
|
||||
│ ABC Ventures│ 김대표 │ 시리즈A 투자제안│ PDF 2개│
|
||||
│ XYZ Capital │ 이과장 │ 협업 미팅 요청 │ - │
|
||||
│ 123 Startup │ 박매니저 │ 파트너십 제안 │ PPT 1개│
|
||||
└─────────────┴──────────┴─────────────────┴────────┘
|
||||
```
|
||||
@ -0,0 +1,70 @@
|
||||
# Tailwind CSS 도입 및 모바일 반응형 문제 해결
|
||||
|
||||
## 문제
|
||||
- Space Times 홈페이지 모바일(375px)에서 TabSection 등 컴포넌트들이 가로로 넘침
|
||||
- 사용자가 의도하지 않은 가로 스크롤 발생
|
||||
|
||||
## 시도한 해결책들
|
||||
### 1차: 개별 컴포넌트 CSS 수정
|
||||
- TabSection.css에 미디어 쿼리 추가
|
||||
- width: 100%, overflow-x: hidden 적용
|
||||
- 문제: 일시적으로 해결됐다가 다시 발생
|
||||
|
||||
### 2차: 전역 CSS 해결
|
||||
- index.css에 전역 스타일 추가
|
||||
```css
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body, html {
|
||||
overflow-x: hidden !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
```
|
||||
- 문제: CSS 우선순위 충돌로 불완전한 해결
|
||||
|
||||
## 최종 해결: Tailwind CSS v3 도입
|
||||
### 설치
|
||||
```bash
|
||||
npm install -D tailwindcss@^3 autoprefixer postcss
|
||||
```
|
||||
|
||||
### 설정 파일
|
||||
- tailwind.config.js: content 경로 설정
|
||||
- postcss.config.js: tailwindcss, autoprefixer 플러그인 설정
|
||||
- index.css: @tailwind 디렉티브 추가
|
||||
|
||||
### 주요 변경사항
|
||||
1. 모든 컴포넌트를 Tailwind 버전(TW suffix)으로 재작성
|
||||
- TabSection → TabSectionTW
|
||||
- ServiceCards → ServiceCardsTW
|
||||
- ContentSection → ContentSectionTW
|
||||
- Sidebar → SidebarTW
|
||||
- HeroCarousel → HeroCarouselTW
|
||||
- SearchSection → SearchSectionTW
|
||||
|
||||
2. CSS 파일 제거, 유틸리티 클래스로 대체
|
||||
- 반응형: sm:, md:, lg: 프리픽스 사용
|
||||
- 그리드: grid grid-cols-1 sm:grid-cols-3
|
||||
- 플렉스박스: flex flex-col sm:flex-row
|
||||
|
||||
### Tailwind v4 → v3 다운그레이드
|
||||
- 초기 Tailwind v4 설치 시 PostCSS 플러그인 호환 문제 발생
|
||||
- v3로 다운그레이드하여 안정성 확보
|
||||
|
||||
### SNS 버튼 브랜드 색상 적용
|
||||
- 카카오톡: #FEE500 (공식 노란색)
|
||||
- 인스타그램: gradient from-[#833ab4] via-[#fd1d1d] to-[#fcb045]
|
||||
- 유튜브: #FF0000 (공식 빨간색)
|
||||
|
||||
## 결과
|
||||
- 375px 모바일 화면에서 가로 스크롤 완전 제거
|
||||
- 모든 컴포넌트가 뷰포트 내에 정상 표시
|
||||
- 깔끔한 유틸리티 클래스 기반 스타일링
|
||||
|
||||
## 교훈
|
||||
- CSS 충돌 문제는 근본적인 해결책(Tailwind 같은 유틸리티 프레임워크)이 효과적
|
||||
- Tailwind v4는 아직 불안정, 프로덕션은 v3 사용 권장
|
||||
- 브랜드 색상은 hex 코드로 직접 지정 ([#색상코드] 형식)
|
||||
81
troubleshooting/250930_naverworks_slack_03_cold_mail_list.md
Normal file
81
troubleshooting/250930_naverworks_slack_03_cold_mail_list.md
Normal file
@ -0,0 +1,81 @@
|
||||
# NAVER WORKS → Slack 연동 [3/3] 콜드메일 자동 감지 및 IR 파일 분석
|
||||
|
||||
## 날짜: 2025-09-30
|
||||
## 작성자: Claude (로컬 개발자)
|
||||
## 상태: 계획
|
||||
|
||||
## 목표
|
||||
NAVER WORKS 메일 중 투자 제안(콜드메일) 수신 시:
|
||||
1. 자동 감지 및 필터링
|
||||
2. Slack 전용 채널에 리스트 포스팅 + 첨부파일 업로드
|
||||
3. 첨부파일(IR 자료) skill-rag-file 자동 학습
|
||||
4. AI 분석 요약 생성 후 채널 공유
|
||||
|
||||
---
|
||||
|
||||
## 현재 상태 (2025-09-30 코드 확인)
|
||||
|
||||
### 구현 완료
|
||||
- skill-email: `list_messages` (naverworks_provider.py:152), `get_message` (naverworks_provider.py:288), 토큰 갱신 (naverworks_provider.py:356)
|
||||
- skill-rag-file: POST /api/upload (upload.py:29), 포트 8508, PDF/DOCX/DOC/TXT/MD 지원 (config.py:33)
|
||||
- rb8001: Slack 파일 → skill-rag-file 전송 (slack_handler.py:52-147, 비동기 병렬)
|
||||
- rb8001: NAVER WORKS 일일 브리핑 (naverworks_briefing.py:36-256, 긴급/계약/결제 키워드)
|
||||
|
||||
### 미구현 (코드 확인)
|
||||
- skill-email: `download_attachment` 메서드 없음
|
||||
- rb8001: 콜드메일(투자/IR) 필터 로직 없음 (현재는 일반 중요 키워드만)
|
||||
- rb8001: NAVER WORKS 첨부파일 다운로드→rag-file 경로 없음
|
||||
- skill-slack: files_upload_v2 사용 없음 (chat_postMessage만 사용, messages.py:49)
|
||||
- **Slack Lists API**: lists:write, lists:read 스코프 미설정, 구현 없음 (2025년 9월 공개)
|
||||
|
||||
---
|
||||
|
||||
## 구현 계획
|
||||
|
||||
### 콜드메일 필터링 (Incremental Naive Bayes)
|
||||
1. **초기 Prior**: DB `coldmail_classifier` 테이블 (word, coldmail_count, normal_count), 도메인(`*.vc`: 0.9), 키워드(`투자`: 0.8) 시드
|
||||
2. **특징 추출**: 제목+발신자 도메인 → 토큰화
|
||||
3. **확률 계산**: P(콜드메일|단어) = P(단어|콜드메일) × P(콜드메일) / P(단어), 임계값 > 0.7
|
||||
4. **Slack 피드백**: "IR 맞음 ✅" / "아님 ❌" 버튼, 클릭 시 DB 카운터 업데이트
|
||||
5. **Prior 갱신**: 매일 8시 스케줄러, 피드백 반영 후 재분류
|
||||
6. **첨부파일 조건**: PDF 우선 처리
|
||||
|
||||
### 처리 흐름
|
||||
1. 매일 8시 rb8001 스케줄러 → skill-email list_messages (최근 24시간)
|
||||
2. 콜드메일 필터링 (rb8001, Naive Bayes), 첨부파일 있는 것만
|
||||
3. 첨부파일 다운로드 (NAVER WORKS API) → skill-rag-file 업로드
|
||||
4. **IR 파일 파싱** (skill-rag-file): PDF/DOCX → 텍스트 추출 → semantic chunking → 임베딩 → ChromaDB 저장
|
||||
5. **핵심 지표 추출** (rb8001, LLM + RAG): 사업 분야, 투자 단계, 매출, 성장률, 팀 구성, 기술 우위
|
||||
6. **가치 평가** (rb8001, Bayesian VC Method):
|
||||
- Prior: 동일 업종/단계 평균 밸류에이션 (DB 조회)
|
||||
- Likelihood: IR 지표 반영 (성장률, 특허, 시장점유율)
|
||||
- Posterior: 밸류에이션 분포 계산 (중간값, 신뢰구간, 불확실성)
|
||||
- DB 저장: `startup_valuation` 테이블
|
||||
7. **Slack Lists 생성/업데이트** (slackLists.items.create):
|
||||
- 컬럼: 회사명, 담당자, 제안내용, 첨부파일, 밸류에이션, IR여부(피드백)
|
||||
- 피드백: slackLists.items.update로 업데이트
|
||||
8. **학습 루프**: 피드백 수집 → Prior 업데이트 → 모델 개선
|
||||
|
||||
---
|
||||
|
||||
## 다음 단계
|
||||
|
||||
### FastAPI 구조 원칙
|
||||
- **main.py**: 앱 생성, 라우터 등록만
|
||||
- **routers/**: 엔드포인트별 분리
|
||||
- **services/**: 비즈니스 로직
|
||||
- **settings.py**: 환경변수, URL 생성
|
||||
|
||||
### 구현 순서
|
||||
1. **Slack 앱 매니페스트 수정**: lists:write, lists:read, files:read 스코프 추가 → 앱 재설치
|
||||
2. NAVER WORKS API 첨부파일 다운로드 확인
|
||||
3. skill-email: `download_attachment` 메서드 추가 (services/naverworks_provider.py)
|
||||
4. PostgreSQL: `coldmail_classifier` 테이블 생성 (word, coldmail_count, normal_count)
|
||||
5. PostgreSQL: `startup_valuation` 테이블 생성 (startup_name, valuation_median, valuation_lower, valuation_upper, confidence, metadata JSONB)
|
||||
6. rb8001: Naive Bayes 필터 구현 (services/coldmail_filter.py)
|
||||
7. rb8001: NAVER WORKS 첨부파일 처리 (services/naverworks_file_processor.py, slack_handler.py:52-147 참고)
|
||||
8. rb8001: IR 지표 추출 (services/ir_analyzer.py, LLM + RAG)
|
||||
9. rb8001: Bayesian 가치 평가 (services/startup_valuation.py, scipy.stats)
|
||||
10. rb8001: Slack Lists 클라이언트 (services/slack_lists_client.py, slackLists API)
|
||||
11. rb8001: 스케줄러 라우터 등록 (routers/coldmail_scheduler.py, APScheduler)
|
||||
12. rb8001: main.py에 라우터만 등록 (app.include_router)
|
||||
Loading…
x
Reference in New Issue
Block a user