Skip to content

fix: 학번 유니크 제약조건 제거 - #356

Merged
dh2906 merged 3 commits into
developfrom
fix/remove-unique-student-number
Mar 8, 2026
Merged

fix: 학번 유니크 제약조건 제거#356
dh2906 merged 3 commits into
developfrom
fix/remove-unique-student-number

Conversation

@dh2906

@dh2906 dh2906 commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

🔍 개요

  • 유저의 휴먼 에러로 학번을 오기입하는 문제가 발생함

  • 그로 인해 누군가는 이미 사용중인 학번이라 가입을 못한다는 문의가 제기됨

  • 정책을 완화하여 학번을 중복가능하도록 하고자 함

  • close #이슈번호

🚀 주요 변경 내용

  • users 테이블에 (university_id, student_number, active_flag) 유니크 제약조건을 제거했습니다.

  • 그에 따라 학번 중복 검증 로직도 같이 제거했습니다.

  • 이름, 학번으로 동아리 멤버를 등록하는 기능에 동일 학번+이름을 지니는 유저가 2명 이상일 시 등록을 차단합니다.

    • 에러 메시지에 관리자에게 문의하라는 문장을 기입하여 관리자가 직접 등록해줄 수 있도록 유도합니다.

💬 참고 사항


✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

@dh2906 dh2906 self-assigned this Mar 7, 2026
@dh2906 dh2906 added the DB DB 마이그레이션을 위한 라벨입니다. label Mar 7, 2026
@coderabbitai

coderabbitai Bot commented Mar 7, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

유니크 학번 제약을 DB 마이그레이션으로 제거하고, 리포지토리 반환타입·서비스 검증·동호회 멤버 추가 흐름을 다중 사용자 처리로 변경했습니다. API 문서 및 응답 코드에서 중복 학번 관련 항목을 삭제/대체했습니다.

Changes

Cohort / File(s) Summary
User 모델 및 마이그레이션
src/main/java/gg/agit/konect/domain/user/model/User.java, src/main/resources/db/migration/V49__remove_unique_constraint_on_user_student_number.sql
users 테이블의 uq_users_university_id_student_number_active 유니크 인덱스 제거 마이그레이션 추가 및 관련 모델 주석/제약 제거
리포지토리 변경
src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
existsByUniversityIdAndStudentNumber(...) 제거, findByUniversityIdAndStudentNumber(...)findAllByUniversityIdAndStudentNumber(...)로 반환 타입·시그니처 변경(다중 사용자 반환)
서비스 검증 및 동호회 흐름 수정
src/main/java/gg/agit/konect/domain/user/service/UserService.java, src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java
회원가입 시 학생번호 중복 런타임 검증 제거; 동호회 멤버 추가에서 다중 후보 조회 후 이름으로 필터링하여 단일 매칭 시 직접 추가, 다중 매칭 시 AMBIGUOUS_USER_MATCH 오류 처리, 미매칭 시 프리멤버 추가로 분기
API 문서 및 응답 코드 변경
src/main/java/gg/agit/konect/domain/user/controller/UserApi.java, src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
회원가입 API 설명에서 409(중복 학번) 제거, DUPLICATE_STUDENT_NUMBER 제거 및 AMBIGUOUS_USER_MATCH 응답 코드 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant UserService
    participant ClubService
    participant UserRepository
    participant Database

    Client->>UserService: 회원가입 요청 (univId, studentNumber, ...) 
    UserService->>UserRepository: findAllByUniversityIdAndStudentNumber(univId, studentNumber)
    UserRepository->>Database: SELECT ... WHERE university_id=? AND student_number=? AND deleted_flag=0
    Database-->>UserRepository: 사용자 리스트 반환
    UserRepository-->>UserService: 사용자 리스트
    UserService->>Database: INSERT 사용자 (중복 검사 없음)
    Database-->>UserService: 생성 결과
    UserService-->>Client: 가입 성공 응답

    Client->>ClubService: 동호회 멤버 추가 요청 (univId, studentNumber, name)
    ClubService->>UserRepository: findAllByUniversityIdAndStudentNumber(univId, studentNumber)
    UserRepository->>Database: SELECT ...
    Database-->>UserRepository: 후보 리스트 반환
    UserRepository-->>ClubService: 후보 리스트
    ClubService->>ClubService: 후보 리스트 필터링 by name
    alt 이름으로 단일 매칭
        ClubService->>Database: 멤버 직접 추가 (matched user)
        Database-->>ClubService: 추가 성공
    else 다중 매칭
        ClubService-->>Client: AMBIGUOUS_USER_MATCH 에러 반환
    else 매칭 없음
        ClubService->>ClubService: addPreMemberInternal 처리 (프리멤버)
    end
    ClubService-->>Client: 멤버 추가 결과
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 굴 속에서 튀어나와 외치네
학번의 굴레는 풀렸구나
후보들이 모여 이름으로 골라지네
중복 검사 대신 눈으로 확인하네
당근 축하파티, 폴더는 가벼워라 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 유니크 제약조건 제거라는 변경의 핵심을 명확하게 반영하고 있으며, 실제 변경 내용과 일치합니다.
Description check ✅ Passed 풀 리퀘스트 설명이 변경사항과 관련성이 있으며, 학번 유니크 제약조건 제거 및 정책 변경에 대해 명확하게 설명하고 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/remove-unique-student-number

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/resources/db/migration/V49__remove_unique_constraint_on_user_student_number.sql`:
- Around line 1-2: This migration drops the unique index
uq_users_university_id_student_number_active on users which makes the change
effectively irreversible if duplicates appear; before dropping it, add a
duplicate-detection step (query for rows grouped by university_id,
student_number, active_flag having count>1) and abort the migration (or clean
up/merge duplicates) if any are found, or alternatively document explicitly in
the migration/operational runbook that V49 is destructive and include the
required manual duplicate-cleanup procedure and rollback impossibility;
reference the ALTER TABLE users DROP INDEX
uq_users_university_id_student_number_active operation and ensure the migration
fails loudly rather than proceeding when duplicates exist.
- Around line 1-2: The migration removes the unique constraint so lookups by
(universityId, studentNumber) may return multiple users; update
UserRepository.findByUniversityIdAndStudentNumber(...) to return a collection
(e.g., List<User>) or a result type that can represent multiple matches, then
update ClubMemberManagementService.addDirectMember(...) (and its caller flow) to
handle multiple results by either requiring an additional disambiguating
identifier, validating uniqueness and failing fast with a clear error if
multiple active users exist, or selecting the correct user deterministically
only after extra checks; also add unit/integration tests for the multi-match
case and deploy the code change before running the migration.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bf0da731-d96e-442f-82a0-30dc1ec7103a

📥 Commits

Reviewing files that changed from the base of the PR and between 8ca1a68 and ff605c9.

📒 Files selected for processing (4)
  • src/main/java/gg/agit/konect/domain/user/model/User.java
  • src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
  • src/main/java/gg/agit/konect/domain/user/service/UserService.java
  • src/main/resources/db/migration/V49__remove_unique_constraint_on_user_student_number.sql
💤 Files with no reviewable changes (3)
  • src/main/java/gg/agit/konect/domain/user/model/User.java
  • src/main/java/gg/agit/konect/domain/user/service/UserService.java
  • src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/main/resources/db/migration/**/*.sql

⚙️ CodeRabbit configuration file

src/main/resources/db/migration/**/*.sql: Flyway 마이그레이션 리뷰 규칙:

  • 버전 파일명 규칙(V{number}__{description}.sql) 위반 여부를 우선 확인한다.
  • 이미 배포된 마이그레이션 수정/재번호 부여 위험이 있으면 반드시 차단 코멘트를 남긴다.
  • 파괴적 변경(drop, rename 등)은 롤백 가능성과 운영 영향 관점에서 검토한다.

Files:

  • src/main/resources/db/migration/V49__remove_unique_constraint_on_user_student_number.sql
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/resources/db/migration/V49__remove_unique_constraint_on_user_student_number.sql

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java`:
- Around line 94-103: The current logic uses
userRepository.findAllByUniversityIdAndStudentNumber(...) and then
candidates.stream().filter(...).findFirst() to pick a matchedUser and pass it to
addDirectMember(...), which can incorrectly choose one of multiple
identical-name candidates; change this so you count/filter name-equals results:
if exactly one match exists call addDirectMember(club, user, clubPosition), but
if zero or more than one matches fall back to addPreMemberInternal(...) (or
throw a clear ambiguity error) to avoid non-deterministic selection; update the
code paths that reference matchedUser, addDirectMember, and addPreMemberInternal
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3ac0e237-8209-4191-a90d-a625501ad50f

📥 Commits

Reviewing files that changed from the base of the PR and between ff605c9 and ed3e1ca.

📒 Files selected for processing (4)
  • src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java
  • src/main/java/gg/agit/konect/domain/user/controller/UserApi.java
  • src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
  • src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
💤 Files with no reviewable changes (2)
  • src/main/java/gg/agit/konect/global/code/ApiResponseCode.java
  • src/main/java/gg/agit/konect/domain/user/controller/UserApi.java
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/domain/user/repository/UserRepository.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java

Comment thread src/main/java/gg/agit/konect/domain/club/service/ClubMemberManagementService.java Outdated
@dh2906
dh2906 merged commit 6308ce6 into develop Mar 8, 2026
2 checks passed
@dh2906
dh2906 deleted the fix/remove-unique-student-number branch March 8, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DB DB 마이그레이션을 위한 라벨입니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant