Skip to content

Feat/community - #178

Merged
isoo127 merged 6 commits into
developfrom
feat/community
Sep 6, 2026
Merged

isoo127 merged 6 commits into
developfrom
feat/community

Conversation

@isoo127

@isoo127 isoo127 commented Sep 6, 2026

Copy link
Copy Markdown
Member

✏️ 작업 개요

커뮤니티 퍼즐에 MMR 기반 추천 정렬과 24시간 업로드 제한을 추가했습니다.
랭킹전 페널티 계산 인자가 뒤바뀐 버그 수정, 에러 메시지·주석 영문화, 테스트 네이밍 통일을 함께 담았습니다.

🔨 작업 상세 내용

  1. 랭킹전 시작 페널티 계산 버그 수정

    • 게임 시작 시 페널티를 선차감하는 RankService.startRankGame에서 calculateMMRDecrease에 originalRating을, calculateRatingDecrease에 originalMmr을 넘기고 있었습니다.
    • 두 함수 모두 첫 인자로 기대 승률과 getPenaltyMultiplier 배수를 판정하므로, mmr과 rating이 벌어진 유저는 페널티가 뒤바뀐 값으로 적용됐습니다. (mmr 1600 / rating 1400, 퍼즐 1400 → 정상 1593/1398, 버그 1595/1396)
    • 기존 테스트는 TestUserFactory가 두 값을 같게 만들어 스왑이 드러나지 않았습니다. 값을 다르게 세팅한 회귀 테스트를 추가했습니다.
  2. 추천 정렬 추가

    • GET /api/community/puzzle의 sort에 RECOMMEND 추가
    • 정렬 키 abs(puzzle.rating - user.mmr) + mod(crc32(concat(id, '-', seed)), 600) 오름차순, 동점은 id 오름차순. MMR에 가까운 퍼즐이 앞에 오되 600점 미만 차이는 seed로 섞어, 난이도 적합성은 유지하면서 매번 같은 목록이 나오는 것을 막습니다.
    • shuffleSeed 파라미터 추가 (미전달 시 0). 같은 seed면 순서가 고정되어 커서 페이징 중 목록이 흔들리지 않습니다.
    • LATEST/LIKE와 달리 오름차순이라 커서 조건을 별도 분기 — score > cursorScore OR (score = cursorScore AND id > cursorId)
    • MMR이 필요해져 searchCommunityPuzzles(request, Long userId) → (request, UserEntity user, long seed)로 변경
    • Testcontainers MySQL 테스트 5개: seed 결정성, 다른 seed 재셔플, MMR 근접 우선, 커서 페이징 전수 방문, int 범위 초과 seed
  3. 업로드 24시간 제한

    • POST /api/community/puzzle에서 최근 24시간 업로드 수를 검사하고 초과 시 EXCEED_DAILY_PUZZLE_UPLOAD(429 / P429) 반환. 한도는 community.puzzle.daily-upload-limit, 기본 50
    • countByAuthorSinceIncludingDeleted는 삭제된 퍼즐까지 셉니다. 업로드 후 삭제로 한도를 우회하지 못하게 한 것이고, 소프트 삭제 필터를 우회해야 해서 네이티브 쿼리를 썼습니다.
    • 자정 리셋이 아닌 롤링 24시간 (clock.instant().minus(24, HOURS))
    • 테스트: 한도 도달 시 save 없이 예외, 카운트 윈도우 시작점 검증
  4. 에러 메시지·주석 영문화

    • ErrorCode 전체 메시지 (코드/HTTP 상태는 유지), request record 30여 개의 validation 메시지, Swagger 설명, 인라인 주석
    • GetCommunityPuzzlesForCacheRequest.java는 CRLF → LF 정규화가 겹쳐 전체 파일이 diff에 잡혔지만 실제 변경은 메시지 3줄입니다.
  5. 테스트 네이밍 통일

    • 한글 @DisplayName 제거, 메서드명을 대상_When조건_Then결과로 통일 (12개 파일, −143/+48)

💡 생각해볼 문제

  • crc32/mod를 numberTemplate으로 직접 넣어 MySQL에 종속됩니다. DB 교체 시 이 쿼리는 다시 써야 합니다.
  • RECOMMEND는 계산식 정렬이라 인덱스를 타지 못하고, 커서 조건도 서브쿼리로 커서 행의 점수를 매번 재계산합니다. 퍼즐 수가 늘면 실측이 필요합니다.
  • RECOMMEND 커서 페이징은 seed 고정이 전제입니다. 페이지마다 다른 seed가 오면 중복·누락이 생기는데 서버가 막지는 않으니 클라이언트와 협의가 필요합니다.
  • RECOMMEND_JITTER = 600은 경험값이라 실제 MMR 분포를 보고 조정이 필요할 수 있습니다.
  • 업로드 제한은 요청 시점 카운트라 동시 요청 시 한도를 약간 넘길 수 있습니다. 남용 방지가 목적이라 락은 걸지 않았습니다.

@isoo127
isoo127 merged commit c226487 into develop Sep 6, 2026
1 check passed
@isoo127
isoo127 deleted the feat/community branch September 6, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants