Skip to content

API 문서

박민지 edited this page Aug 17, 2025 · 2 revisions

Kickytime API 명세 (Spring Boot + JPA)

본 문서는 Kickytime 백엔드 REST API의 사용 방법과 스키마를 설명합니다. 인증은 JWT Bearer 토큰을 사용합니다. 표기된 예시는 개발 환경 기준이며, 운영 환경 URL은 프로젝트 설정에 맞게 교체해 주세요.

개요

  • 스펙: OpenAPI 3.0.1

  • 베이스 URL

    • 개발: http://localhost:8080
    • 운영: https://api.kickytime.nextcloudlab.com
  • 콘텐츠 타입: application/json; charset=UTF-8

  • 시간 포맷: ISO-8601 예) 2025-08-18T21:30:00+09:00 (Asia/Seoul)

인증 및 권한

  • 보안 스킴: HTTP Bearer / JWT
  • 헤더: Authorization: Bearer <access_token>
  • 역할(Role): USER, ADMIN
  • 토큰 획득: Cognito Hosted UI 로그인 후 access_token 수신 → 백엔드에 전달

공통 응답 규약

  • 성공 범례

    • 조회: 200 OK
    • 생성: 201 Created (권장, 현재 스펙은 200)
    • 삭제/참여취소 등 바디 없음: 204 No Content (권장, 현재 스펙은 200)
  • 에러 응답(권장 포맷)

{
  "timestamp": "2025-08-18T12:34:56.789+09:00",
  "status": 400,
  "error": "Bad Request",
  "code": "VALIDATION_FAILED",
  "message": "maxPlayers must be >= 2",
  "path": "/api/matches"
}
상황 상태코드 예시 코드
인증 실패 401 UNAUTHORIZED
권한 부족 403 FORBIDDEN
유효성 오류 400 VALIDATION_FAILED
리소스 없음 404 NOT_FOUND
중복/비즈니스 충돌 409 CONFLICT

엔드포인트 요약

구분 메서드 경로 설명 권한
사용자 POST /api/users/signin-up 최초 로그인 시 사용자 upsert USER
사용자 GET /api/users/me 내 프로필 조회 USER
경기 GET /api/matches 경기 목록 조회 USER
경기 POST /api/matches 경기 개설 USER
경기 GET /api/matches/me 내가 참여한 경기 목록 USER
경기 POST /api/matches/{matchId}/participants 경기 참여 USER
경기 DELETE /api/matches/{matchId}/participants 경기 참여 취소 USER
경기(관리) DELETE /api/matches/{matchId} 경기 삭제 ADMIN
사용자(관리) POST /api/admin/users/backfill-cognito?confirm=false Cognito 백필(백필: 데이터 뒷채움) ADMIN

상세 명세 및 예시

1) 사용자 로그인/업서트 — POST /api/users/signin-up

  • 설명: Cognito access_token으로 사용자 정보를 조회하고 DB에 upsert 수행

  • 헤더:

    • Authorization: Bearer <access_token>
    • Accept: application/json
  • 요청 바디: 없음

  • 응답: 200 OK + User 객체

응답 예시

{
  "id": 12,
  "email": "[email protected]",
  "nickname": "kickytime",
  "cognitoSub": "ap-northeast-2:xxxx-xxxx",
  "emailVerified": true,
  "role": "USER",
  "imageUrl": "https://.../avatar.png",
  "rank": "INTERMEDIATE",
  "createdAt": "2025-08-10T10:11:12+09:00",
  "updatedAt": "2025-08-18T12:00:00+09:00"
}

비고: password 필드는 Cognito만 사용 시 null 가능.


2) 내 프로필 조회 — GET /api/users/me

  • 설명: 액세스 토큰 기준 내 프로필 반환
  • 응답: 200 OK + UserDto

응답 예시

{
  "id": 12,
  "email": "[email protected]",
  "email_verified": true,
  "nickname": "kickytime",
  "imageUrl": "https://.../avatar.png",
  "role": "USER",
  "rank": "INTERMEDIATE",
  "createdAt": "2025-08-10T10:11:12+09:00"
}

3) 경기 목록 조회 — GET /api/matches

  • 설명: 전체 경기 목록 조회
  • 쿼리 파라미터: (확장 제안) status, from, to, page, size, sort
  • 응답: 200 OK + MatchResponseDto[]

응답 예시

[
  {
    "id": 1,
    "matchStatus": "OPEN",
    "matchDateTime": "2025-08-20T19:00:00+09:00",
    "location": "서울특별시 OO구 풋살장 A",
    "maxPlayers": 10,
    "currentParticipants": 3
  }
]

4) 경기 개설 — POST /api/matches

  • 설명: 신규 경기 생성
  • 바디 스키마: MatchCreateRequestDto

요청 예시

{
  "matchDateTime": "2025-08-21T20:00:00+09:00",
  "location": "서울특별시 OO구 풋살장 B",
  "maxPlayers": 10
}

응답

  • 현재 스펙: 200 OK
  • 권장: 201 Created + 생성된 리소스 또는 Location 헤더

5) 내가 참여한 경기 — GET /api/matches/me

  • 설명: 토큰 사용자 기준 참여 목록과 요약
  • 응답: 200 OK + MyMatchesResponse

응답 예시

{
  "summary": {
    "totalCount": 5,
    "upcomingCount": 3,
    "completedCount": 2
  },
  "matches": [
    {
      "id": 10,
      "participantId": 101,
      "location": "서울 OO구 풋살장 C",
      "matchDateTime": "2025-08-22T18:30:00+09:00",
      "maxPlayers": 10,
      "currentPlayers": 7,
      "joinedAt": "2025-08-18T09:00:00+09:00",
      "matchStatus": "OPEN"
    }
  ]
}

6) 경기 참여 — POST /api/matches/{matchId}/participants

  • 설명: 지정 경기 참여(중복 참여 방지, 정원 초과 시 거절)

  • 경로 파라미터: matchId: int64

  • 응답:

    • 현재 스펙: 200 OK
    • 권장: 201 Created 또는 200 OK(참여 리소스 반환 시)
  • 에러:

    • 정원 초과 → 409 CONFLICT
    • 중복 참여 → 409 CONFLICT
    • 존재하지 않는 경기 → 404 NOT_FOUND

응답 예시(권장)

{
  "participantId": 123,
  "matchId": 10,
  "joinedAt": "2025-08-18T12:00:00+09:00"
}

7) 경기 참여 취소 — DELETE /api/matches/{matchId}/participants

  • 설명: 내 참여 취소(경기 시작 이후 정책은 비즈니스 규칙에 따름)

  • 응답:

    • 현재 스펙: 200 OK
    • 권장: 204 No Content

8) 경기 삭제(관리자) — DELETE /api/matches/{matchId}

  • 권한: ADMIN

  • 설명: 경기 리소스 삭제

  • 응답:

    • 현재 스펙: 200 OK
    • 권장: 204 No Content
  • 에러:

    • 권한 없음 → 403 FORBIDDEN
    • 리소스 없음 → 404 NOT_FOUND

9) Cognito 백필(관리자) — POST /api/admin/users/backfill-cognito?confirm=false

  • 권한: ADMIN

  • 파라미터:

    • confirm(boolean, 기본 false)

      • false: 시뮬레이션(드라이런)
      • true: 실제 반영 (구현 확인 필요)
  • 응답: 200 OK + BackfillReport

응답 예시

{
  "processed": 120,
  "created": 5,
  "updated": 12
}

예시 cURL(curl)

# 1) 로그인/업서트
curl -X POST http://localhost:8080/api/users/signin-up \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# 2) 내 프로필
curl -X GET http://localhost:8080/api/users/me \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# 3) 경기 목록
curl -X GET http://localhost:8080/api/matches \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# 4) 경기 개설
curl -X POST http://localhost:8080/api/matches \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"matchDateTime":"2025-08-21T20:00:00+09:00","location":"서울 OO구 풋살장 B","maxPlayers":10}'

# 5) 경기 참여
curl -X POST http://localhost:8080/api/matches/10/participants \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# 6) 참여 취소
curl -X DELETE http://localhost:8080/api/matches/10/participants \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

# 7) 경기 삭제(관리자)
curl -X DELETE http://localhost:8080/api/matches/10 \
  -H "Authorization: Bearer <ADMIN_ACCESS_TOKEN>"

# 8) 백필(관리자) 드라이런
curl -X POST "http://localhost:8080/api/admin/users/backfill-cognito?confirm=false" \
  -H "Authorization: Bearer <ADMIN_ACCESS_TOKEN>"