-
Notifications
You must be signed in to change notification settings - Fork 1
API and Authentication
공개 API의 확인 방법과 사용자·내부 시스템 인증 경계를 설명합니다. 전체 요청·응답 스키마는 실행 중인 Swagger에서 확인합니다.
실행 중인 서버의 다음 주소를 API 계약 기준으로 사용합니다.
- Swagger UI는
/swagger-ui/index.html입니다. - OpenAPI JSON은
/v3/api-docs입니다. - 운영 Swagger는 api.cchaksa.com에서 확인합니다.
Controller와 controller/docs 아래의 Swagger 인터페이스가 함께 API 문서를 구성합니다. Wiki에는 전체 요청·응답 스키마를 복제하지 않습니다.
| 영역 | 주요 경로 | 인증 |
|---|---|---|
| Health |
/health, /actuator/health
|
공개 |
| 사용자 로그인 | POST /api/users/signin |
공개 |
| Token 갱신 | POST /api/auth/refresh |
공개 |
| 사용자 |
/api/users/me, /api/users/delete
|
Bearer JWT |
| 포털 연동 |
POST /portal/link, /portal/link/jobs/**
|
Bearer JWT |
| 학사 |
/api/academic/**, /api/semester/**
|
Bearer JWT |
| 학생 | /api/student/** |
Bearer JWT |
| 졸업 | /api/graduation/** |
Bearer JWT |
| 강의평가 | /api/lecture-evaluations/** |
Bearer JWT |
| Worker 콜백 | POST /internal/scrape-results |
HMAC Header |
| dev 테스트 |
/api/admin/** 일부 |
endpoint별 정책 확인 |
GET /api/graduation/progress의 data.analysisType은 진단 기준을 나타냅니다.
-
REGULAR: 일반 재학생의 영역별 졸업 진행도를graduationProgress로 반환합니다. -
TRANSFER: 편입생의 부분 진단을transferProgress로 반환합니다. 총 취득학점, 편입 인정학점, GPA, 지정과목 이수 상태를 포함하며 자동으로 확인할 수 없는 요건은manualReviewReasons에 표시합니다.
편입생의 analysisStatus는 현재 MANUAL_REVIEW_REQUIRED이며, 이는 API 오류가 아니라 학교 확인이 필요한 졸업요건이 남아 있다는 의미입니다. 전체 필드와 enum은 실행 중인 /v3/api-docs를 기준으로 확인합니다.
PR #343에 포함된 계약입니다. 운영 반영 여부는 PR과 배포 이력을 확인합니다.
- 3학년 편입생은 편입연도에서 2년 전의 학과별 일반 학생 요건을 적용합니다. 2026년 편입이면 2024학번 기준입니다.
-
transferProgress.areas의 전핵·전선은 각각 기준학점의 50%와 실제 취득학점을 비교합니다.requiredCredits는 소수점 기준을 보존하며, 예를 들어 19학점의 절반은 9.5학점입니다. - 전핵 필수과목 목록은 판정하지 않습니다.
requiredCourses는 기존 응답 호환을 위해 빈 목록으로 유지합니다. 전취 등 다른 영역은EARNED_ONLY이며 전핵에 합산하지 않습니다. - 기준이 있으면
COMPARISON, 해당 영역의 기준이 없거나 복수전공 정책이 미확정이면UNAVAILABLE입니다. 기준은 있지만 개인 학점이 미확인이면COMPARISON상태에서 학점·충족 여부를 null로 반환합니다. -
designatedEarnedCredits는 실제 이수한 지정과목의 코드별 학점 합계입니다. 통과 성적이 있고 개인 학점만 없으면 이수 상태는COMPLETED, 합계는 null과COURSE_DATA_INCOMPLETE를 반환합니다. 스냅샷 미수신은SNAPSHOT_NOT_RECEIVED로 구분합니다. - 두 영역을 충족해도 전체 졸업 자격을 확정하지 않으므로
analysisStatus=MANUAL_REVIEW_REQUIRED를 유지합니다.
POST /api/users/signin 요청은 다음 정보를 받습니다.
-
provider는KAKAO또는APPLE입니다. -
id_token은 Provider가 발급한 ID Token입니다. -
nonce는 로그인 요청에서 사용한 값입니다.
백엔드는 Provider 서명, iss, aud, 만료 시간, nonce를 검증합니다. 성공하면 자체 Access Token과 Refresh Token을 발급하고 포털 연동 여부를 반환합니다.
Kakao audience는 APP_KEY와 선택 값 APP_NATIVE_KEY를 사용합니다. Apple audience는 APPLE_CLIENT_ID와 선택 목록 APPLE_ALLOWED_CLIENT_IDS를 사용합니다.
OIDC 오류는 T01부터 T09를 확인합니다. 특히 T06은 앱 키와 Token의 aud가 다를 때 발생합니다.
보호 endpoint는 다음 Header를 요구합니다.
Authorization: Bearer <access-token>Access Token의 subject는 사용자 UUID입니다. Filter는 Token을 파싱하고 사용자 정보를 불러와 Security Context를 만듭니다.
- Header가 없으면 보호 endpoint에서
A05 AUTHENTICATION_REQUIRED입니다. - 만료되거나 잘못된 Token은
401입니다. - 인증은 됐지만 권한이 없으면
C04 FORBIDDEN과403입니다. -
Bearer접두사가 정확해야 합니다.
Token 원문은 로그, Issue, Sentry tag에 남기지 않습니다.
POST /api/auth/refresh는 Body의 refreshToken으로 Token을 재발급합니다. 저장된 세션과 Token이 맞지 않으면 T11, 저장된 Token이 없으면 T12입니다.
Refresh Token을 Access Token 대신 Authorization Header에 넣지 않습니다. Access와 Refresh의 만료 시간은 각각 JWT_ACCESS_EXPIRATION, JWT_REFRESH_EXPIRATION으로 관리합니다.
/internal/scrape-results는 공개 URL이지만 HMAC 검증을 통과해야 처리됩니다.
X-Timestamp: <unix timestamp>
X-Signature: <hmac signature>
X-Callback-Attempt: <positive integer>
X-Request-Id: <worker request id>X-Callback-Attempt와 X-Request-Id는 진단용이며, Timestamp와 Signature는 필수입니다. 허용 시각 차이는 SCRAPING_CALLBACK_ALLOWED_SKEW_SECONDS로 관리합니다.
서명 오류를 확인할 때도 Signature 원문이나 HMAC Secret을 공유하지 않습니다. 로그의 encoding, length, hash, timestamp delta만 사용합니다.
성공 응답은 SuccessResponse를 사용합니다. 실패 응답은 ErrorCode의 code, message, HTTP status를 기준으로 처리합니다.
클라이언트는 HTTP status만 보지 말고 오류 code를 함께 기록해야 합니다. 예를 들어 포털 작업은 모두 서버 오류처럼 보여도 C10, C16, C17, C18의 확인 지점이 다릅니다.
-
local은 모든 Origin을 허용합니다. -
dev와prod는 코드에 등록된 척척학사 Origin과 localhost를 허용합니다. -
OPTIONS요청은 공개됩니다.
CORS 변경은 SecurityConfig의 프로필별 설정을 확인하고 실제 Origin으로 preflight를 재현합니다. 브라우저 오류만 보고 백엔드 인증 문제로 판단하지 않습니다.