← 목록
기타 2026-08-01 6KB 읽기 5분

crowny-gametools 서버·화면 통합 — 티옴타·퀴즈배틀 (T199+T200+T202)

개요

/Users/ef/crowny-gametools 서버.한선과 web/ 화면에 검증완료 엔진 2본(티옴타.한선, 퀴즈배틀.한선)을 배선. SSOT=SPEC.md 바카라/시험운영 선례를 그대로 확장(룸 게임모드 필드, deal 분기, /api/quiz/* 라우트).

무엇을 했는지

  1. 서버.한선: _방게임모드("none"|"tiomta"|"quiz") + _방티옴타(직렬화) + 퀴즈 room 필드 3종
(_방퀴즈문제idx/_방퀴즈답안/_방퀴즈점수, 전부 문자열/정수) 추가. /api/room/new?game=, /tiomta/{room} /quiz/{room} HTML 라우트, /api/deal 분기(tiomta→티옴타배분 결과를 tio 필드에, quiz→카드 배분 없이 phase만 dealt), /api/quiz/next(이전 라운드 채점 + 무작위 출제 + 초기화), /api/quiz/answer?room&seat&pick(답안 누적 기록). 퀴즈뱅크(data/퀴즈뱅크.psv, 기존 20문항)는 부팅 1회 퀴즈배틀부팅()으로 로드.
  1. web/티옴타.html: 참가자(?seat=N) 4장 카드 inline SVG(▲○▽●) + 합산·점수, 딜러뷰 좌석 그리드.
  2. web/퀴즈.html: 딜러 출제 버튼·문제/점수판, 참가자 4지선다 대형버튼(터치=answer API, 250ms 폴링).
  3. web/랜딩.html: 게임 선택 세그먼트(레디/티옴타/퀴즈배틀) 추가, 선택된 게임에 맞는 라우트로 이동.
  4. 한선씨 동반: 티옴타화면.한선·퀴즈화면.한선(화면시험.한선 패턴 최소판, 순수계산 자체검증
15/15·8/8 PASS) + 공통.한선카드기호/손패합산_클라/점수판정_클라/티옴타파싱 추가 (web/공통.js 신규 클라 함수의 한선씨 동반본).

★실사고로 잡은 VM함정 (신규, 미문서화였던 것)

request-scope 메모리마커()/메모리복원()이 영속 전역 배열을 되감아 오염시킨다. 서버.한선 accept 루프는 요청마다 배열마크=메모리마커() → 처리 → 메모리복원(배열마크)로 "이번 요청이 만든 임시 배열"만 회수하려 하지만, 퀴즈배틀.한선의 좌석배열/선택배열처럼 요청 중 추가()로 키워지는 영속 전역 배열까지 같은 배열힙에서 되감긴다. 다음 요청이 같은 번지를 재사용하면 이전 요청에서 저장한 값이 소급 오염된다(실측: /api/quiz/answer 2회째 호출 직후 1회째 항목의 seat 필드가 통째로 2회째 요청의 원시 HTTP 텍스트로 뒤바뀜 — 파라미터명 리네임 으로는 재현 불변, 순수 배열힙 재사용 문제로 확인).

우회(적용됨): 여러 요청에 걸쳐 사는 room 상태는 (기존 _방좌석 비트문자열 패턴과 동일하게) 문자열/정수 필드로만 관리하고, 퀴즈배틀.한선의 배열기반 라운드 헬퍼(라운드초기화/좌석답안기록/ 답안직렬화/점수문자열화/라운드채점/선착순정답판정)는 request-scope 서버에서 호출하지 않음 (엔진의 순수 조회 함수 출제/현재문제텍스트/현재보기/현재정답번호만 안전 재사용). 서버.한선에 _퀴즈답안개수/_퀴즈채점 헬퍼로 동등 로직을 문자열 파싱으로 재구현.

이 함정은 ~/.claude/templates/한선씨-가드레일.md에도 반영 필요(다음 세션 몫).

검증 (격리 사본, 라이브 9625 무접촉)

/tmp/gt_iso에 사본 배포, 포트 9629(9625/9626/9627/9628 충돌 확인 후 free 포트 선택)로 기동.

  • ./hanseonc_high 서버.한선 STRICT 경고 0건 (9236 토큰, 20272 큐브)
  • tiomta: room new → seat×3 ready → deal → state의 tio 필드에 4장씩 3좌석 직렬화 확인
  • quiz: room new → /api/quiz/next(출제) → seat1/seat2 answer → state qans 정상 누적
("1,1,1|2,2,2") → 다음 /api/quiz/next 호출 시 이전 라운드 채점되어 qscore":"1:10" 확인
  • 기존 game=none(트라이얼) 룸도 회귀 없이 바카라 배분 정상 동작 확인
  • 격리 서버 종료, /tmp/gt_iso 삭제. 라이브 9625는 무접촉.

관련 파일

  • /Users/ef/crowny-gametools/서버.한선 (게임모드/퀴즈 라우트 추가)
  • /Users/ef/crowny-gametools/공통.한선 (클라 대응 계산 함수 추가)
  • /Users/ef/crowny-gametools/티옴타화면.한선 /Users/ef/crowny-gametools/퀴즈화면.한선 (신규, 화면시험 패턴)
  • /Users/ef/crowny-gametools/web/티옴타.html /Users/ef/crowny-gametools/web/퀴즈.html (신규)
  • /Users/ef/crowny-gametools/web/랜딩.html /Users/ef/crowny-gametools/web/공통.js (수정)
  • /Users/ef/crowny-gametools/티옴타.한선 /Users/ef/crowny-gametools/퀴즈배틀.한선 (기존 엔진, 미수정)

잔여 이슈 (다음 티켓 T203 몫)

  • 라이브 9625 재기동 필요(이번 작업은 라이브 무접촉 지시로 배선만, 재기동은 별도 티켓).
  • 퀴즈 라운드 상태가 room-scope지만 문제뱅크 출제 함수(출제())는 여전히 엔진 전역
현재문제인덱스 하나를 공유 — 동시에 여러 quiz room이 /api/state 폴링을 인터리브해도 _퀴즈JSON조각이 매번 출제(qidx)로 재설정 후 즉시 읽으므로 단일 요청 내에서는 안전하지만, 극단적 동시성(멀티스레드) 환경이면 레이스 가능 — 현재 accept 루프는 단일스레드 순차처리라 실사용 무해. 참고만.
  • 디자인이식 훅이 기존 파일(딜러.html/랜딩.html 등)에 이미 있던 치수까지 묶어 "타" 판정을
반복 출력 — 신규 파일(티옴타.html/퀴즈.html)의 카드 크기(46px)/문항 폰트(17px) 등은 원본 시안 부재 상태에서 기존 pip-card(32px)류를 준용해 추정한 값. 정식 디자인 시안 확보 시 재조정 필요.