Skip to content

[Feat/#175] 빌릴게 대여 이용 제한 기간 설정 + 신청 차단 - #182

Open
jjunh33 wants to merge 10 commits into
feat/#174-admin-rental-status-and-approval-flowfrom
feat/#175-exam-period-rental-block
Open

jjunh33 wants to merge 10 commits into
feat/#174-admin-rental-status-and-approval-flowfrom
feat/#175-exam-period-rental-block

Conversation

@jjunh33

@jjunh33 jjunh33 commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

#️⃣연관된 이슈

🎯 해결하려는 문제가 무엇인가요?

관리자가 임의의 기간과 사유를 설정하면, 그 기간 동안 학생의 대여 신청을 실제로 막는다(처음엔 "시험기간" 전용으로 시작했으나, 특정 용도에 묶이지 않도록 범용 이용 제한 기간으로 바꿨다). 더불어 #172~#174 스택 전체를 마지막으로 검토하며 발견한 버그 수정과 코드 정리를 함께 담았다.

❓ 왜 해결해야 하나요?

레거시(billilge/backend)에도 있던 기능인데 지금은 대여 신청이 그대로 열려 있다. "시험기간"으로 좁게 구현했다가, 리뷰 중 관리자가 임의 기간에 사유를 적어 막을 수 있도록 범용화하는 쪽으로 방향을 바꿨다. 또한 #172~#174를 쌓고 나서 전체를 다시 훑어보니, 승인 플로우 도입(#174)이 간접적으로 만든 버그 두 개와 트랜잭션 전제가 깨진 부분을 발견해 이 PR에서 같이 고쳤다.

⭐ 어떻게 해결했나요?

대여 이용 제한 기간 설정 + 신청 차단

  • RentalBlockPeriodConfigKeys(RENTAL_BLOCK_START/RENTAL_BLOCK_END/RENTAL_BLOCK_REASON) — 기존 admin_config_values key-value를 그대로 재사용, 새 테이블 없음.
  • GET/PUT /v1/admin/billilge/rental-block-period(AdminRentalBlockPeriodApi/Controller) — 날짜 역전 검증(종료일 < 시작일 → INVALID_INPUT)은 컨트롤러에 두지 않고, 새로 만든 AdminRentalBlockPeriodUseCase로 옮겼다.
  • RentalErrorCode.INVALID_RENTAL_TIME_BLOCKED 추가 — 관리자가 적은 차단 사유를 그대로 에러 메시지에 노출한다(BusinessException의 formatArgs 생성자를 이 코드베이스에서 처음 실제로 사용).
  • RentalApplyUseCase.apply()의 lockExecutor.executeOptimistic(...) 진입 전에 차단 기간 체크(validateNotBlocked)를 둔다(단순 조회라 재시도 루프 밖에서 처리). 반납 신청·취소는 막지 않는다.

#172~#174 스택 전체 재검토에서 발견한 수정

  • RentalHistory.changeStatusByAdmin이 RENTAL/RETURNED로 바뀔 때 rentAt/returnedAt을 항상 지금 시각으로 덮어쓰도록 변경(기존엔 "비어 있을 때만"이라 사실상 죽은 코드였다). 같은 상태로의 반복 요청은 아무 효과가 없도록 가드를 추가해 처리자 로그 중복 적재도 함께 막았다.
  • 대여품(RENTAL) 물품을 반납 정책 없이 등록·수정할 수 있던 구멍을 막았다(RentalErrorCode.RETURN_POLICY_REQUIRED).
  • 낡은 javadoc, 미사용 메서드(isHolding()) 정리.

관리자 전용 대여 조회 분리 + 마지막 정리

  • 관리자 전용 대여 이력 조회·상태 변경(search/getById/changeStatusByAdmin/getWorkerLogs)을 학생 쪽 RentalHistoryService에서 분리해 AdminRentalHistoryService로 옮겼다 — AdminItemService/ItemService 분리 패턴과 맞췄다.
  • search/getById에 붙였던 읽기 전용 트랜잭션을 다시 검토해 뺐다. 두 조회 사이에 물품 정책이 바뀌어도 조회 화면 한 행의 dueAt이 드물게 어긋나는 정도라 트랜잭션으로 묶을 만큼의 문제는 아니라고 판단했고, 같은 레이스를 가진 학생 쪽 조회 메서드(getHistories/getReturnRequiredRentals/getAllReturnRequiredRentals)에도 똑같이 적용해 일관성을 맞췄다.
  • 설계 이유·대안 비교를 길게 풀어쓴 주석들을 "이 메서드가 뭘 하는지" 정도의 한 줄로 정리했다(로직 변경 없음).

🧩 이 PR의 한계 & 트레이드오프

관리자 PATCH로 상태를 바꿀 때 백데이트(과거 시각 지정)는 여전히 지원하지 않는다 — 항상 처리 시점의 현재 시각으로 기록된다. 이용 제한 기간은 한 번에 하나만 설정할 수 있다(여러 기간을 동시에 등록하는 건 지원하지 않는다).

⛓️ 기존 기능에 미치는 영향

  • 대여 신청 API에 이용 제한 기간 차단이 새로 생긴다(INVALID_RENTAL_TIME_BLOCKED).
  • 관리자 상태 변경 API의 rentAt/returnedAt 기록 시점이 더 정확해진다.
  • 물품 등록/수정 API에 새 검증(RETURN_POLICY_REQUIRED)이 생겨, 반납 정책 없는 대여품 등록 요청은 이제 막힌다.
  • GET/PUT /v1/admin/billilge/examperiod가 /v1/admin/billilge/rental-block-period로 바뀌고 요청/응답에 reason 필드가 추가됐다(아직 머지 전이라 연동된 프론트는 없다).

🔀 Edge Case & 실패 시나리오

같은 상태로의 반복 요청(예: 이미 RENTAL인데 다시 RENTAL 요청)은 이제 아무 효과가 없다 — 재고 변화·로그 적재·시각 재기록이 전부 일어나지 않는다.

📋 검토한 대안과 선택 이유

  • 차단 기간 체크 위치를 컨트롤러(순수 검증)와 UseCase(DB 조회 필요) 중 어디에 둘지 검토했다. admin_config_values 조회가 필요해 RentalTimeValidator처럼 컨트롤러에 둘 수 없었고, apply() 내부·락 재시도 밖에 두었다.
  • 차단 사유를 관리자 참고용으로만 남길지, 학생에게 보여줄 에러 메시지에 넣을지 검토했다. 왜 막혔는지 알려주는 게 더 유용하다고 판단해 메시지에 포함했다.
  • search/getById의 스냅샷 일관성(트랜잭션)을 지킬지, 트랜잭션 오버헤드를 줄일지 검토했다. 조회 화면 표시값일 뿐이라는 낮은 중요도를 고려해 트랜잭션을 빼는 쪽으로 결정했다.

💬 리뷰 포인트

  • [r] 시험기간 → 범용 이용 제한 기간 전환 전체 — API 경로·요청/응답 필드가 바뀌었습니다.
  • [r] 차단 사유를 에러 메시지에 그대로 노출하는 설계 — 괜찮은 방향인지 확인해주세요.
  • [c] search/getById 트랜잭션 제거 — 레이스 컨디션 허용 범위에 대한 판단입니다.
  • [a] 주석 정리 — 로직 변경 없음, 최종 상태만 봐주시면 됩니다.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@jjunh33 jjunh33 linked an issue Oct 28, 2026 that may be closed by this pull request
6 tasks done
@jjunh33
jjunh33 added this pull request to stack #183 October 28, 2026 13:35
@jjunh33
jjunh33 force-pushed the feat/#175-exam-period-rental-block branch from 125e72e to 6ca0b19 Compare October 28, 2026 13:39
@jjunh33
jjunh33 force-pushed the feat/#175-exam-period-rental-block branch from 8ca2071 to 33a1682 Compare October 28, 2026 14:13
@jjunh33
jjunh33 force-pushed the feat/#175-exam-period-rental-block branch from 33a1682 to a9f8181 Compare October 29, 2026 18:22
@jjunh33 jjunh33 changed the title [Feat/#175] 빌릴게 시험기간 설정 + 대여 신청 차단 [Feat/#175] 빌릴게 대여 이용 제한 기간 설정 + 신청 차단 Oct 30, 2026
getById는 유일한 호출부가 이미 LockExecutor 안에서 불러 그 트랜잭션에
합류하므로 자체 트랜잭션이 의미가 없었다. search는 대여 이력·물품 두 번
조회 사이에 물품 정책이 바뀔 수는 있지만, 조회 목록에 보여주기용으로
계산하는 dueAt 한 행이 드물게 어긋나는 정도라 트랜잭션으로 묶을 만한
문제는 아니라고 판단해 뺐다.
특정 시험기간 전용이 아니라 관리자가 임의 기간에 사유를 적어 대여를
막을 수 있도록 ExamPeriod* 전반을 RentalBlockPeriod*로 바꿨다. 사유는
admin_config_values에 새 키(RENTAL_BLOCK_REASON)로 저장하고, 학생이
그 기간에 신청하면 BusinessException의 formatArgs로 에러 메시지에
그대로 노출한다.

날짜 역전 검증(종료일 < 시작일)은 컨트롤러가 아니라 새로 만든
AdminRentalBlockPeriodUseCase로 옮겼다.
메서드가 뭘 하는지 정도만 남기고, 설계 이유·대안 비교·레이스 컨디션
설명처럼 길게 풀어쓴 부분은 줄였다. 로직 변경은 없다.
@jjunh33
jjunh33 force-pushed the feat/#175-exam-period-rental-block branch from 4b36b33 to b71910d Compare October 31, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

빌릴게 시험기간 설정 + 대여 신청 차단 적용

1 participant