1. API 목록

2. POST: 회원가입 이메일 인증

HTTP Request
POST /sign-up/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 37
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr"
}
HTTP Response
HTTP/1.1 201 Created
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 1. Request Fields
Path Type Description

email

String

가입 이메일

2.1. ⚠️ 실패 케이스

❌ Case 1: 인증 이메일이 부산대 이메일이 아님
POST /sign-up/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 32
Host: localhost:8080

{
  "email" : "test@gmail.com"
}
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: 66

{
  "message" : "부산대 이메일만 가입 가능합니다."
}
Path Type Description

email

String

잘못된 도메인의 이메일 (부산대 메일이 아님)

3. PATCH: 회원가입 이메일 인증코드 확인

HTTP Request
PATCH /sign-up/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 67
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "authCode" : "exampleCode"
}
HTTP Response
HTTP/1.1 204 No Content
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 2. Request Fields
Path Type Description

email

String

가입 이메일

authCode

String

인증 코드

3.1. ⚠️ 실패 케이스

❌ Case 1: 인증번호 불일치
PATCH /sign-up/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 66
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "authCode" : "wrong_code"
}
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: 73

{
  "message" : "이메일 인증 코드가 일치하지 않습니다."
}
Path Type Description

email

String

가입 이메일

authCode

String

틀린 인증 코드

❌ Case 2: 만료된 인증코드
PATCH /sign-up/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 68
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "authCode" : "expired_code"
}
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: 83

{
  "message" : "이메일 인증 코드 만료 시간이 초과되었습니다."
}
Path Type Description

email

String

가입 이메일

authCode

String

만료된 인증 코드

4. POST: 회원가입

HTTP Request
POST /sign-up HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 123
Host: localhost:8080

{
  "name" : "테스트회원",
  "studentId" : "202612345",
  "email" : "example@pusan.ac.kr",
  "password" : "qwer123!"
}
HTTP Response
HTTP/1.1 201 Created
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 3. Request Fields
Path Type Description

name

String

회원 이름

studentId

String

회원의 학번

email

String

회원의 이메일

password

String

회원의 비밀번호

5. POST: 로그인

로그인 시도는 5회만 가능합니다. 5회 이내로 로그인 못하면 비밀번호를 변경해야 합니다.
HTTP Request
POST /sign-in HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 64
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "password" : "qwer123!"
}
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: 109

{
  "memberId" : 1,
  "name" : "테스트회원",
  "token" : "exampleToken",
  "types" : [ "ROLE_회원" ]
}
Table 4. Request Fields
Path Type Description

email

String

로그인 이메일

password

String

비밀번호 (영문+숫자+특수문자 조합)

Table 5. Response Body’s Fields
Path Type Description

memberId

Number

회원 고유 식별자

name

String

회원 이름

token

String

JWT 액세스 토큰

types

Array

회원 권한 목록(회원, 관리자)

6. POST: 비밀번호 변경 이메일 인증

HTTP Request
POST /sign-in/password-reset/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 37
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr"
}
HTTP Response
HTTP/1.1 201 Created
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 6. Request Fields
Path Type Description

email

String

가입 이메일

7. PATCH: 비밀번호 변경 이메일 인증코드 확인

HTTP Request
PATCH /sign-in/password-reset/email-auth HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 67
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "authCode" : "exampleCode"
}
HTTP Response
HTTP/1.1 204 No Content
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 7. Request Fields
Path Type Description

email

String

가입 이메일

authCode

String

인증 코드

7.1. ⚠️ 실패 케이스

회원가입 이메일 인증 실패 케이스와 동일

8. PATCH: 비밀번호 변경

HTTP Request
PATCH /sign-in/password-reset HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 72
Host: localhost:8080

{
  "email" : "example@pusan.ac.kr",
  "newPassword" : "newPassword1!"
}
HTTP Response
HTTP/1.1 204 No Content
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Table 8. Request Fields
Path Type Description

email

String

가입 이메일

newPassword

String

새로운 비밀번호

9. GET : 가입 이메일 찾기

HTTP Request
GET /sign-in/1/email-find HTTP/1.1
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: 37

{
  "email" : "example@pusan.ac.kr"
}
Table 9. /sign-in/{studentId}/email-find
Parameter Description

studentId

가입 학번

Table 10. Response Body’s Fields
Path Type Description

email

String

가입된 이메일

10. GET: Google OAuth 로그인 리다이렉트

사용자를 Google OAuth 인증 페이지로 리다이렉트합니다. CSRF 공격 방지를 위한 state 파라미터가 세션 ID와 함께 Redis에 저장됩니다. (TTL: 5분)
HTTP Request
GET /oauth/google HTTP/1.1
Host: localhost:8080
HTTP Response
HTTP/1.1 302 Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Location: https://accounts.google.com/o/oauth2/v2/auth?client_id=test&redirect_uri=http://localhost:8080/oauth/google/callback&response_type=code&scope=email+profile&state=test-state

11. GET: Google OAuth 콜백

Google OAuth 인증 완료 후 호출되는 콜백 엔드포인트입니다. 기존 회원이면 로그인 처리, 신규 회원이면 자동 가입 후 JWT 토큰을 발급합니다.
HTTP Request
GET /oauth/google/callback?code=authorization_code&state=state_token HTTP/1.1
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: 109

{
  "memberId" : 1,
  "name" : "테스트회원",
  "token" : "exampleToken",
  "types" : [ "ROLE_회원" ]
}
Table 11. Query Parameters
Parameter Description

code

Google 인가 코드

state

CSRF 방어용 상태 토큰

Table 12. Response Body’s Fields
Path Type Description

memberId

Number

회원 고유 식별자

name

String

회원 이름

token

String

JWT 액세스 토큰

types

Array

회원 권한 목록(회원, 관리자)

11.1. ⚠️ 실패 케이스

❌ Case 1: state 누락/불일치/만료
GET /oauth/google/callback?code=authorization_code&state=invalid_state HTTP/1.1
Host: localhost:8080
HTTP/1.1 401 Unauthorized
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
Content-Length: 66

{
  "message" : "소셜 로그인 인증에 실패했습니다."
}
❌ Case 2: 사용자 권한 거부
GET /oauth/google/callback?code=authorization_code&state=state_token&error=access_denied HTTP/1.1
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: 69

{
  "message" : "사용자가 권한 요청을 거부했습니다."
}