docs: NaverWorks-Slack 연동 구현 완료 문서 업데이트
- 코드 분석 결과 반영 (51124 서버 확인) - 구현 결정 사항 정리 (6가지 핵심 결정) - 우선순위별 구현 체크리스트 (P0, P1, P2) - 실제 데이터 흐름 15단계 상세 기록 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d01e35452e
commit
6bd22f0a3f
@ -1,9 +1,9 @@
|
|||||||
# NAVER WORKS → Slack 연동 [1/3] 기본 구성
|
# NAVER WORKS → Slack 연동 [1/3] 기본 구성
|
||||||
|
|
||||||
## 날짜: 2025-09-19
|
## 날짜: 2025-09-19 (수정: 2025-01-09)
|
||||||
## 작성자: Claude (51123 서버 관리자)
|
## 작성자: Claude (51123 서버 관리자) / happybell80
|
||||||
## 관련 서비스: rb8001, skill-email, auth-server
|
## 관련 서비스: rb8001, skill-email, skill-slack, auth-server
|
||||||
## 상태: 기본 구조 구현 필요
|
## 상태: 기본 구조 부분 구현
|
||||||
|
|
||||||
## 관련 문서
|
## 관련 문서
|
||||||
- [2/3 일일 브리핑](./250919_naverworks_slack_02_daily_briefing.md)
|
- [2/3 일일 브리핑](./250919_naverworks_slack_02_daily_briefing.md)
|
||||||
@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 1. 현재 구현 상태 (2025-01-09 확인)
|
||||||
## 1. 현재 구현 상태 (코드 분석 기준)
|
|
||||||
|
|
||||||
### 구현 완료
|
### 구현 완료
|
||||||
- **auth-server**:
|
- **auth-server**:
|
||||||
@ -24,16 +23,19 @@
|
|||||||
- GET `/messages` 엔드포인트 (provider 파라미터 지원)
|
- GET `/messages` 엔드포인트 (provider 파라미터 지원)
|
||||||
- POST `/send` 엔드포인트
|
- POST `/send` 엔드포인트
|
||||||
- registry.register("naverworks", NaverWorksProvider()) 등록됨
|
- registry.register("naverworks", NaverWorksProvider()) 등록됨
|
||||||
|
- **skill-slack (포트 8502)**:
|
||||||
|
- POST `/api/v1/send` 토큰 파라미터 지원 (2025-01-09)
|
||||||
|
- 멀티 워크스페이스 지원 가능
|
||||||
- **NAVER WORKS Mail API**:
|
- **NAVER WORKS Mail API**:
|
||||||
- ✅ 올바른 엔드포인트 확인: `/mail/mailfolders/{folderId}/children`
|
- ✅ 올바른 엔드포인트 확인: `/mail/mailfolders/{folderId}/children`
|
||||||
- ✅ mailAddress null 문제 해결 (API 사용에 영향 없음)
|
- ✅ mailAddress null 문제 해결 (API 사용에 영향 없음)
|
||||||
- ✅ 9,192개 메일 정상 조회 확인
|
- ✅ 9,192개 메일 정상 조회 확인
|
||||||
|
|
||||||
### 미구현/불일치
|
### 미구현/문제점
|
||||||
- **rb8001**: provider=naverworks 미지정 → 기본 Gmail만 사용
|
- **rb8001**: provider 파라미터 없음, UUID 변환 누락 (list 경로)
|
||||||
- **skill-email**: `/mail-summary` 엔드포인트 없음 (문서에만 제안)
|
- **skill-slack**: rb8001과 미연동 (직접 WebClient 사용)
|
||||||
- **식별자**: Slack ID → UUID 변환이 send에만 부분 적용
|
- **24시간 필터**: 어디에도 구현 안 됨
|
||||||
- **보안 위험**: NaverWorksProvider.DEFAULT_USER_ID 하드코딩 존재
|
- **토큰 갱신**: 자동 호출 없음 (수동 함수만 존재)
|
||||||
|
|
||||||
### 잘못된 전제 정정
|
### 잘못된 전제 정정
|
||||||
- ❌ "skill-naverworks(8511) 구현 완료" → ✅ skill-email(8501) 멀티 프로바이더로 통합
|
- ❌ "skill-naverworks(8511) 구현 완료" → ✅ skill-email(8501) 멀티 프로바이더로 통합
|
||||||
@ -64,186 +66,149 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. 오케스트레이션 구조와 skill-slack 통합
|
## 3. 정확한 구현 경로
|
||||||
|
|
||||||
### 3.1 rb8001 오케스트레이션 흐름
|
### 3.1 전체 데이터 흐름 (토큰 갱신 포함)
|
||||||
```
|
|
||||||
Slack 요청 → rb8001 (중앙 오케스트레이터)
|
**시나리오**: 슬랙에서 "네이버웍스 메일 확인" 메시지를 보내면 최근 24시간 이내 받은 메일 전체가 슬랙 채널에 표시
|
||||||
├→ skill-email (메일 데이터 조회)
|
|
||||||
├→ 필터링/분석 (rb8001 내부)
|
**상세 흐름**:
|
||||||
├→ skill-slack (Slack 포맷팅)
|
1. 슬랙 "네이버웍스 메일 확인" → Gateway
|
||||||
└→ Slack 응답
|
2. Gateway가 slack_user_mapping에서 UUID 조회 → X-User-Id 헤더
|
||||||
|
3. Gateway가 slack_workspace에서 봇 토큰 조회 → X-Slack-Bot-Token 헤더
|
||||||
|
4. Gateway가 X-Source: "slack" 헤더 추가
|
||||||
|
5. Gateway → rb8001 (헤더 + 메시지)
|
||||||
|
6. rb8001이 X-Source 확인 → slack 요청임을 인지
|
||||||
|
7. rb8001 → skill-email:8501/messages?provider=naverworks&user_id={uuid}
|
||||||
|
8. skill-email이 naverworks_token에서 액세스 토큰 조회
|
||||||
|
9. 토큰 만료 체크 → 만료시 auth-server:8000/auth/naverworks/passport/refresh 호출
|
||||||
|
10. auth-server가 naverworks_token 테이블 업데이트 → 새 토큰 반환
|
||||||
|
11. NaverWorks API 호출 → 24시간 이내 메일 전체 반환
|
||||||
|
12. rb8001이 메일 데이터를 슬랙 메시지 형식으로 포맷팅 (blocks, markdown)
|
||||||
|
13. rb8001 → skill-slack:8502/api/v1/send (channel, text, blocks, token)
|
||||||
|
14. skill-slack이 슬랙 API 형식에 맞게 최종 포맷팅
|
||||||
|
15. skill-slack → 슬랙 채널에 메일 표시
|
||||||
|
|
||||||
|
**Gateway → rb8001 전달 정보**:
|
||||||
|
|
||||||
|
Headers:
|
||||||
|
- `X-User-Id`: UUID (Slack user를 UUID로 변환)
|
||||||
|
- `X-Slack-Bot-Token`: 봇 토큰 (Gateway가 DB에서 조회)
|
||||||
|
- `X-Source`: "slack" (요청 출처 구분)
|
||||||
|
- `X-Slack-Signature`: Slack 서명
|
||||||
|
- `X-Slack-Request-Timestamp`: 타임스탬프
|
||||||
|
|
||||||
|
Body (원본 그대로):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"team": {"id": "T0925SXPS4D"},
|
||||||
|
"event": {
|
||||||
|
"user": "U0928DT3MDW",
|
||||||
|
"channel": "C07V9F3V21V",
|
||||||
|
"text": "네이버웍스 메일 확인"
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**rb8001의 역할:**
|
**프론트엔드 요청 경로**:
|
||||||
- 사용자 의도 파악
|
|
||||||
- 스킬 조합 결정
|
|
||||||
- 데이터 가공 및 필터링
|
|
||||||
- 최종 응답 전송
|
|
||||||
|
|
||||||
### 3.2 skill-slack 현재 구조 및 추가 역할
|
|
||||||
|
|
||||||
**실제 파일 구조 (포트 8502):**
|
|
||||||
```
|
```
|
||||||
skill-slack/
|
Frontend → Gateway → rb8001 → skill-email → rb8001 → skill-slack → Slack
|
||||||
├── app/
|
|
||||||
│ ├── main.py # FastAPI 앱, API 버전 설정
|
|
||||||
│ ├── api/
|
|
||||||
│ │ └── endpoints/
|
|
||||||
│ │ ├── messages.py # /messages/send, /messages/update
|
|
||||||
│ │ ├── summarize.py # /summarize
|
|
||||||
│ │ └── digest.py # /digest
|
|
||||||
│ ├── services/
|
|
||||||
│ │ ├── slack_service.py # SlackService 클래스
|
|
||||||
│ │ ├── message_formatter.py # 메시지 포맷 헬퍼
|
|
||||||
│ │ └── summarize_service.py # 요약 서비스
|
|
||||||
│ ├── models/
|
|
||||||
│ │ └── slack_models.py # BaseSkillRequest 등 Pydantic 모델
|
|
||||||
│ └── core/
|
|
||||||
│ └── config.py # Settings 설정
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**기존 엔드포인트 (모두 `/api/v1` prefix):**
|
Gateway → rb8001 전달 정보:
|
||||||
| 엔드포인트 | 역할 | 현재 상태 | Request Body |
|
- Headers: `X-User-Id`, `X-Source`: "frontend"
|
||||||
|-----------|------|-----------|--------------|
|
- Body: `{"text": "메시지", "user_id": "UUID", "context": {}}`
|
||||||
| POST `/api/v1/messages/send` | Slack 메시지 전송 | ✅ 구현됨 | BaseSkillRequest + message |
|
|
||||||
| POST `/api/v1/messages/update` | 메시지 업데이트 | ✅ 구현됨 | BaseSkillRequest + ts + message |
|
|
||||||
| POST `/api/v1/summarize` | 대화 요약 | ✅ 구현됨 | BaseSkillRequest + messages |
|
|
||||||
| POST `/api/v1/digest` | 스레드 다이제스트 | ✅ 구현됨 | BaseSkillRequest + thread_ts |
|
|
||||||
|
|
||||||
**BaseSkillRequest 구조:**
|
### 3.2 현재 사용 가능한 엔드포인트
|
||||||
```python
|
|
||||||
class BaseSkillRequest(BaseModel):
|
|
||||||
team_id: str
|
|
||||||
user_id: str
|
|
||||||
channel_id: str
|
|
||||||
thread_ts: Optional[str] = None
|
|
||||||
```
|
|
||||||
|
|
||||||
**추가 필요 엔드포인트:**
|
**skill-email (포트 8501)**:
|
||||||
| 엔드포인트 | 역할 | 입력 | 출력 |
|
- GET `/messages?provider=naverworks&user_id={uuid}` - 메일 목록 조회
|
||||||
|-----------|------|------|------|
|
- POST `/send` - 메일 발송 (provider 필드 포함)
|
||||||
| POST `/api/v1/format/mail-list` | 메일 목록을 Slack 블록으로 변환 | BaseSkillRequest + mails | Block Kit JSON |
|
|
||||||
| POST `/api/v1/format/cold-mail` | 콜드메일 테이블 포맷 생성 | BaseSkillRequest + cold_mails | Table Block |
|
|
||||||
| POST `/api/v1/format/briefing` | 일일 브리핑 포맷 생성 | BaseSkillRequest + briefing_data | Briefing Block |
|
|
||||||
|
|
||||||
### 3.3 skill-email 파일별 역할 (최소 변경 원칙)
|
**skill-slack (포트 8502)**:
|
||||||
| 파일 경로 | 역할 | 구현 내용 | 예상 코드 줄 수 |
|
- POST `/api/v1/send` - Slack 메시지 전송
|
||||||
|-----------|------|-----------|----------------|
|
- 필수: channel, text
|
||||||
| `main.py` | 앱 실행, 라우터 등록 | 기존 엔드포인트 유지, 새 라우터만 추가 | +5줄 추가 |
|
- 선택: token, thread_ts, blocks
|
||||||
| `routers/naverworks_mail.py` (신규) | HTTP 요청 처리 | `/cold-mail-list`, `/daily-briefing` 엔드포인트 | 30-40줄 |
|
|
||||||
| `services/naverworks_mail_service.py` (신규) | 비즈니스 로직 | 콜드메일 필터링, 브리핑 생성 로직 | 100-150줄 |
|
|
||||||
| `services/naverworks_provider.py` | NAVER WORKS API 연동 | 기존 파일 활용, 메서드만 추가 | +50줄 추가 |
|
|
||||||
| `repositories/mail_cache_repository.py` (신규) | DB CRUD 작업 | 메일 캐시 저장/조회 SQL | 50-60줄 |
|
|
||||||
| `models/mail_cache.py` (신규) | DB 테이블 정의 | SQLAlchemy ORM 모델 (mail_cache 테이블) | 15-20줄 |
|
|
||||||
| `schemas/naverworks_schemas.py` (신규) | API 입출력 형식 | Pydantic 모델 (Request/Response) | 30-40줄 |
|
|
||||||
| `core/slack_formatter.py` (신규) | Slack 포맷터 | 메일→Slack 블록 변환 | 50-70줄 |
|
|
||||||
|
|
||||||
### 3.4 데이터 계층 구분
|
### 3.3 수정 필요 위치
|
||||||
| 계층 | 파일 종류 | 역할 | 비유 |
|
|
||||||
|------|-----------|------|------|
|
|
||||||
| **Model** | `models/*.py` | DB 테이블 구조 정의 (SQLAlchemy ORM) | 창고 선반 설계도 (내부용) |
|
|
||||||
| **Schema** | `schemas/*.py` | API 요청/응답 형식 (Pydantic) | 손님 주문서 양식 (외부용) |
|
|
||||||
| **Repository** | `repositories/*.py` | DB 접근 로직 (CRUD) | 창고 관리 직원 |
|
|
||||||
| **Database** | `db/session.py` | DB 연결 관리 | 창고 출입문 열쇠 |
|
|
||||||
|
|
||||||
#### 데이터 흐름 예시
|
**rb8001/app/skills/email_integration.py**:
|
||||||
```
|
- 262행: GET `/messages` 호출 시 provider 파라미터 누락
|
||||||
1. API 요청 → Schema (검증)
|
- 현재 코드: `params={"user_id": user_id, "limit": 5}` (Gmail만 조회)
|
||||||
2. Service → Repository (DB 작업 요청)
|
- 필요한 수정: provider=naverworks 파라미터 추가
|
||||||
3. Repository → Model (ORM으로 DB 테이블 접근)
|
|
||||||
4. Model → Database (실제 SQL 실행)
|
|
||||||
5. 결과 → Schema (응답 포맷) → API 응답
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.5 rb8001 파일별 역할
|
**rb8001/app/router/slack_handler.py**:
|
||||||
| 파일 경로 | 역할 | 구현 내용 |
|
- 274행: `local_client.chat_postMessage()` 직접 호출
|
||||||
|-----------|------|-----------|
|
- 311행: `WebClient(token=custom_token)` 직접 생성
|
||||||
| `app/main.py` | 메시지 라우팅 | Slack 메시지 수신 및 처리 |
|
- skill-slack 사용 안 함
|
||||||
| `app/skills/email_integration.py` | 이메일 스킬 통합 | NaverWorks 지원 추가 |
|
|
||||||
| `app/services/scheduler.py` | 스케줄러 | 일일 브리핑 자동 실행 |
|
**robeing-gateway/app/main.py**:
|
||||||
| `app/schemas/skill_schemas.py` | 스킬 요청/응답 형식 | SkillRequest, SkillResponse |
|
- 553, 560, 611, 615행: X-User-Id, X-Slack-Bot-Token 헤더 설정
|
||||||
|
- X-Source 헤더 없음 (요청 출처 구분 불가)
|
||||||
|
|
||||||
### 3.6 auth-server 파일별 역할
|
|
||||||
| 파일 경로 | 역할 | 현재 상태 |
|
|
||||||
|-----------|------|-----------|
|
|
||||||
| `app/providers/naverworks.py` | OAuth 로그인 | ✅ 구현됨 |
|
|
||||||
| `app/providers/naverworks_passport.py` | Passport 시스템 | ✅ 구현됨 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. 기본 연동 테스트 시나리오
|
## 4. 확인된 사실과 구현 체크리스트
|
||||||
|
|
||||||
### 4.1 자동 Provider 감지 테스트 (skill-slack 포함)
|
### 코드 분석 결과 (2025-01-09)
|
||||||
- Slack: "@로빙 메일 확인"
|
- **skill-slack**: 8502 포트 엔드포인트 구현됨, rb8001은 직접 WebClient 사용 중 (미연동)
|
||||||
- rb8001 흐름:
|
- **provider 구분**: 미구현, 기본 Gmail만 동작 (rb8001/app/skills/email_integration.py:260-266)
|
||||||
1. DB 조회 (gmail_token, naverworks_token)
|
- **24시간 필터**: 미구현, orderBy만 있음 (skill-email/services/naverworks_provider.py:167)
|
||||||
2. provider 자동 결정
|
- NaverWorks API는 searchDateType, startSearchDate, endSearchDate 파라미터 지원
|
||||||
3. skill-email 호출 → 메일 데이터 획득
|
- **토큰 갱신**: NaverWorks는 auth-server 위임, 자동 호출 없음
|
||||||
4. skill-slack `/format-mail-list` → Slack 블록 생성
|
- **UUID 변환**: list 경로에서 변환 없음 (263행 user_id는 입력 그대로 전달)
|
||||||
5. Slack 응답
|
|
||||||
|
|
||||||
### 4.2 명시적 Provider 지정
|
### 필수 수정 사항 (우선순위별)
|
||||||
- Slack: "@로빙 네이버웍스 메일 확인"
|
**P0 (즉시)**:
|
||||||
- DB 조회 없이 바로 provider=naverworks 사용
|
- [ ] skill-slack thread_ts 버그 수정 (messages.py:29-33)
|
||||||
- 오버라이드로 특정 provider 강제 지정
|
- [ ] skill-slack API Key 인증 추가 (messages 엔드포인트)
|
||||||
|
|
||||||
|
**P1 (1주)**:
|
||||||
|
- [ ] Gateway UUID 변환 완전 처리
|
||||||
|
- [ ] rb8001 provider 로직: 키워드→DB조회→질문
|
||||||
|
- [ ] skill-email 24시간 필터 (API 파라미터)
|
||||||
|
- [ ] skill-email DEFAULT_USER_ID 제거 (31행)
|
||||||
|
- [ ] skill-email 401 에러 시 토큰 갱신
|
||||||
|
|
||||||
|
**P2 (점진적)**:
|
||||||
|
- [ ] 새 기능만 skill-slack 사용
|
||||||
|
- [ ] 기존 코드 부분 전환
|
||||||
|
|
||||||
### 4.3 DB 조회 로직 구현
|
|
||||||
- rb8001/app/skills/email_integration.py에 detect_email_provider 메서드 추가
|
|
||||||
- gmail_token 테이블에서 is_equipped=true인 계정 확인
|
|
||||||
- naverworks_token 테이블에서 사용자 계정 확인
|
|
||||||
- 둘 다 있으면 "both", 하나만 있으면 해당 provider, 없으면 "none" 반환
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. 기본 구성 구현 체크리스트
|
## 5. 주요 파일 위치와 역할
|
||||||
|
|
||||||
### 5.1 rb8001 수정
|
### rb8001 (포트 8001)
|
||||||
- [ ] `app/skills/email_integration.py` 수정
|
- **app/skills/email_integration.py**: Gmail 스킬 통합 (네이버웍스 추가 필요)
|
||||||
- [ ] `detect_email_provider()` 함수 추가 - DB 기반 자동 감지
|
- **app/router/slack_handler.py**: Slack 이벤트 처리 (현재 직접 호출)
|
||||||
- [ ] get_messages()에 자동 provider 선택 로직
|
|
||||||
- [ ] send_email()에 자동 provider 선택 로직
|
|
||||||
- [ ] 둘 다 있을 때 선택 UI 구현
|
|
||||||
- [ ] DB 조회 로직 구현
|
|
||||||
- [ ] gmail_token 테이블 조회
|
|
||||||
- [ ] naverworks_token 테이블 조회
|
|
||||||
- [ ] 결과 기반 provider 자동 결정
|
|
||||||
- [ ] Slack ID → UUID 변환 일관성 확보
|
|
||||||
- [ ] get_uuid_from_slack() 활용 확대
|
|
||||||
- [ ] 모든 skill-email 호출에 UUID 사용
|
|
||||||
|
|
||||||
### 5.2 skill-slack 구현
|
### skill-email (포트 8501)
|
||||||
- [ ] 새 엔드포인트 추가 (`/api/v1` prefix 필수)
|
- **services/naverworks_provider.py**: 네이버웍스 Provider 구현
|
||||||
- [ ] POST `/api/v1/format/mail-list` - 기본 메일 목록 포맷
|
- 270행: refresh_token() 함수 존재 (auth-server의 `/auth/naverworks/passport/refresh` 호출)
|
||||||
- [ ] POST `/api/v1/format/cold-mail` - 콜드메일 테이블 포맷
|
- 150행: list_messages() - 토큰 만료 체크 없이 바로 사용
|
||||||
- [ ] POST `/api/v1/format/briefing` - 일일 브리핑 포맷
|
- 31행: DEFAULT_USER_ID 하드코딩 문제
|
||||||
- [ ] BaseSkillRequest 상속 모델 구현
|
- **main.py**: 엔드포인트 정의
|
||||||
- [ ] MailListRequest(BaseSkillRequest)
|
- 210행: GET `/messages` - provider 파라미터로 gmail/naverworks 분기
|
||||||
- [ ] ColdMailRequest(BaseSkillRequest)
|
- POST `/send`
|
||||||
- [ ] BriefingRequest(BaseSkillRequest)
|
- **services/gmail_service.py**
|
||||||
- [ ] Slack Block Kit Builder 구현
|
- 60-72행: 토큰 자동 갱신 구현 (creds.expired 체크 후 refresh)
|
||||||
- [ ] Section blocks
|
|
||||||
- [ ] Divider blocks
|
### skill-slack (포트 8502)
|
||||||
- [ ] Context blocks
|
- **app/api/endpoints/messages.py**: 메시지 전송 엔드포인트
|
||||||
|
- **app/models/requests.py**: SlackMessageRequest 모델 (token 필드 포함)
|
||||||
|
|
||||||
### 5.3 skill-email 수정
|
|
||||||
- [ ] `services/naverworks_provider.py` 수정
|
|
||||||
- [ ] DEFAULT_USER_ID 하드코딩 제거
|
|
||||||
- [ ] account_id 없을 시 명확한 에러 처리
|
|
||||||
- [ ] 에러 응답 표준화
|
|
||||||
- [ ] 400: 잘못된 요청
|
|
||||||
- [ ] 422: 필수 정보 누락
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. 환경 설정 및 주의사항
|
## 6. 결정 사항 (2025-01-09)
|
||||||
|
|
||||||
### 6.1 환경 설정 확인
|
### 구현 결정
|
||||||
- skill-email .env 파일에 NAVER WORKS 관련 설정 확인
|
1. **Provider 선택**: 키워드 우선 → DB 조회 → 둘 다 있으면 질문
|
||||||
- rb8001에서 skill-email 호출 시 포트 8501 사용
|
2. **24시간 필터**: skill-email에서 API 파라미터 처리 (startSearchDate, endSearchDate)
|
||||||
- auth-server의 NAVER WORKS OAuth 설정 확인
|
3. **토큰 갱신**: 401 에러 후 재시도 (1회)
|
||||||
|
4. **UUID 변환**: Gateway에서 모두 변환
|
||||||
|
5. **skill-slack 전환**: 단계적 (새 기능부터)
|
||||||
|
6. **메일 표시**: 5개 요약 + "더보기" 버튼
|
||||||
|
|
||||||
### 6.2 보안 주의사항
|
|
||||||
- **계정 오매핑 방지**: DEFAULT_USER_ID 제거로 잘못된 계정 접근 차단
|
|
||||||
- **UUID 검증**: 모든 사용자 식별자를 UUID로 표준화
|
|
||||||
- **에러 처리**: 명확한 HTTP 상태 코드로 문제 진단 용이
|
|
||||||
Loading…
x
Reference in New Issue
Block a user