2️⃣ 투표 시스템

종류 제약 URL
팀 투표 1인 1팀 POST /api/v1/votes/teams
파트장 후보 투표 FE/BE 파트별 각 1표 POST /api/v1/votes/candidates

📌 엔티티 설계

TeamVote (팀 투표) + CandidateVote (파트장 투표) 두 엔티티로 분리

단일 Vote + VoteType TeamVote + CandidateVote
team_id / candidate_id ⇒ nullable NOT NULL FK
XOR 검증 필요 스키마 자체가 무결성 강제

동시성

[1차 방어] 사전 체크 (existsByUserId / existsByUserIdAndPart)
    └─ 일반 케이스 대부분 처리, 명확한 ALREADY_VOTED 응답
    
[2차 방어] DB UNIQUE 제약
    ├─ UNIQUE(user_id)         — 팀 투표 1인 1표
    └─ UNIQUE(user_id, part)   — 파트별 1표
    └─ race condition 시 DataIntegrityViolationException 발생
        -> Service의 try/catch에서 ALREADY_VOTED로 변환
        -> 어떤 경로든 일관된 응답 보장
	// 투표 저장
	try {
			teamVoteRepository.save(TeamVote.of(user, team));
	} catch (DataIntegrityViolationException e) {
			throw new GeneralException(VoteErrorCode.ALREADY_VOTED);
	}