Skip to main content
Glama
README.md
# Slack MCP Server - Complete Implementation

## πŸ“‹ ν”„λ‘œμ νŠΈ κ°œμš”

FastMCP v2λ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•œ μ™„μ „ν•œ Slack API 연동 MCP μ„œλ²„μž…λ‹ˆλ‹€. 과제 κ°€μ΄λ“œλΌμΈμ— 따라 **ν•„μˆ˜ κΈ°λŠ₯ 4개**, **선택 κΈ°λŠ₯ 4개**, 그리고 **λ³΄λ„ˆμŠ€ λ½€λͺ¨λ„λ‘œ 타이머 κΈ°λŠ₯ 4개**λ₯Ό λͺ¨λ‘ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

### 🎯 μ£Όμš” νŠΉμ§•

- βœ… **μ™„μ „ν•œ UTF-8 ν•œκΈ€ 지원** - λͺ¨λ“  λ©”μ‹œμ§€μ—μ„œ ν•œκΈ€ μ™„λ²½ 지원
- βœ… **이쀑 토큰 μ‹œμŠ€ν…œ** - Bot Token + User Token으둜 λͺ¨λ“  κΈ°λŠ₯ 지원
- βœ… **슀마트 파일 μ—…λ‘œλ“œ** - 크기별 졜적 μ—…λ‘œλ“œ 방식 μžλ™ 선택
- βœ… **λ½€λͺ¨λ„λ‘œ 타이머** - μžλ™ μ•Œλ¦Ό κΈ°λŠ₯이 ν¬ν•¨λœ μ‹œκ°„ 관리 도ꡬ
- βœ… **비동기 처리** - κ³ μ„±λŠ₯ asyncio 기반 κ΅¬ν˜„
- βœ… **μƒμ„Έν•œ μ—λŸ¬ 핸듀링** - λͺ¨λ“  API ν˜ΈμΆœμ— λŒ€ν•œ μ μ ˆν•œ μ˜ˆμ™Έ 처리

## πŸš€ κΈ°λŠ₯ λͺ©λ‘

### πŸ”΄ ν•„μˆ˜ κΈ°λŠ₯ (Required Features - 4개)

1. **`send_slack_message`** - λ©”μ‹œμ§€ 전솑
   - 채널 λ˜λŠ” DM에 λ©”μ‹œμ§€ 전솑
   - μŠ€λ ˆλ“œ λ‹΅κΈ€ 지원
   - μ™„μ „ν•œ UTF-8 ν•œκΈ€ 지원

2. **`get_slack_channels`** - 채널 λͺ©λ‘ 쑰회
   - 곡개/λΉ„κ³΅κ°œ 채널 ꡬ뢄
   - 멀버십 μƒνƒœ 확인
   - λ³΄κ΄€λœ 채널 필터링

3. **`get_slack_channel_history`** - λ©”μ‹œμ§€ νžˆμŠ€ν† λ¦¬ 쑰회
   - μ΅œμ‹  λ©”μ‹œμ§€λΆ€ν„° 쑰회
   - μ‹œκ°„ λ²”μœ„ μ§€μ • κ°€λŠ₯
   - λ©”μ‹œμ§€ 메타데이터 포함

4. **`send_slack_direct_message`** - DM 전솑
   - νŠΉμ • μ‚¬μš©μžμ—κ²Œ 1:1 λ©”μ‹œμ§€ 전솑
   - μžλ™ DM 채널 생성
   - 봇 μ‚¬μš©μž 필터링

### 🟑 선택 κΈ°λŠ₯ (Optional Features - 4개)

5. **`get_slack_users`** - μ‚¬μš©μž λͺ©λ‘ 쑰회
   - μ‚¬μš©μž νƒ€μž…λ³„ λΆ„λ₯˜ (κ΄€λ¦¬μž, 멀버, 게슀트, 봇)
   - DM κ°€λŠ₯ μ‚¬μš©μž 필터링
   - μƒμ„Έν•œ ν”„λ‘œν•„ 정보

6. **`search_slack_messages`** - λ©”μ‹œμ§€ 검색 (User Token ν•„μš”)
   - ν‚€μ›Œλ“œ 기반 전체 μ›Œν¬μŠ€νŽ˜μ΄μŠ€ 검색
   - μ •λ ¬ 및 필터링 μ˜΅μ…˜
   - 검색 κ²°κ³Ό 메타데이터

7. **`upload_file_to_slack`** - 슀마트 파일 μ—…λ‘œλ“œ
   - 파일 크기별 졜적 μ—…λ‘œλ“œ 방식
   - λ‹€μ–‘ν•œ 파일 ν˜•μ‹ 지원
   - μžλ™ 미리보기 및 μ½”λ“œ ν•˜μ΄λΌμ΄νŒ…

8. **`add_slack_reaction`** - λ©”μ‹œμ§€ λ°˜μ‘ μΆ”κ°€
   - 이λͺ¨μ§€ λ°˜μ‘ μΆ”κ°€
   - λ‹€μ–‘ν•œ 이λͺ¨μ§€ ν˜•μ‹ 지원

### 🟒 λ³΄λ„ˆμŠ€ κΈ°λŠ₯ (Bonus Features - 4개)

9. **`start_pomodoro_timer`** - λ½€λͺ¨λ„λ‘œ 타이머 μ‹œμž‘
   - 5κ°€μ§€ 타이머 νƒ€μž… (study, work, break, meeting, custom)
   - μžλ™ μ‹œμž‘/μ’…λ£Œ μ•Œλ¦Ό
   - μ‚¬μš©μž μ •μ˜ μ‹œκ°„ 및 λ©”μ‹œμ§€

10. **`cancel_pomodoro_timer`** - 타이머 μ·¨μ†Œ
    - μ‹€ν–‰ 쀑인 타이머 μ¦‰μ‹œ 쀑단
    - μ·¨μ†Œ μ•Œλ¦Ό 전솑

11. **`list_active_timers`** - ν™œμ„± 타이머 λͺ©λ‘
    - ν˜„μž¬ μ‹€ν–‰ 쀑인 λͺ¨λ“  타이머
    - μ§„ν–‰λ₯  및 남은 μ‹œκ°„ ν‘œμ‹œ

12. **`get_timer_status`** - 타이머 μƒνƒœ 쑰회
    - νŠΉμ • νƒ€μ΄λ¨Έμ˜ 상세 μƒνƒœ
    - μ‹€μ‹œκ°„ μ§„ν–‰ 상황

### πŸ› οΈ μœ ν‹Έλ¦¬ν‹° κΈ°λŠ₯

13. **`test_slack_connection`** - μ—°κ²° ν…ŒμŠ€νŠΈ
14. **`get_workspace_info`** - μ›Œν¬μŠ€νŽ˜μ΄μŠ€ 정보
15. **`get_file_preview`** - 파일 미리보기
16. **`verify_or_create_file`** - 파일 확인/생성

## πŸ“¦ μ„€μΉ˜ 및 μ‹€ν–‰ 방법

### 1. ν”„λ‘œμ νŠΈ μ΄ˆκΈ°ν™”

```bash
# ν”„λ‘œμ νŠΈ 클둠 λ˜λŠ” λ‹€μš΄λ‘œλ“œ ν›„
cd slack-mcp

# uv νŒ¨ν‚€μ§€ λ§€λ‹ˆμ € μ„€μΉ˜ (μ—†λŠ” 경우)
curl -LsSf https://astral.sh/uv/install.sh | sh

# κ°€μƒν™˜κ²½ 생성 및 ν™œμ„±ν™”
uv venv
source .venv/bin/activate  # Linux/macOS
# .venv\Scripts\activate  # Windows

# μ˜μ‘΄μ„± μ„€μΉ˜
uv sync
# λ˜λŠ”
uv pip install -r requirements.txt
```

### 2. ν™˜κ²½ λ³€μˆ˜ μ„€μ •

`.env` νŒŒμΌμ„ μƒμ„±ν•˜κ³  λ‹€μŒκ³Ό 같이 μ„€μ •:

```env
# ν•„μˆ˜: Slack Bot Token (xoxb-둜 μ‹œμž‘)
SLACK_BOT_TOKEN=xoxb-your-bot-token-here

# 선택: Slack User Token (xoxp-둜 μ‹œμž‘) - 검색, νŒŒμΌμ—…λ‘œλ“œμš©
SLACK_USER_TOKEN=xoxp-your-user-token-here

# 선택: κΈ°λ³Έ 채널 ID (ν…ŒμŠ€νŠΈμš©)
SLACK_TEST_CHANNEL_ID=C08UZKK9Q4R

# 선택: 둜그 레벨
LOG_LEVEL=INFO
```

### 3. Slack App μ„€μ •

#### ν•„μš”ν•œ Bot Token Scopes:
```
channels:read        # 채널 λͺ©λ‘ 쑰회
channels:history     # 채널 λ©”μ‹œμ§€ νžˆμŠ€ν† λ¦¬ 쑰회
chat:write          # λ©”μ‹œμ§€ 전솑
im:read             # DM 채널 읽기
im:write            # DM λ©”μ‹œμ§€ 전솑
im:history          # DM νžˆμŠ€ν† λ¦¬ 쑰회
users:read          # μ‚¬μš©μž 정보 쑰회
reactions:write     # λ°˜μ‘ μΆ”κ°€
```

#### μΆ”κ°€ User Token Scopes (선택 κΈ°λŠ₯용):
```
search:read         # λ©”μ‹œμ§€ 검색
files:write         # 파일 μ—…λ‘œλ“œ
```

### 4. μ„œλ²„ μ‹€ν–‰

```bash
# MCP μ„œλ²„ μ‹€ν–‰
python slack_mcp_server.py

# λ˜λŠ” 직접 μ‹€ν–‰
uv run slack_mcp_server.py
```

## πŸ’‘ μ‚¬μš©λ²• 및 μ˜ˆμ‹œ

### κΈ°λ³Έ λ©”μ‹œμ§€ 전솑
```python
# Claude/LLM이 도ꡬ 호좜 μ‹œ
send_slack_message(
    channel="C08UZKK9Q4R", 
    text="μ•ˆλ…•ν•˜μ„Έμš”! MCPμ—μ„œ λ³΄λ‚΄λŠ” λ©”μ‹œμ§€μž…λ‹ˆλ‹€! πŸš€"
)
```

### 파일 μ—…λ‘œλ“œ (슀마트 처리)
```python
# λ‹€μ–‘ν•œ 크기의 νŒŒμΌμ„ μžλ™μœΌλ‘œ 졜적 λ°©μ‹μœΌλ‘œ μ—…λ‘œλ“œ
upload_file_to_slack(
    file_path="./report.pdf",
    channels="C08UZKK9Q4R",
    title="뢄석 λ³΄κ³ μ„œ",
    comment="μ›”κ°„ 데이터 뢄석 κ²°κ³Όμž…λ‹ˆλ‹€."
)
```

### λ½€λͺ¨λ„λ‘œ 타이머 μ‚¬μš©
```python
# μˆ˜μ—… 타이머 μ‹œμž‘ (50λΆ„)
start_pomodoro_timer(
    timer_type="study",
    channel_id="C08UZKK9Q4R",
    duration_minutes=50,
    custom_name="파이썬 κ³ κΈ‰ 문법 ν•™μŠ΅"
)

# ν™œμ„± 타이머 확인
list_active_timers()

# 타이머 μ·¨μ†Œ
cancel_pomodoro_timer("study_20250602_143022_123456")
```

### λ©”μ‹œμ§€ 검색 (User Token ν•„μš”)
```python
# μ›Œν¬μŠ€νŽ˜μ΄μŠ€ μ „μ²΄μ—μ„œ λ©”μ‹œμ§€ 검색
search_slack_messages(
    query="MCP μ„œλ²„",
    count=10,
    sort="timestamp"
)
```

## πŸ—οΈ ν”„λ‘œμ νŠΈ ꡬ쑰

```
slack-mcp/
β”œβ”€β”€ .env                     # ν™˜κ²½ λ³€μˆ˜ (Git μ œμ™Έ)
β”œβ”€β”€ .env.example            # ν™˜κ²½ λ³€μˆ˜ ν…œν”Œλ¦Ώ
β”œβ”€β”€ .gitignore              # Git λ¬΄μ‹œ 파일
β”œβ”€β”€ README.md               # 이 파일
β”œβ”€β”€ requirements.txt        # μ˜μ‘΄μ„± λͺ©λ‘
β”œβ”€β”€ pyproject.toml         # ν”„λ‘œμ νŠΈ μ„€μ •
β”œβ”€β”€ slack_api_client.py    # Slack API ν΄λΌμ΄μ–ΈνŠΈ (핡심 λͺ¨λ“ˆ)
β”œβ”€β”€ pomodoro_timer.py      # λ½€λͺ¨λ„λ‘œ 타이머 λͺ¨λ“ˆ
└── slack_mcp_server.py    # FastMCP μ„œλ²„ 메인
```

## πŸ”§ 기술적 κ΅¬ν˜„ 세뢀사항

### 이쀑 토큰 μ‹œμŠ€ν…œ
- **Bot Token (xoxb-)**: 일반적인 봇 κΈ°λŠ₯ (λ©”μ‹œμ§€ 전솑, 채널 쑰회 λ“±)
- **User Token (xoxp-)**: μ‚¬μš©μž κΆŒν•œ ν•„μš”ν•œ κΈ°λŠ₯ (검색, λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œ)

### 슀마트 파일 μ—…λ‘œλ“œ μ „λž΅
1. **μž‘μ€ ν…μŠ€νŠΈ 파일 (< 50KB)**: λ©”μ‹œμ§€ λ‚΄μš©μœΌλ‘œ 직접 전솑
2. **쀑간 파일 (50KB - 1MB)**: μ½”λ“œ μŠ€λ‹ˆνŽ«μœΌλ‘œ μ—…λ‘œλ“œ
3. **일반 파일 (1MB - 100MB)**: ν‘œμ€€ 파일 μ—…λ‘œλ“œ
4. **λŒ€μš©λŸ‰ 파일 (100MB - 1GB)**: User Token으둜 μ—…λ‘œλ“œ
5. **μ΄ˆλŒ€μš©λŸ‰ 파일 (> 1GB)**: 파일 μ •λ³΄λ§Œ 곡유

### 비동기 처리 및 λ™μ‹œμ„±
- `asyncio` 기반 μ™„μ „ 비동기 κ΅¬ν˜„
- λ½€λͺ¨λ„λ‘œ νƒ€μ΄λ¨Έμ˜ 병렬 μ‹€ν–‰ 지원
- 락(Lock)을 ν†΅ν•œ ν΄λΌμ΄μ–ΈνŠΈ μ΄ˆκΈ°ν™” μ•ˆμ „μ„± 보μž₯

### UTF-8 ν•œκΈ€ 지원
```python
headers = {
    'Content-Type': 'application/json; charset=utf-8'
}
```

## πŸ› 개발 κ³Όμ •μ—μ„œ κ²ͺ은 어렀움과 ν•΄κ²° 방법

### 1. ν•¨μˆ˜λ“€ κ°„μ˜ Input λ³€μˆ˜λͺ… 톡일 어렀움
**문제**: API ν•¨μˆ˜λ§ˆλ‹€ λ§€κ°œλ³€μˆ˜ 이름이 λ‹¬λΌμ„œ 일관성 λΆ€μ‘±
- `channel` vs `channel_id` vs `channels`
- `text` vs `message` vs `content`

**ν•΄κ²°μ±…**: 
- Slack API 곡식 λ¬Έμ„œ κΈ°μ€€μœΌλ‘œ λ³€μˆ˜λͺ… 톡일(ν–₯ν›„ μ—…λ°μ΄νŠΈ μ˜ˆμ •)
- λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œλŠ” μΌκ΄€λœ 넀이밍 μ»¨λ²€μ…˜ 적용
- docstring에 λͺ…ν™•ν•œ λ§€κ°œλ³€μˆ˜ μ„€λͺ… μΆ”κ°€

```python
async def send_message(
    self, 
    channel: str,      # κ°€λŠ₯ν•œ 뢀뢄듀은 channel 둜 톡일 μ˜ˆμ •
    text: str,         # 톡일: text
    thread_ts: Optional[str] = None
) -> Dict[str, Any]:
```

### 2. Input-Output λ³€μˆ˜λͺ… μ°ΎκΈ° 어렀움
**문제**: Slack API μ‘λ‹΅μ˜ λ³΅μž‘ν•œ 쀑첩 ꡬ쑰둜 ν•„μš”ν•œ 데이터 μΆ”μΆœ 어렀움

**ν•΄κ²°μ±…**:
- API 응닡을 둜그둜 좜λ ₯ν•˜μ—¬ ꡬ쑰 νŒŒμ•…
- 곡톡 데이터 μΆ”μΆœ ν•¨μˆ˜ μž‘μ„±
- 응닡 데이터 μ •κ·œν™” 및 ν¬λ§·νŒ…

```python
# 응닡 데이터 μ •κ·œν™” μ˜ˆμ‹œ
formatted_messages.append({
    'text': msg.get('text', ''),
    'user': msg.get('user', 'Unknown'),
    'timestamp': readable_time,
    'ts': msg.get('ts', ''),
    # ... ν•„μš”ν•œ ν•„λ“œλ§Œ μΆ”μΆœ
})
```

### 3. Outdated file_upload ν•¨μˆ˜λ₯Ό μ΅œμ‹  λ²„μ „μœΌλ‘œ μ‚¬μš©ν•˜κΈ°κΉŒμ§€ λ§Žμ€ μ‹œν–‰μ°©μ˜€
**문제**: Slack의 파일 μ—…λ‘œλ“œ APIκ°€ μ—¬λŸ¬ 번 λ³€κ²½λ˜μ–΄ κΈ°μ‘΄ 방식 deprecated

**ν•΄κ²°μ±…**:
- `files.upload` (deprecated) β†’ `files.getUploadURLExternal` + `files.completeUploadExternal`
- Slack SDK와 κΈ°μ‘΄ REST API의 ν•˜μ΄λΈŒλ¦¬λ“œ 접근법
- 파일 크기별 λ‹€λ₯Έ μ—…λ‘œλ“œ μ „λž΅ κ΅¬ν˜„

```python
# μƒˆλ‘œμš΄ 파일 μ—…λ‘œλ“œ ν”Œλ‘œμš°
# 1. μ—…λ‘œλ“œ URL μš”μ²­
upload_response = await self._make_request('files.getUploadURLExternal', 'POST', upload_data)

# 2. μ™ΈλΆ€ URL둜 파일 μ—…λ‘œλ“œ
async with self._session.put(upload_url, data=file_content) as response:
    # 파일 μ—…λ‘œλ“œ

# 3. μ—…λ‘œλ“œ μ™„λ£Œ 처리
complete_response = await self._make_request('files.completeUploadExternal', 'POST', complete_data)
```

### 4. User Token이 ν•„μš”ν•œ 경우 vs Bot Token만으둜 ν•΄κ²°λ˜λŠ” 경우
**문제**: μ–΄λ–€ κΈ°λŠ₯에 μ–΄λ–€ 토큰이 ν•„μš”ν•œμ§€ νŒŒμ•…ν•˜κΈ° 어렀움

**ν•΄κ²°μ±…**:
- κΈ°λŠ₯별 토큰 μš”κ΅¬μ‚¬ν•­ λͺ…ν™•νžˆ λΆ„λ₯˜
- 이쀑 토큰 μ‹œμŠ€ν…œμœΌλ‘œ μžλ™ 선택
- 토큰 λΆ€μ‘± μ‹œ λͺ…ν™•ν•œ μ•ˆλ‚΄ λ©”μ‹œμ§€

```python
# Bot Token으둜 κ°€λŠ₯ν•œ κΈ°λŠ₯
- λ©”μ‹œμ§€ 전솑 (chat.postMessage)
- 채널 λͺ©λ‘ (conversations.list)
- μ‚¬μš©μž λͺ©λ‘ (users.list)
- 파일 μ—…λ‘œλ“œ (< 100MB)

# User Token이 ν•„μš”ν•œ κΈ°λŠ₯  
- λ©”μ‹œμ§€ 검색 (search.messages)
- λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œ (> 100MB)
```

### 5. GET vs POST의 차이
**문제**: μ–Έμ œ GET을 μ“°κ³  μ–Έμ œ POSTλ₯Ό 써야 ν•˜λŠ”μ§€ ν˜Όλž€

**ν•΄κ²°μ±…**:
- Slack API λ¬Έμ„œμ˜ HTTP λ©”μ†Œλ“œ μ •ν™•νžˆ 확인
- 데이터 μ‘°νšŒλŠ” GET, 데이터 생성/μˆ˜μ •μ€ POST
- ν†΅μΌλœ `_make_request` ν•¨μˆ˜λ‘œ 처리

```python
# GET: 데이터 쑰회
await self._make_request('conversations.list', 'GET', params)
await self._make_request('users.list', 'GET', params)

# POST: 데이터 생성/μˆ˜μ •
await self._make_request('chat.postMessage', 'POST', data)
await self._make_request('files.getUploadURLExternal', 'POST', data)
```

### 6. 기타 ν•΄κ²°ν•œ μ΄μŠˆλ“€
- **Rate Limiting**: μ§€μˆ˜ λ°±μ˜€ν”„μ™€ μž¬μ‹œλ„ 둜직
- **Error Handling**: 각 μ—λŸ¬ μ½”λ“œλ³„ λ§žμΆ€ν˜• ν•΄κ²° μ œμ•ˆ
- **UTF-8 Encoding**: ν•œκΈ€ λ©”μ‹œμ§€ μ™„λ²½ 지원
- **Async Safety**: λ½€λͺ¨λ„λ‘œ νƒ€μ΄λ¨Έμ˜ λ™μ‹œ μ‹€ν–‰ 처리

## πŸ“Š μ„±λŠ₯ 및 μ œν•œμ‚¬ν•­

### 파일 μ—…λ‘œλ“œ μ œν•œ
- **무료 ν”Œλžœ**: μ΅œλŒ€ 5GB μ›Œν¬μŠ€νŽ˜μ΄μŠ€ μŠ€ν† λ¦¬μ§€
- **κ°œλ³„ 파일**: μ΅œλŒ€ 1GB (유료 ν”Œλžœμ—μ„œ)
- **Bot Token**: μ΅œλŒ€ 100MB 파일 μ—…λ‘œλ“œ
- **User Token**: μ΅œλŒ€ 1GB 파일 μ—…λ‘œλ“œ

### API Rate Limits
- **Tier 1 λ©”μ†Œλ“œ**: 1+ per minute
- **Tier 2 λ©”μ†Œλ“œ**: 20+ per minute  
- **Tier 3 λ©”μ†Œλ“œ**: 50+ per minute
- **Tier 4 λ©”μ†Œλ“œ**: 100+ per minute

## πŸ” ν…ŒμŠ€νŠΈ 방법

### 1. μ—°κ²° ν…ŒμŠ€νŠΈ
```bash
# μ„œλ²„ μ‹€ν–‰ ν›„ Claudeμ—μ„œ ν…ŒμŠ€νŠΈ
test_slack_connection()
```

### 2. κΈ°λ³Έ κΈ°λŠ₯ ν…ŒμŠ€νŠΈ
```bash
# 채널 λͺ©λ‘ 쑰회
get_slack_channels()

# λ©”μ‹œμ§€ 전솑 ν…ŒμŠ€νŠΈ  
send_slack_message("C08UZKK9Q4R", "ν…ŒμŠ€νŠΈ λ©”μ‹œμ§€μž…λ‹ˆλ‹€! πŸŽ‰")
```

### 3. κ³ κΈ‰ κΈ°λŠ₯ ν…ŒμŠ€νŠΈ
```bash
# 파일 μ—…λ‘œλ“œ ν…ŒμŠ€νŠΈ
upload_file_to_slack("./test.txt", title="ν…ŒμŠ€νŠΈ 파일")

# λ½€λͺ¨λ„λ‘œ 타이머 ν…ŒμŠ€νŠΈ
start_pomodoro_timer("work", duration_minutes=25, custom_name="ν…ŒμŠ€νŠΈ μž‘μ—…")
```

## 🀝 κΈ°μ—¬ 방법

1. 이슈 제보: GitHub Issues μ‚¬μš©
2. κΈ°λŠ₯ μ œμ•ˆ: Feature Request ν…œν”Œλ¦Ώ μ‚¬μš©  
3. μ½”λ“œ κΈ°μ—¬: Pull Request ν™˜μ˜
4. λ¬Έμ„œ κ°œμ„ : README 및 docstring κ°œμ„ 

## πŸ“„ λΌμ΄μ„ μŠ€

이 ν”„λ‘œμ νŠΈλŠ” MIT λΌμ΄μ„ μŠ€λ₯Ό λ”°λ¦…λ‹ˆλ‹€.

## πŸ™‹β€β™‚οΈ 문의 및 지원

- **개발자**: JunHyuck Kwon
- **버전**: 8.5.2 (Complete Implementation)
- **μ΅œμ’… μ—…λ°μ΄νŠΈ**: 2025-06-04

---

**과제 완성도**: βœ… ν•„μˆ˜ 4개 + βœ… 선택 4개 + βœ… λ³΄λ„ˆμŠ€ 4개 + βœ… μœ ν‹Έλ¦¬ν‹° 4개 = **총 16개 κΈ°λŠ₯ μ™„μ „ κ΅¬ν˜„**

이 ν”„λ‘œμ νŠΈλ₯Ό 톡해 μ‹€μ œ μ—…λ¬΄μ—μ„œ ν™œμš©ν•  수 μžˆλŠ” κ³ ν’ˆμ§ˆ Slack 연동 도ꡬλ₯Ό ꡬ좕할 수 μžˆμŠ΅λ‹ˆλ‹€! πŸš€