Skip to content

토너먼트 초대코드 조회 풀스캔 제거 (active_invite_code 인덱스 활용)#698

Open
sevineleven wants to merge 2 commits into
devfrom
perf/684-invite-code-active-fullscan
Open

토너먼트 초대코드 조회 풀스캔 제거 (active_invite_code 인덱스 활용)#698
sevineleven wants to merge 2 commits into
devfrom
perf/684-invite-code-active-fullscan

Conversation

@sevineleven

@sevineleven sevineleven commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Situation

  • 초대 코드로 토너먼트를 찾는 조회(초대 참여, 프리뷰)는 사용자가 자주 타는 경로인데, 매 호출마다 tournaments 테이블 풀스캔이 발생했다.
  • 초대 코드 중복을 막는 유니크 인덱스는 원본 컬럼 invite_code 가 아니라 파생 컬럼 active_invite_code(삭제 안 된 행에만 코드가 살아있는 generated 컬럼)에만 걸려 있다. 그런데 조회는 원본 invite_code 로 필터해서, MySQL 8 이 그 유니크 인덱스를 쓰지 못하고 전수 스캔으로 떨어졌다.

Task

  • 초대 코드 조회가 유니크 인덱스를 타도록 바꿔 풀스캔을 제거한다.
  • 단, 겉보기 동작(활성 토너먼트만 조회, 삭제된 건 제외)은 그대로 유지하고 스키마 변경 없이 코드만으로 해결한다.

Action

  • 조회 기준 전환: 초대 코드 조회를 원본 컬럼이 아니라 파생 컬럼 active_invite_code 기준으로 바꿨다. 삭제된 행은 이 컬럼이 비어(NULL) 있어, "삭제 안 된 것만" 이라는 조건이 컬럼 자체에 이미 녹아 있다. 그래서 별도의 삭제 여부 조건을 걸지 않아도 활성 행만 잡힌다.
  • 구현: 파생 컬럼을 도메인 엔티티에 읽기 전용으로만 매핑(insertable=false, updatable=false)하고, 조회는 기존과 같은 파생 쿼리(findFirstByActiveInviteCode, existsByActiveInviteCode)로 유지했다. 배선은 repository 계층 두 파일만 바뀐다.
  • 안전망: 삭제된 토너먼트의 코드로 조회하면 조회되지 않아야 한다는 계약을 통합 테스트로 잠갔다(삭제 후 그 코드로 조회 시 400).

구현 방식 결정 — native 쿼리 대신 파생 쿼리

파생 컬럼을 조회하는 두 갈래를 저울질했다.

방식 타입 안전 레포 컨벤션 비고
native SQL(@Query(nativeQuery=true)) 없음 (컬럼명 문자열, 런타임에야 오류) 이질적 (이 레포는 @Query 를 잠금/수정에만 씀) 엔티티는 안 건드림
파생 쿼리 + 읽기 전용 컬럼 매핑 (채택) 있음 (부팅 시 프로퍼티 경로 검증) 부합 (파생 쿼리가 지배적) 엔티티에 읽기 전용 필드 1개 추가

파생 쿼리는 부팅 시점에 프로퍼티 경로가 검증되어 오타나 컬럼 변경이 곧바로 드러난다. 이 레포가 파생 쿼리를 기본으로 쓰는 점과도 맞아, 엔티티에 읽기 전용 매핑 하나를 더하는 비용을 감수하고 이쪽을 택했다.

Result

  • 초대 코드 조회가 풀스캔에서 유니크 인덱스 단일 행 조회로 바뀐다. MySQL 8 컨테이너에 같은 스키마를 재현해 EXPLAIN 으로 실측했다(2000행, 활성 1960행):
조회 접근 방식 사용 인덱스 스캔 행 수
변경 전 (invite_code = ? AND deleted_at IS NULL) 풀스캔(ALL) 없음 1999
변경 후 (active_invite_code = ?) 상수 조회(const) uk_tournaments_active_invite_code 1
  • 마이그레이션 없음(기존 유니크 인덱스를 그대로 활용), 엔티티의 겉보기 동작 불변.

연관 이슈

Summary by CodeRabbit

  • 기능 개선

    • 초대 코드 조회가 활성 상태 기준으로 동작하도록 개선되었습니다.
    • 삭제된 항목은 조회 결과에서 제외되어, 더 정확한 초대 코드 검사가 가능해졌습니다.
  • 버그 수정

    • 소프트 삭제된 항목의 초대 코드로 조회 시 400 Bad Request가 반환되도록 수정되었습니다.
    • 중복 조회 상황에서 더 안정적으로 결과를 반환하도록 개선되었습니다.

초대 참여·프리뷰(hot path)의 초대코드 조회가 base 컬럼 invite_code 로
필터해 tournaments 풀스캔이 됐다. 유니크 인덱스는 generated STORED 컬럼
active_invite_code(= IF(deleted_at IS NULL, invite_code, NULL))에만 걸려
있어, MySQL 8 이 base 컬럼 조건에 이 인덱스를 못 쓰기 때문.

조회를 active_invite_code = ? 기준으로 전환한다. 삭제행은 이 컬럼이 NULL
이라 deleted_at IS NULL 조건도 자연 흡수된다. 컬럼을 엔티티에 read-only
로만 매핑하고 derived query 를 유지해 마이그레이션 0, 타입 안전을 지킨다.

EXPLAIN 실측: type ALL(rows 1999) -> const(uk_tournaments_active_invite_code).
@sevineleven sevineleven added the perf 성능 개선 (측정 가능, 외부 동작 불변) label Jul 7, 2026
@sevineleven sevineleven self-assigned this Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

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

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@sevineleven, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 5c01c78b-355a-41b5-ba04-c80e8ff7a76d

📥 Commits

Reviewing files that changed from the base of the PR and between a2d09d0 and 6daf1da.

📒 Files selected for processing (4)
  • src/main/kotlin/com/depromeet/piki/tournament/domain/Tournament.kt
  • src/main/kotlin/com/depromeet/piki/tournament/repository/TournamentJpaRepository.kt
  • src/main/kotlin/com/depromeet/piki/tournament/repository/TournamentRepositoryImpl.kt
  • src/test/kotlin/com/depromeet/piki/tournament/controller/TournamentIntegrationTest.kt
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/684-invite-code-active-fullscan

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

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 43 minutes.

@sevineleven

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Action performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 57 minutes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf 성능 개선 (측정 가능, 외부 동작 불변)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P1] 토너먼트 초대코드 조회 풀스캔 제거 (invite_code -> active_invite_code)

1 participant