Files
vexplor_dev/docs/yc/MSN[맥락]-메신저기능.md
2026-03-30 17:52:57 +09:00

2.7 KiB

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 인증

// 서버: 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} 형식으로 회사별 격리.