course-registration

Spring Boot 4.1.1 / Java 21 기반 수강신청 API 예제입니다. 핵심은 CRUD 개수보다 수강신청 거부 규칙(R1~R8)동시 신청 시 정원·학점·시간표 정확성을 지키는 것입니다.

Scope

  • 수강신청(Create)
  • 내 수강신청 목록 / 강의 목록·상세(Read)
  • 수강취소(Delete, soft cancel)
  • 신청 수정(Update) API 없음 — 취소 후 재신청
  • 마스터 데이터 CRUD 없음 — Seeder 사용
  • 인증/JWT 없음
  • k6 부하 테스트는 후속 범위

상세 규칙은 docs/Requirements.md를 기준으로 합니다.

Run local

./gradlew bootRun

기본 profile은 local이며 H2 + Seeder가 자동 활성화됩니다.

  • API: http://127.0.0.1:8080/api/v1
  • Swagger UI: http://127.0.0.1:8080/swagger-ui.html
  • OpenAPI JSON: http://127.0.0.1:8080/v3/api-docs
  • Health: http://127.0.0.1:8080/actuator/health
  • H2 console: http://127.0.0.1:8080/h2-console

Run dev with PostgreSQL

cp .env.example .env
# 필요한 값 수정
docker compose up --build

Compose는 host에 127.0.0.1로만 노출합니다.

docker compose down
# DB volume까지 초기화하려면
docker compose down -v

Profiles

profile DB ddl-auto Seeder Swagger
local H2 create-drop ON ON
dev PostgreSQL update APP_SEED_ENABLED ON
prod PostgreSQL validate OFF SWAGGER_ENABLED 기본 false

운영 profile의 DB 접속 정보는 반드시 환경변수로 주입합니다.

API

POST   /api/v1/users/{userId}/registrations
GET    /api/v1/users/{userId}/registrations?semesterId={semesterId}
DELETE /api/v1/users/{userId}/registrations/{registrationId}
GET    /api/v1/lessons?semesterId={id}&subjectId={id}&page=0&size=20
GET    /api/v1/lessons/{lessonId}

Concurrency invariant

모든 registration mutation은 아래 순서로 row lock을 획득합니다.

User FOR UPDATE
  -> Lesson FOR UPDATE
    -> R4~R8 검증
      -> INSERT / cancel

User lock은 동일 학생의 학점·동일과목·시간표 경쟁을 직렬화하고, Lesson lock은 정원 경쟁을 직렬화합니다. 락 순서는 항상 User -> Lesson으로 고정합니다.

Local seed IDs

Postman과 동일한 고정 ID를 사용합니다.

Semester
00000000-0000-0000-0000-000000000001

1학년 학생
30000000-0000-0000-0000-000000000001

2학년 학생
30000000-0000-0000-0000-000000000002

대학원생
30000000-0000-0000-0000-000000000003

자료구조 01분반
40000000-0000-0000-0000-000000000001

자료구조 02분반 (동일 Subject)
40000000-0000-0000-0000-000000000002

운영체제 (자료구조 01과 월요일 시간 충돌)
40000000-0000-0000-0000-000000000003

정원 1명 강의
40000000-0000-0000-0000-000000000004

최소 3학년 강의
40000000-0000-0000-0000-000000000005

대학원생 전용 강의
40000000-0000-0000-0000-000000000006

월요일 11:00~13:00 경계 테스트 강의
40000000-0000-0000-0000-000000000007

Postman

postman/
  course-registration.postman_collection.json
  local.postman_environment.json
  dev.postman_environment.json

Register lesson 요청은 성공 시 응답의 registrationId를 environment에 자동 저장합니다.

Tests

./gradlew test
./gradlew build

테스트에는 다음이 포함됩니다.

  • R1~R8 규칙 및 경계값
  • 신청/조회/취소/재신청
  • 취소 이력 유지
  • 정원 1명에 동시 10명
  • 정원 30명에 동시 50명
  • 동일 학생의 학점 한도 경쟁
  • 동일 학생의 시간표 충돌 경쟁
  • 동일 학생의 같은 강의 중복 경쟁
S
Description
No description provided
Readme
140 KiB
Languages
Java 99.5%
Dockerfile 0.5%