Skip to content

플레이 링크를 코드로도 공유 - #1101

Merged
sevineleven merged 4 commits into
devfrom
feat/1013-play-by-code
Oct 19, 2026
Merged

sevineleven merged 4 commits into
devfrom
feat/1013-play-by-code

Conversation

@sevineleven

@sevineleven sevineleven commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Situation

착수 후 드러난 것

Task

코드 입장 경로 신설

Action

코드는 주소, 게이트는 상태

  • POST /tournaments/from-play-code 추가. 경로에 id 없음
    • 원인: 코드로 들어오는 쪽은 토너먼트 id 를 모름
  • 6자리 코드는 생성 시점 발급분 재사용. 새 컬럼·새 발급 없음
    • 조건: uk_tournaments_active_invite_code 가 활성 토너먼트 전체에서 코드 유일성 보장
대상 상태 코드로 열리는 문 게이트
대기실 참여자 합류 (기존 join) 초대 유효 · 30분
주최자 완주 플레이 생성 (신규) 공유 링크 유효 · 14일

완료 게이트를 공유 링크 수명에 묶음

  • playLinkExpiresAt 을 코드 게이트로 그대로 사용
  • 대안: 코드 전용 만료 컬럼 신설
    • 기각: 두 수명을 손으로 맞춰야 하고, 어긋나면 "링크는 되는데 코드는 안 되는" 상태 발생

정원 8명을 링크 경로에도 적용

  • 이전: 초대 합류만 8명 제한. 플레이 링크는 제한 없음
  • 코드·링크가 같은 제한 공유
    • 원인: 코드만 막으면 링크를 대신 요청해 우회 가능. 제한이 이름뿐이 됨
    • 결과: prod 실측 공유 토너먼트 37건의 입장자 최대 4명. 기존 사용 영향 없음
입장자 수 토너먼트 수
1명 27건
2명 5건
3명 3건
4명 2건

미리보기를 입장과 같은 게이트로

  • 이전: checkJoinable(null) 단일 경로. 완주한 토너먼트가 409 로 막힘
  • 상태별 분기 도입
    • 원인: 코드로 들어오기 전 무엇을 보게 될지 확인 불가
    • 결과: "보이는데 못 들어가는" · "입장은 되는데 미리보기는 막히는" 어긋남 소멸

구현

  • 구현: TournamentService.createFromPlayCode · joinAsPlayer · isOwnerCompleted · CreateFromPlayCodeRequest
  • 완료 판정은 주최자 참여 행 기준
    • 원인: createPlayLink 가 쓰는 기준과 같아야 "링크는 만들어졌는데 코드로는 못 들어가는" 어긋남 없음
    • 결과: 전역 status 로 처음 작성했다가 통합 테스트 5건 실패로 발견
  • 코드 형식 검증은 입력 경계(@Pattern)에 배치. 기존 초대 코드 상수 재사용

Result

응답 계약

케이스 status code
주최자 완주 + 공유 켬 200 없음
이미 참여 중 200 없음
대기실 상태 409 TOURNAMENT-023
공유 미생성 404 TOURNAMENT-026
공유 만료 409 TOURNAMENT-027
정원 초과 409 TOURNAMENT-030
없는 코드 400 TOURNAMENT-020
코드 형식 오류 400 COMMON-INVALID-INPUT

검증

  • 통합 테스트 8건. 공유 미생성 차단·대기실 회귀 가드·멱등·정원 초과 포함
  • 위험: 링크 경로에 정원 제한 신설. 실측상 최대 4명이라 현 사용자 영향 없으나 동작 변경
  • 후속: 플레이 링크를 코드로도 공유 #1013 의 나머지 결정(미리보기 상세)은 서버 재량으로 확정. 별도 작업 없음

연관 이슈

Summary by CodeRabbit

  • 새 기능

    • 6자리 초대 코드로 완료된 토너먼트에 참여할 수 있습니다.
    • 이미 참여한 경우 기존 토너먼트 정보를 반환합니다.
    • 토너먼트 참여 인원은 주최자를 포함해 최대 8명으로 제한됩니다.
  • 오류 처리

    • 미완료 토너먼트, 공유 미설정, 잘못된 코드, 링크 만료 및 정원 초과 상황을 구분해 안내합니다.
  • 문서

    • 코드 참여 API와 주요 성공·오류 사례가 OpenAPI 문서에 추가되었습니다.

완료된 토너먼트를 남에게 넘기는 방법이 링크 하나뿐이었다. 6자리 코드는
생성 시점에 발급돼 바뀌지 않는데 대기실 합류에만 쓰여, 완료 후에는 죽은
값이 됐다. 오프라인에서 불러주거나 손으로 입력하는 자리를 지원하지 못한다.

POST /tournaments/from-play-code 를 추가한다. 경로에 id 를 두지 않는다 -
코드로 들어오는 사람은 토너먼트 id 를 모르고, 그게 이 경로의 요점이다.

코드는 주소일 뿐이고 무엇이 열려 있는지는 상태가 정한다. 완료 상태의
게이트를 playLinkExpiresAt 으로 둬 링크와 같은 수명을 공유하게 했다.
그래서 공유를 켜지 않은 토너먼트는 코드만으로 뚫리지 않고, 주최자 탈퇴로
무효화된 경우도 함께 막히며, 만료 후 재발급(#980)하면 코드도 살아난다.

정원 8명을 링크 경로에도 걸었다. 코드만 막으면 "링크를 달라고 하면
들어가지는" 상태가 되어 제한이 이름뿐이 된다. prod 실측상 공유된 토너먼트
37개의 입장자가 최대 4명이라 기존 사용은 깨지지 않는다.

미리보기도 입장과 같은 게이트를 쓰게 했다. 예전엔 checkJoinable(null)
하나라 완주한 토너먼트가 409 로 막혀, 코드로 들어오기 전에 무엇을 보게
될지 알 수 없었다.

작업 중 "완료" 판정이 옮겨져 있던 것을 발견했다 - Phase 3(#1044) 이후
진행 상태가 참여 행으로 가서 tournaments.status 는 주최자의 완주를 뜻하지
않는다. createPlayLink 와 같은 기준(주최자 참여 행)을 쓰지 않으면 "링크는
만들어졌는데 코드로는 못 들어가는" 어긋남이 생긴다.

#1027 Phase 1-3 덕분에 클론 재공유와 source 평탄화는 이 이슈에서 빠졌다.
클론 개념이 없어져 누가 어느 주소로 들어오든 참여 행이 하나 생긴다.
@sevineleven sevineleven added the feat 외부 가시적 새 기능 label Sep 15, 2026
@sevineleven sevineleven linked an issue Sep 15, 2026 that may be closed by this pull request
@sevineleven sevineleven self-assigned this Sep 15, 2026
@github-actions

Copy link
Copy Markdown

Discord 스레드 연동용 메타데이터입니다. discord-pr-bot 워크플로가 자동 생성하며, 수정·삭제하면 PR 과 Discord 알림 연동이 끊깁니다.

@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 17 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: TeamPiKi/core/.coderabbit.yml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 75343bd5-958e-43c4-95d4-c2deb093f14a
📥 Commits

Reviewing files that changed from the base of the PR and between 22f6613 and ce1e84f.

📒 Files selected for processing: 5
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApi.kt
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApiExamples.kt
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentController.kt
  • src/main/kotlin/com/depromeet/piki/tournament/service/TournamentService.kt
  • src/test/kotlin/com/depromeet/piki/tournament/controller/TournamentIntegrationTest.kt

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Advanced

Run ID: 8bd0cdd0-46a4-424b-a9da-1bd4856d11ae

📥 Commits

Reviewing files that changed from the base of the PR and between bd76c27 and 22f6613.

📒 Files selected for processing (6)
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApi.kt
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApiExamples.kt
  • src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentController.kt
  • src/main/kotlin/com/depromeet/piki/tournament/controller/dto/CreateFromPlayCodeRequest.kt
  • src/main/kotlin/com/depromeet/piki/tournament/service/TournamentService.kt
  • src/test/kotlin/com/depromeet/piki/tournament/controller/TournamentIntegrationTest.kt

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

완료된 토너먼트에 6자리 코드로 입장하는 API를 추가했습니다. 상태와 공유 링크를 검사하고, 기존 참여 반환과 참여 정원 제한을 적용했습니다. 미리보기와 링크 입장 경로도 관련 게이트를 사용합니다.

Changes

완료 토너먼트 코드 입장

Layer / File(s) Summary
코드 입장 API 계약
src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApi.kt, src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentController.kt, src/main/kotlin/com/depromeet/piki/tournament/controller/dto/CreateFromPlayCodeRequest.kt, src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApiExamples.kt
POST /from-play-code와 CreateFromPlayCodeRequest를 추가했습니다. 코드는 [A-Z]{3}\d{3} 형식으로 검증합니다. 성공 시 200과 토너먼트 id를 반환합니다.
상태 게이트와 참여 생성
src/main/kotlin/com/depromeet/piki/tournament/service/TournamentService.kt
완료 여부, 공유 링크 생성 여부, 링크 만료 여부를 검사합니다. 기존 참여자는 같은 ROOT id를 반환합니다. 링크와 코드 경로에 참여 정원 제한을 적용합니다.
통합 시나리오 검증
src/test/kotlin/com/depromeet/piki/tournament/controller/TournamentIntegrationTest.kt
완료·PENDING·공유 미설정·잘못된 코드·중복 입장 시나리오를 검증합니다. 미리보기와 링크 경로의 참여 정원 초과도 검증합니다.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TournamentController
  participant TournamentService
  participant Tournament
  participant TournamentPlayedFromLink
  TournamentController->>TournamentService: createFromPlayCode(userId, code)
  TournamentService->>Tournament: 코드로 대상 토너먼트와 ROOT 확인
  TournamentService->>TournamentService: 상태와 공유 링크 유효성 검사
  TournamentService->>Tournament: 참여 행 저장
  TournamentService->>TournamentPlayedFromLink: 참여 이벤트 발행
  TournamentService-->>TournamentController: ROOT id 반환
Loading

연결 이슈 평가

Objective Addressed Explanation
완료된 토너먼트를 코드로 입장하고, PENDING 코드는 기존 합류 동작을 유지함 [#1013] ✅
공유하지 않았거나 만료된 완료 토너먼트의 코드 입장을 차단함 [#1013] ✅
클론이 재공유하고 새 클론의 sourceTournamentId를 ROOT로 평탄화함 [#1013] ❓ 코드 경로가 ROOT id를 사용하지만, 클론의 재공유와 sourceTournamentId 평탄화를 직접 검증한 구현 또는 테스트는 요약에 없습니다.
Merge Risk: ⚪ Minimal · up to 22f66

Existing participants can re-enter using their code as intended, including while the tournament is pending. No actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/1013-play-by-code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sevineleven sevineleven changed the title 완료된 토너먼트 코드 입장 허용 플레이 링크를 코드로도 공유 Sep 15, 2026
@sevineleven

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 54 minutes.

# Conflicts:
#	src/main/kotlin/com/depromeet/piki/tournament/controller/TournamentApiExamples.kt
@sevineleven
sevineleven merged commit 461daba into dev Oct 19, 2026
5 checks passed
@sevineleven
sevineleven deleted the feat/1013-play-by-code branch October 19, 2026 13:36
@TeamPiKi TeamPiKi deleted a comment from coderabbitai Bot Oct 20, 2026
@TeamPiKi TeamPiKi deleted a comment from coderabbitai Bot Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 외부 가시적 새 기능

Projects

None yet

Development

Successfully merging this pull request may close these issues.

플레이 링크를 코드로도 공유

1 participant