실시간 마을 채팅 티커

- 오른쪽 상단에 한 줄씩 뜨는 반투명 채팅, 20초 후 페이드아웃 (최대 6줄)
- 💬 버튼으로 입력창 토글, Enter 전송 / ESC 닫기
- SSE 스트림(/api/chat/stream): 접속 즉시 연결, 최근 20개 백로그는 비동기 전송,
  25초 하트비트로 프록시 유휴 타임아웃 방지
- 전송(/api/chat/send): 닉네임+토큰 검증(사칭 방지), 1.5초 도배 제한, 120자 제한
- chat_messages 테이블 자동 생성, 인프로세스 EventEmitter 브로드캐스트 (단일 컨테이너)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
이 커밋은 다음에 포함됨:
kjs
2026-08-14 16:38:25 +09:00
co-authored by Claude Fable 5
부모 7ae93bee91
커밋 ad157bc4fe
5개의 변경된 파일과 320개의 추가작업 그리고 0개의 파일을 삭제
+6
파일 보기
@@ -5,6 +5,7 @@ import { useGame } from "@/hooks/useGame";
import VillageView, { type PlacingState } from "@/components/game/VillageView";
import DbStatus from "@/components/DbStatus";
import NicknameModal from "@/components/game/NicknameModal";
import ChatTicker from "@/components/game/ChatTicker";
import {
engine,
effectiveRate,
@@ -232,6 +233,11 @@ export default function Game() {
}
/>
{/* ── 실시간 마을 채팅 (닉네임 확정 후) ── */}
{state.nickname && state.syncToken && (
<ChatTicker nickname={state.nickname} token={state.syncToken} />
)}
{/* ── 닉네임 입력 (인사 후, 미입력 시 게임 차단) ── */}
{!state.nickname && (state.tutorialStep ?? TUTORIAL_DONE) >= 1 && (
<NicknameModal onDone={() => dispatch(() => undefined)} />