# MSN[맥락] 메신저 기능 개발

## 왜 하는가

벡스플로어 ERP 내에서 사용자 간 실시간 커뮤니케이션 수단이 없다. 업무 맥락을 ERP 밖(카카오톡, 슬랙 등)으로 내보내지 않고 시스템 안에서 처리할 수 있도록 내장 메신저를 도입한다.

---

## 핵심 결정 및 근거

| 결정 | 근거 |
|------|------|
| Socket.IO 신규 도입 | HTTP 폴링은 메신저에 부적합. 실시간 타이핑 표시, 온라인 상태, 즉각적인 메시지 수신이 필요 |
| Gmail 스타일 우측 하단 모달 | 업무 화면을 방해하지 않고 언제든 접근 가능. 별도 페이지 이동 없이 사용 |
| DM + 그룹 + 채널 1차 구현 | 채널은 `room_type` 값으로만 분리하여 나중에 제거 용이하게 설계 |
| company_code 격리 | 기존 멀티테넌시 패턴과 동일하게 적용. 회사 간 데이터 유출 방지 |
| 파일 업로드: multer 로컬 | 기존 메일 첨부파일과 동일한 방식. 인프라 추가 없이 일관성 유지 |
| 프로필: photo BLOB 활용 | `user_info.photo` 컬럼에 이미 이미지 저장됨. 없으면 이름 첫 글자 원형 아바타 |
| 토스트 알림 on/off | 집중 업무 시 알림 방해 방지. localStorage에 설정 저장 |

---

## 관련 파일

### 참고 패턴 (기존 코드)
| 파일 | 참고 목적 |
|------|-----------|
| `backend-node/src/config/multerConfig.ts` | 파일 업로드 설정 패턴 |
| `backend-node/src/services/authService.ts` | user_info.photo BLOB → base64 변환 패턴 |
| `backend-node/src/middleware/authMiddleware.ts` | JWT 인증 미들웨어 (Socket.IO handshake에도 동일 로직 적용) |
| `frontend/components/mail/` | UI 컴포넌트 구조 참고 |
| `frontend/hooks/use-toast.ts` | 기존 토스트 훅 사용 |
| `backend-node/src/app.ts` | 라우트 등록 및 미들웨어 설정 위치 |

---

## 기술 참고

### Socket.IO JWT 인증
```typescript
// 서버: handshake 시 토큰 검증
io.use((socket, next) => {
  const token = socket.handshake.auth.token;
  const user = verifyJWT(token);
  socket.data.user = user;
  next();
});

// 클라이언트: 연결 시 토큰 전달
const socket = io(BACKEND_URL, {
  auth: { token: localStorage.getItem('token') }
});
```

### 채널 분리 설계
채널 기능은 `room_type = 'channel'` 조건으로만 분리되어 있음.
제거 시: RoomList의 채널 탭 UI 제거 + `/api/messenger/rooms?type=channel` 호출 제거만으로 완전 비활성화 가능. DB 스키마 변경 불필요.

### 멀티테넌시 적용
모든 쿼리에 `WHERE company_code = $n` 조건 필수 적용.
Socket.IO 룸 네이밍: `{company_code}:{room_id}` 형식으로 회사별 격리.
