|
| 1 | +# Coffee Chat Bot - 개발 계획 |
| 2 | + |
| 3 | +> 이 문서는 완료된 기능과 향후 추가할 기능들을 정리합니다. |
| 4 | +
|
| 5 | +--- |
| 6 | + |
| 7 | +## ✅ 완료된 기능 (MVP) |
| 8 | + |
| 9 | +### 핵심 기능 |
| 10 | + |
| 11 | +#### B-1: 자동 매칭 |
| 12 | +**상태**: ✅ 완료 (2026-01-26) |
| 13 | + |
| 14 | +**구현 내용**: |
| 15 | +- GitHub Actions를 통한 2주마다 자동 실행 |
| 16 | +- cron 스케줄: 매주 월요일 UTC 00:00 (KST 09:00) |
| 17 | +- 짝수 주차에만 실행 (홀수 주는 skip) |
| 18 | +- `workflow_dispatch`로 수동 트리거 가능 |
| 19 | + |
| 20 | +**구현 파일**: |
| 21 | +- `.github/workflows/match.yml` |
| 22 | +- `src/matcher.ts` - `createMatches()` |
| 23 | + |
| 24 | +#### B-2: 매칭 발표 |
| 25 | +**상태**: ✅ 완료 (2026-01-26) |
| 26 | + |
| 27 | +**구현 내용**: |
| 28 | +- Discord Webhook으로 매칭 결과 채널에 공지 |
| 29 | +- 참여자 멘션 포함 (`<@user_id>`) |
| 30 | +- 3인조 표시 자동 추가 |
| 31 | + |
| 32 | +**구현 파일**: |
| 33 | +- `src/webhook.ts` - `announceMatches()` |
| 34 | + |
| 35 | +**메시지 포맷**: |
| 36 | +``` |
| 37 | +☕ **이번 커피챗 매칭 발표!** |
| 38 | +
|
| 39 | +1. @user1 ↔ @user2 |
| 40 | +2. @user3 ↔ @user4 |
| 41 | +3. @user5 ↔ @user6 ↔ @user7 (3인조) |
| 42 | +
|
| 43 | +2주 안에 커피챗을 진행해주세요! ☕ |
| 44 | +``` |
| 45 | + |
| 46 | +#### B-3: 중복 매칭 방지 |
| 47 | +**상태**: ✅ 완료 (2026-01-26) |
| 48 | + |
| 49 | +**구현 내용**: |
| 50 | +- `data/history.json`에서 최근 4회 매칭 이력 참조 |
| 51 | +- 같은 조합이 나오면 재셔플 (최대 100번 시도) |
| 52 | +- Fisher-Yates 셔플 알고리즘 사용 |
| 53 | + |
| 54 | +**구현 파일**: |
| 55 | +- `src/matcher.ts` - `getRecentPairs()`, `shuffle()` |
| 56 | + |
| 57 | +**데이터 구조**: |
| 58 | +```json |
| 59 | +{ |
| 60 | + "matches": [ |
| 61 | + { |
| 62 | + "date": "2026-01-26", |
| 63 | + "pairs": [ |
| 64 | + ["user_id_1", "user_id_2"], |
| 65 | + ["user_id_3", "user_id_4"] |
| 66 | + ] |
| 67 | + } |
| 68 | + ] |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +#### B-4: 홀수 처리 |
| 73 | +**상태**: ✅ 완료 (2026-01-26) |
| 74 | + |
| 75 | +**구현 내용**: |
| 76 | +- 참여자가 홀수일 경우 마지막 조를 3인 1조로 구성 |
| 77 | +- 마지막 사람을 마지막 조에 추가 |
| 78 | + |
| 79 | +**구현 파일**: |
| 80 | +- `src/matcher.ts` - `createMatches()` 마지막 로직 |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +### 인프라 & CI/CD |
| 85 | + |
| 86 | +#### GitHub Actions 자동화 |
| 87 | +**상태**: ✅ 완료 (2026-01-26) |
| 88 | + |
| 89 | +**구현 내용**: |
| 90 | +- 매칭 자동 실행 워크플로우 |
| 91 | +- 매칭 후 `data/history.json` 변경사항을 자동 PR 생성 |
| 92 | +- Biome 자동 포맷팅 추가 (2026-02-01) |
| 93 | + |
| 94 | +**구현 파일**: |
| 95 | +- `.github/workflows/match.yml` |
| 96 | +- `.github/workflows/ci.yml` |
| 97 | + |
| 98 | +#### CI 파이프라인 |
| 99 | +**상태**: ✅ 완료 (2026-01-26) |
| 100 | + |
| 101 | +**구현 내용**: |
| 102 | +- TypeScript 타입 체크 (`tsc --noEmit`) |
| 103 | +- Biome lint & format 체크 |
| 104 | +- Bun 테스트 실행 |
| 105 | +- PR 및 main push 시 자동 실행 |
| 106 | + |
| 107 | +**구현 파일**: |
| 108 | +- `.github/workflows/ci.yml` |
| 109 | +- `biome.json` |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +### 기술 스택 |
| 114 | + |
| 115 | +| 항목 | 선택 | 완료일 | |
| 116 | +|------|------|--------| |
| 117 | +| 런타임 | Bun | 2026-01-26 | |
| 118 | +| 언어 | TypeScript | 2026-01-26 | |
| 119 | +| 데이터 저장 | JSON 파일 | 2026-01-26 | |
| 120 | +| 매칭 실행 | GitHub Actions (cron) | 2026-01-26 | |
| 121 | +| 결과 발표 | Discord Webhook | 2026-01-26 | |
| 122 | +| 참여자 관리 | `/coffee join/leave` (Cloudflare Worker) | 2026-02-08 | |
| 123 | +| 코드 품질 | Biome (lint + format) | 2026-01-26 | |
| 124 | + |
| 125 | +--- |
| 126 | + |
| 127 | +### 환경변수 |
| 128 | + |
| 129 | +| 환경변수 | 타입 | 용도 | |
| 130 | +|----------|------|------| |
| 131 | +| `DISCORD_BOT_TOKEN` | Secret | Discord Bot 토큰 (Role 멤버 조회) | |
| 132 | +| `DISCORD_WEBHOOK_URL` | Secret | 매칭 결과 발표용 Webhook | |
| 133 | +| `DISCORD_SERVER_ID` | Variable | 디스코드 서버 ID | |
| 134 | +| `DISCORD_ROLE_ID` | Variable | 커피챗 참여자 Role ID | |
| 135 | + |
| 136 | +--- |
| 137 | + |
| 138 | +## 📋 Post-MVP 기능 |
| 139 | + |
| 140 | +### 1. 사용자 기능 |
| 141 | + |
| 142 | +#### U-1: 커피챗 참여 신청 |
| 143 | +**상태**: ✅ 완료 (2026-02-08) |
| 144 | + |
| 145 | +**구현 내용**: |
| 146 | +- `/coffee join` 슬래시 명령어로 커피챗 Role 자동 부여 |
| 147 | +- Cloudflare Workers + Discord HTTP Interactions Endpoint 방식 (상시 서버 불필요) |
| 148 | +- ephemeral 응답으로 본인에게만 확인 메시지 표시 |
| 149 | + |
| 150 | +**구현 파일**: |
| 151 | +- `worker/src/handlers.ts` - `handleJoin()` |
| 152 | +- `worker/src/discord-api.ts` - `addRole()` |
| 153 | + |
| 154 | +#### U-2: 커피챗 참여 탈퇴 |
| 155 | +**상태**: ✅ 완료 (2026-02-08) |
| 156 | + |
| 157 | +**구현 내용**: |
| 158 | +- `/coffee leave` 슬래시 명령어로 커피챗 Role 자동 제거 |
| 159 | +- U-1과 동일한 Cloudflare Workers 인프라 사용 |
| 160 | + |
| 161 | +**구현 파일**: |
| 162 | +- `worker/src/handlers.ts` - `handleLeave()` |
| 163 | +- `worker/src/discord-api.ts` - `removeRole()` |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +### 2. 관리자 기능 |
| 168 | + |
| 169 | +#### A-1: 매칭 주기 설정 |
| 170 | +**설명**: 매칭이 실행되는 주기 및 시간을 관리자가 설정 |
| 171 | + |
| 172 | +**현재 제약**: |
| 173 | +- 매칭 주기가 2주로 하드코딩됨 (`.github/workflows/match.yml`) |
| 174 | +- 변경하려면 GitHub Actions 워크플로우 파일 수정 필요 |
| 175 | + |
| 176 | +**향후 구현**: |
| 177 | +- 설정 파일 또는 Discord 명령어로 주기 변경 |
| 178 | +- 예: `/coffee set-schedule weekly` 또는 `/coffee set-schedule biweekly` |
| 179 | + |
| 180 | +--- |
| 181 | + |
| 182 | +### 3. 고급 매칭 기능 |
| 183 | + |
| 184 | +#### 채널/그룹별 매칭 풀 분리 |
| 185 | +**설명**: 슬랙 Donut처럼 채널별로 독립적인 매칭 풀 운영 |
| 186 | + |
| 187 | +**배경**: |
| 188 | +- 디스코드는 슬랙과 달리 채널 멤버십 개념이 없음 |
| 189 | +- 채널 참여 = 매칭 풀 참여 자동 연동 불가 |
| 190 | + |
| 191 | +**구현 방식 (옵션)**: |
| 192 | +1. **채널 + Role 연동**: 채널마다 전용 Role 생성 |
| 193 | +2. **포럼/스레드 활용**: 관심사별 포럼 채널 참여자 매칭 |
| 194 | +3. **명령어에 채널 지정**: `/coffee join #channel-name` |
| 195 | + |
| 196 | +**데이터 구조 변경**: |
| 197 | +```json |
| 198 | +{ |
| 199 | + "channels": { |
| 200 | + "채널_ID_1": { |
| 201 | + "matches": [...] |
| 202 | + }, |
| 203 | + "채널_ID_2": { |
| 204 | + "matches": [...] |
| 205 | + } |
| 206 | + } |
| 207 | +} |
| 208 | +``` |
| 209 | + |
| 210 | +#### 관심사 기반 매칭 알고리즘 |
| 211 | +**설명**: 직군, 관심사 등 다양한 기준으로 최적의 매칭 |
| 212 | + |
| 213 | +**구현 아이디어**: |
| 214 | +- 사용자 프로필 등록 (관심사, 직군, 경력 등) |
| 215 | +- 가중치 기반 매칭 점수 계산 |
| 216 | +- 유사도가 낮은 사람끼리 매칭하여 다양성 증진 |
| 217 | + |
| 218 | +--- |
| 219 | + |
| 220 | +### 4. 피드백 & 품질 개선 |
| 221 | + |
| 222 | +#### 커피챗 피드백 수집 |
| 223 | +**설명**: 커피챗 후기 수집 및 매칭 품질 개선 |
| 224 | + |
| 225 | +**구현 방식**: |
| 226 | +- 커피챗 2주 후 자동 DM 발송 |
| 227 | +- 간단한 평점 시스템 (👍/👎 리액션) |
| 228 | +- 피드백 데이터를 매칭 알고리즘에 반영 |
| 229 | + |
| 230 | +--- |
| 231 | + |
| 232 | +### 5. 스케줄링 통합 |
| 233 | + |
| 234 | +#### 사용자 프로필 및 가용 시간 등록 |
| 235 | +**설명**: 사용자 가용 시간(Availability) 등록 및 자동 일정 조율 |
| 236 | + |
| 237 | +**기능**: |
| 238 | +- 사용자가 선호하는 요일/시간대 등록 |
| 239 | +- Google Calendar, Outlook 연동 |
| 240 | +- 매칭 시 양측의 가용 시간 자동 제안 |
| 241 | + |
| 242 | +--- |
| 243 | + |
| 244 | +### 6. 배포 & 확장 |
| 245 | + |
| 246 | +#### 마켓플레이스 공개 배포 |
| 247 | +**설명**: Discord 마켓플레이스에서 누구나 설치 가능한 오픈소스 봇 |
| 248 | + |
| 249 | +**요구사항**: |
| 250 | +- 멀티 테넌시 지원 (여러 서버에서 독립적으로 동작) |
| 251 | +- 데이터베이스 필요 (JSON 파일로는 한계) |
| 252 | +- 안정적인 호스팅 환경 |
| 253 | + |
| 254 | +--- |
| 255 | + |
| 256 | +## 우선순위 |
| 257 | + |
| 258 | +| 순위 | 기능 | 난이도 | 비고 | |
| 259 | +|------|------|--------|------| |
| 260 | +| 1 | A-1: 매칭 주기 설정 | 쉬움 | 설정 파일만 추가하면 됨 | |
| 261 | +| 2 | 채널/그룹별 매칭 풀 | 중간 | 데이터 구조 변경 필요 | |
| 262 | +| ~~3~~ | ~~U-1, U-2: 슬래시 명령어~~ | ~~중간~~ | ✅ 완료 (Cloudflare Worker) | |
| 263 | +| 4 | 피드백 수집 | 중간 | DM 발송 로직 추가 | |
| 264 | +| 5 | 관심사 기반 매칭 | 어려움 | 프로필 시스템 + 알고리즘 개선 | |
| 265 | +| 6 | 스케줄링 통합 | 어려움 | 외부 API 연동 | |
| 266 | +| 7 | 마켓플레이스 배포 | 어려움 | 멀티 테넌시 + DB + 호스팅 | |
| 267 | + |
| 268 | +--- |
| 269 | + |
| 270 | +## 기술 부채 |
| 271 | + |
| 272 | +### 현재 제약사항 |
| 273 | + |
| 274 | +1. **JSON 파일 기반 저장소** |
| 275 | + - 동시성 제어 없음 |
| 276 | + - 스케일링 한계 |
| 277 | + - → PostgreSQL/MongoDB로 마이그레이션 필요 |
| 278 | + |
| 279 | +2. **GitHub Actions 실행** |
| 280 | + - 실시간 명령어 처리 불가 |
| 281 | + - 매칭 주기 변경 시 코드 수정 필요 |
| 282 | + - → 상시 실행 봇 + 설정 관리 시스템 필요 |
| 283 | + |
| 284 | +3. ~~**Role 수동 관리**~~ → ✅ 해결 (2026-02-08) |
| 285 | + - `/coffee join` / `/coffee leave` 명령어로 자동화 완료 |
| 286 | + - Cloudflare Workers로 서버리스 구현 |
| 287 | + |
| 288 | +--- |
| 289 | + |
| 290 | +## 참고 자료 |
| 291 | + |
| 292 | +- 벤치마킹: [Donut (Slack)](https://www.donut.com/) |
| 293 | +- Discord API: https://discord.com/developers/docs |
| 294 | +- discord.js: https://discord.js.org/ |
0 commit comments