Socket.io 기반 실시간 채팅 애플리케이션
URL: https://chat.gnuboard.net
| 구분 | 기술 |
|---|---|
| 프레임워크 | Next.js 16 (App Router) |
| 런타임 | Node.js + tsx |
| 실시간 통신 | Socket.io 4 |
| 스타일링 | Tailwind CSS 4 (CSS 변수 기반 테마) |
| 언어 | TypeScript |
| 배포 | PM2 + Apache2 리버스 프록시 + Let's Encrypt SSL |
- 공개방 — 누구나 입장 가능
- 비밀방 — 비밀번호 입력 후 입장
- 1:1 DM — 최대 2명 참여
- Socket.io를 통한 실시간 메시지 송수신
- 내 메시지 / 상대방 메시지 좌우 구분 표시
- 시스템 메시지 (입장, 퇴장, 닉네임 변경 등)
sessionStorage기반 세션 ID로 탭 단위 사용자 식별- 새로고침 시 소켓 재연결을 감지하여 메시지 유지 + 조용한 재접속 (시스템 메시지 없음)
- 10초 연결 끊김 유예 기간 (Disconnect Grace) — 새로고침/일시적 끊김 시 퇴장 처리하지 않음
- 30초 빈 방 정리 타이머 — 모든 참여자가 떠난 후 30초 뒤 방 삭제
- 라이트 / 다크 모드 전환
- CSS 커스텀 프로퍼티 기반 시맨틱 컬러 토큰
localStorage에 테마 설정 저장
- 닉네임 변경 (방 내에서)
- 채팅 내역 텍스트 파일 다운로드
- 참여자 목록 사이드바
- 로비에서 저장된 닉네임 표시
chat/
├── server.ts # 커스텀 HTTP 서버 (Next.js + Socket.io)
├── ecosystem.config.js # PM2 설정 (.gitignore)
├── package.json
├── tsconfig.json
├── next.config.ts
├── postcss.config.mjs
└── src/
├── app/
│ ├── globals.css # 테마 변수 (라이트/다크)
│ ├── layout.tsx # 루트 레이아웃 (ThemeProvider)
│ ├── page.tsx # 로비 (방 목록, 방 생성/입장)
│ └── room/
│ └── [id]/
│ └── page.tsx # 채팅방 (메시지, 참여자, 설정)
└── lib/
├── socket.ts # Socket.io 클라이언트 싱글턴 + 세션 ID
├── theme.tsx # ThemeProvider + useTheme 훅
└── types.ts # 공용 타입 (Message, RoomInfo)
소켓 ID 대신 세션 ID로 참여자를 식별합니다. 이를 통해 페이지 새로고침이나 일시적 연결 끊김 시에도 동일 사용자로 인식합니다.
클라이언트 (sessionStorage)
└─ sessionId (crypto.randomUUID)
└─ Socket.io auth로 전달
└─ 서버에서 sessionId 기준으로 참여자 관리
소켓 끊김 발생
└─ 10초 유예 타이머 시작
├─ 10초 내 재접속 → 타이머 취소 (조용한 재접속)
└─ 10초 경과 → 퇴장 처리 + 시스템 메시지
└─ 방 참여자 0명이면 → 30초 후 방 삭제
| 이벤트 | 방향 | 설명 |
|---|---|---|
room:list |
S→C | 방 목록 전송 |
room:list:request |
C→S | 방 목록 재요청 |
room:create |
C→S | 방 생성 |
room:join |
C→S | 방 입장 |
room:state |
C→S | 방 상태 조회 (재접속 시) |
room:leave |
C→S | 방 퇴장 |
room:participants |
S→C | 참여자 목록 갱신 |
message:send |
C→S | 메시지 전송 |
message:new |
S→C | 새 메시지 수신 |
nickname:change |
C→S | 닉네임 변경 |
chat:download |
C→S | 채팅 내역 다운로드 |
npm install
npm run devhttp://localhost:3000 에서 접속
npm run build
npm run start# ecosystem.config.js 생성 후
pm2 start ecosystem.config.js
pm2 save- 서버: Ubuntu + Apache2 리버스 프록시
- SSL: Let's Encrypt (certbot)
- 프로세스 관리: PM2 (fork 모드, tsx 인터프리터)
- 포트: 5200 (내부) → Apache가 443으로 프록시
- WebSocket:
mod_proxy_wstunnel을 통한 WebSocket 프록시