[global] todo 백로그 16건 처리 (방·세션·안정성)#44
Conversation
- JoinRoom이 JoinRoomResult/JoinRoomResponse로 SteamLobbyId 반환 (fix 01) - 단건/목록 조회 응답에 MaxPlayers 추가 (feat 04) - GetAllRoomService가 응답 DTO 대신 GetRoomResult를 반환하고 컨트롤러에서 매핑하도록 경계 정리 (refactor 03)
- IsPrivate는 방 목록 노출 여부만 의미, 비밀번호는 공개/비공개 무관 설정 가능 - join 검증을 IsPrivate에서 PasswordHash != null 기준으로 변경해 비밀번호 없는 비공개 방 참가 시 null 해시 BCrypt 500 오류 제거 - 방 목록 조회에서 비공개 방 제외 (idx_room_status_private 활용) - 단건/목록 조회 응답에 HasPassword 노출
- 전역 단일 카운터(AddFixedWindowLimiter)를 AddPolicy + RateLimitPartition.GetFixedWindowLimiter로 교체 - login은 클라이언트 IP, create_room/join_room은 Session-Id 헤더 (없으면 IP fallback) 기준으로 파티셔닝 - 파티션 키 헬퍼 단위 테스트 추가 (InternalsVisibleTo)
- room에 guest_steam_id 추가, TryJoinAsync로 게스트 점유와 인원 증가를 원자적으로 처리 (중복 참가·호스트 본인 참가 차단) - JoinRoomCommand에 SteamId 추가, AlreadyJoinedRoomException 신설 - RoomName ≤50자, Nickname ≤32자 검증 (서비스 레벨 도메인 예외) - room_name/nickname 컬럼 길이 제한 + last_heartbeat_at 선반영 마이그레이션 (AddRoomGuestHeartbeatAndLengthLimits)
- POST api/v1/room/{roomCode}/leave — 게스트 퇴장(조건부 감소로 0 미만
방지), 호스트가 나가면 방 자동 Close (호스트 이관 없음 정책 확정)
- DELETE api/v1/room/{roomCode} — 호스트만 방 Close 가능
- CloseAsync에 Active 조건 추가로 멱등 처리
- LeaveRoomService/CloseRoomService 및 단위 테스트 추가
- POST api/v1/room/{roomCode}/heartbeat — 호스트만 LastHeartbeatAt 갱신
- StaleRoomCleanupService(BackgroundService)가 주기적으로 하트비트가
끊긴 Active 방을 set-based 쿼리로 일괄 Close (하트비트 없으면
CreatedAt 기준)
- 주기/타임아웃은 RoomCleanup 설정 섹션으로 주입, TimeProvider 사용
- RoomRepository.CreateAsync가 PostgreSQL 23505(UniqueViolation)를 DuplicateRoomCodeException으로 변환 (Npgsql 의존을 Repository에 격리) - CreateRoomService가 최대 3회 새 코드로 재시도, 소진 시 RoomCodeGenerationFailedException(500)
- GET api/v1/room/all에 page/size 쿼리 파라미터 (size 상한 50) - size+1 조회 방식으로 count 쿼리 없이 hasNext 판별 - 응답에 page, size, hasNext 포함
- ICacheStore/CacheStore 전 메서드에 ct 추가, IDistributedCache로 전달 - ISessionService.CreateAsync/GetAsync에 ct 추가, DeleteAsync도 실제 전달 - IAuthTicketValidator.ValidateAsync에 ct 추가, Steam HTTP 호출에 전달 - LoginService·SessionAuthorizeAttribute 호출부에서 ct 전달
- CacheKey.Session.BySteamId 역인덱스 키 추가 - 재로그인 시 기존 세션을 삭제 후 새 세션 발급 (탈취된 구 세션 무효화) - 로그아웃 시 역인덱스가 현재 세션을 가리킬 때만 함께 정리 - SessionServiceTests 신규 추가
- Room.MarkDeleting / RoomStatus.Deleting 삭제 (즉시 Close 정책 채택으로 불필요, DB에 Deleting 값 없음) - User.UpdateNickname / UpdateLastLogin 삭제 (set-based UpdateAsync 유지) - 관련 RoomTests/UserTests 정리, 닉네임 검증은 생성자 테스트로 대체 - docs/todo/README.md에 전 항목 처리 결과와 정책 변경 비고 기록
전 항목이 feat/todo-backlog 브랜치에서 구현 완료되어 백로그 문서를 제거한다. 정책 변경 내역(IsPrivate=목록 노출 여부, 호스트 leave=자동 Close 등)은 각 구현 커밋 메시지에 기록되어 있다.
완료된 백로그 문서는 삭제하되 docs/todo 골격과 우선순위 범례, 처리 이력은 README로 유지한다.
There was a problem hiding this comment.
Code Review
This pull request introduces several key features and improvements to the matchmaking backend, including room leaving, closing, and heartbeat functionalities, along with a background cleanup service (StaleRoomCleanupService) for stale rooms. It also implements single-session enforcement per user, room code collision retries, pagination for room listings, and proper CancellationToken propagation across I/O paths. Feedback on these changes highlights a security vulnerability in the rate limiter where unvalidated Session-Id headers can bypass limits, and suggests a performance optimization to initialize LastHeartbeatAt to CreatedAt to avoid index-blocking COALESCE operations during stale room cleanup queries.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
클라이언트가 Session-Id 헤더 값을 바꿔가며 요청하면 파티션이 무한히 생성되어 레이트리밋이 우회되는 문제를 수정한다. 리뷰 지적(PR #44) 반영.
개요
2026-06-11 코드 분석으로 정리한 todo 백로그 16건(fix 7 / feat 5 / refactor 4)을 전체 처리하였습니다. 방 생명주기 관리 기능을 확장하고, 매치메이킹 흐름의 결함을 수정하였으며, 세션 정책과 코드 정리를 함께 진행하였습니다.
변경사항
신규 기능 (feat)
POST /leave) 및 방 닫기(POST /close) API를 추가하였습니다. 방 닫기는 호스트만 가능하도록 검증합니다.POST /heartbeat) API와 유령 방 정리 백그라운드 잡을 추가하였습니다. 하트비트가 끊긴 방은 주기적으로 정리되며, 주기와 타임아웃은RoomCleanup설정으로 제어합니다.MaxPlayers,SteamLobbyId를 포함하도록 응답 DTO를 보강하였습니다.버그 수정 (fix)
SteamLobbyId가 반환되지 않아 P2P 연결이 불가능하던 문제를 수정하였습니다.IsPrivate플래그가 아닌PasswordHash유무 기준으로 전환하였습니다.CancellationToken을 전파하였습니다.리팩터링 (refactor)
GetAllRoomService의 응답 DTO 경계를 정비하였습니다.기타
AddRoomGuestHeartbeatAndLengthLimits마이그레이션을 추가하였습니다 (게스트/하트비트 컬럼, 문자열 길이 제한).참고