1. API 목록

투표는 PUT/DELETE 두 엔드포인트로 분리되어 있으며, 두 메서드 모두 멱등합니다.

  • PUT /teams/{teamId}/votes → 투표 등록 (이미 등록된 경우 NO-OP, 200 OK)

  • DELETE /teams/{teamId}/votes → 투표 취소 (이미 취소된 경우 NO-OP, 200 OK)

두 메서드 모두 응답 본문에 사용자의 남은 투표 가능 횟수와 대회 최대 투표 허용 개수를 포함합니다.
투표 등록 시 대회 최대 투표 수 초과 시 400 에러가 발생합니다.
투표 기간 중에만 호출 가능하며, 투표 기간이 아닐 때 호출하면 400 에러가 발생합니다.

2. PUT: 팀 투표 등록

해당 팀에 대해 투표를 등록합니다. 이미 투표한 상태에서 호출해도 동일하게 200 OK와 현재 카운트를 반환합니다 (멱등).

Table 1. /teams/{teamId}/votes
Parameter Description

teamId

투표할 팀의 ID

Table 2. HTTP Request Headers
Name Description

Authorization

Bearer {accessToken}

HTTP Request
PUT /teams/1/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
HTTP Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 54

{
  "remainingVotesCount" : 1,
  "maxVotesLimit" : 2
}
Table 3. Response Fields
Path Type Description

remainingVotesCount

Number

남은 투표 가능 횟수

maxVotesLimit

Number

대회 최대 투표 허용 개수

3. DELETE: 팀 투표 취소

해당 팀에 대한 투표를 취소합니다. 투표한 적 없는 팀에 호출해도 동일하게 200 OK와 현재 카운트를 반환합니다 (멱등).

Table 4. /teams/{teamId}/votes
Parameter Description

teamId

투표를 취소할 팀의 ID

Table 5. HTTP Request Headers
Name Description

Authorization

Bearer {accessToken}

HTTP Request
DELETE /teams/1/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
HTTP Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 54

{
  "remainingVotesCount" : 2,
  "maxVotesLimit" : 2
}
Table 6. Response Fields
Path Type Description

remainingVotesCount

Number

남은 투표 가능 횟수

maxVotesLimit

Number

대회 최대 투표 허용 개수

3.1. ⚠️ 실패 케이스

❌ Case 1: 존재하지 않는 팀
PUT /teams/999/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 53

{
  "message" : "팀이 존재하지 않습니다."
}
❌ Case 2: 최대 투표 수 초과
PUT /teams/3/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 76

{
  "message" : "대회당 최대 2개 팀만 투표할 수 있습니다."
}
❌ Case 3: 투표 기간이 아닐 때 투표 등록
PUT /teams/1/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 60

{
  "message" : "지금은 투표 기간이 아닙니다."
}
❌ Case 4: 투표 기간이 아닐 때 투표 취소
DELETE /teams/1/votes HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
HTTP/1.1 400 Bad Request
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 60

{
  "message" : "지금은 투표 기간이 아닙니다."
}

4. GET: 사용자 남은 투표 개수 조회

Table 7. /contests/{contestId}/votes/me
Parameter Description

contestId

대회 ID

Table 8. HTTP Request Headers
Name Description

Authorization

Bearer {accessToken}

HTTP Request
GET /contests/1/votes/me HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
HTTP Response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 54

{
  "remainingVotesCount" : 1,
  "maxVotesLimit" : 2
}
Table 9. Response Fields
Path Type Description

remainingVotesCount

Number

남은 투표 가능 횟수

maxVotesLimit

Number

대회 최대 투표 허용 개수

4.1. ⚠️ 실패 케이스

❌ Case 1: 존재하지 않는 대회 ID
GET /contests/999/votes/me HTTP/1.1
Authorization: Bearer member.access.token
Host: localhost:8080
HTTP/1.1 404 Not Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 56

{
  "message" : "존재하지 않는 대회입니다."
}