Skip to content

[reservation] 활성 예약 판정을 도메인·쿼리 레벨로 이관 - #125

Merged
d1ng1724 merged 5 commits into
masterfrom
refactor/reservation-currently-active-query
Sep 10, 2026
Merged

[reservation] 활성 예약 판정을 도메인·쿼리 레벨로 이관#125
d1ng1724 merged 5 commits into
masterfrom
refactor/reservation-currently-active-query

Conversation

@d1ng1724

@d1ng1724 d1ng1724 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

개요

isActive() && !isExpired() 형태로 서비스 곳곳에 복제되어 있던 만료 제외 활성 예약 판정을 도메인 메서드와 리포지토리 쿼리로 이관하였습니다. 판정 규칙을 한곳에 모아 새 호출부에서 만료 조건이 누락되는 격차를 막고, 활성 상태 전체를 로드한 뒤 메모리에서 거르던 방식을 reservedAt 컷오프를 조건에 포함한 쿼리로 전환하였습니다.

본문

도메인 메서드 추가

Reservation.isCurrentlyActive()를 추가하였습니다. 활성 상태이더라도 타임아웃이 지난 RESERVED 예약은 활성으로 세지 않는다는 규칙을 엔티티가 직접 표현합니다.

리포지토리 쿼리 추가

ReservationRepositoryCustomfindCurrentlyActiveByUser, findCurrentlyActiveByMachine, findCurrentlyActiveByRoomNumber 세 개를 추가하였습니다. 만료 조건은 공통 currentlyActive() BooleanExpression으로 한곳에 모았습니다.

status = RUNNING
  OR (status = RESERVED AND reservedAt > now - 타임아웃)

RUNNING은 타임아웃 대상이 아니므로 그대로 통과시키고, RESERVED만 컷오프를 적용합니다. isExpired()Duration.between(reservedAt, now).toMinutes() >= 타임아웃이므로 이 조건은 그 부정과 정확히 일치합니다. 기존 findExpiredReservations()가 쓰던 reservedAt 기준 및 idx_user_status_created_at 인덱스와 같은 축을 사용합니다.

호출부 전환

  • ReservationCreationSupport의 기기 단위 중복, 1인 1예약, 호실 동일 유형 중복 검증 세 곳을 새 쿼리로 전환하였습니다. 메모리 판정용 hasCurrentActiveReservation() 헬퍼와 ACTIVE_STATUSES 상수가 함께 제거되었습니다.
  • QueryActiveReservationServiceImpl은 정렬까지 쿼리(createdAt 내림차순)로 넘겨 서비스는 첫 건만 취하도록 단순화하였습니다.
  • QueryRoomActiveReservationsServiceImpl.filter(r -> !r.isExpired())를 제거하였습니다.
  • 메모리 판정이 남는 유일한 지점인 ActiveReservationSelectorisCurrentlyActive()로 교체하였습니다.

기존 판정과 논리적으로 동등하며 동작 변경은 없습니다.

부수 개선

사용자 및 호실 활성 예약 조회에 fetch join이 없어 DTO 매핑 시 N+1이 발생하던 것을 새 쿼리에서 해소하였습니다.

타임아웃 유무와 길이를 ReservationStatus에서 파생하도록 정리하였습니다. 엔티티(isExpired(), getRemainingTimeUntilTimeout())와 QueryDSL 조건 양쪽에 상태별 분기가 따로 박혀 있어 한쪽만 고치면 어긋날 수 있었으나, 이제 열거형만 수정하면 두 판정이 함께 따라옵니다.

호출부 전환으로 사용처가 사라진 findByUserAndStatusIn, findByMachineAndStatusIn, findActiveReservationsByRoomNumber를 제거하였습니다.

테스트

기존 스텁을 새 쿼리로 전환하였습니다. 만료 필터링이 쿼리 책임이 되면서 서비스 단위로는 검증할 수 없게 된 테스트 세 건을 제거하고, 해당 커버리지를 ReservationTestisCurrentlyActive() 단위 테스트 네 건으로 옮겼습니다.

더해서 리포지토리 통합 테스트 인프라를 새로 마련하였습니다. H2와 spring-boot-starter-data-jpa-test를 테스트 의존성에 추가하고, ReservationRepositoryCurrentlyActiveTest@DataJpaTest로 실제 쿼리를 실행합니다. 엔티티의 isCurrentlyActive()와 QueryDSL 조건이 같은 답을 내는지 타임아웃 직전·정각·경과·미래 시각과 RUNNING 경계에서 대조하므로, 한쪽 규칙만 바뀌면 이 테스트가 실패합니다.

전체 테스트 480건이 통과합니다.

Closes #114

@d1ng1724 d1ng1724 added the 리팩터링 코드를 개선합니다. label Sep 3, 2026
@d1ng1724 d1ng1724 self-assigned this Sep 3, 2026
@d1ng1724
d1ng1724 requested a review from exijn September 3, 2026 11:45
Base automatically changed from develop to master September 3, 2026 11:48
@exijn

exijn commented Sep 8, 2026

Copy link
Copy Markdown
Member

/review

@exijn

exijn commented Sep 9, 2026

Copy link
Copy Markdown
Member

/review

@inryeok-bot inryeok-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 결과

변경된 15개 파일을 검토했으며, 수정이 필요한 문제를 찾지 못했습니다.

심각도 개수
Critical 0
High 0
Medium 0
Low 0

완료

변경 사항을 검토했으며 게시할 인라인 코멘트가 없습니다.

재리뷰 비교

구분 개수
새로운 Finding 0
계속 확인된 Finding 0
이번 리뷰에서 다시 발견되지 않음 0

이번 리뷰에서 다시 발견되지 않았다는 것이 해결을 확정하는 것은 아닙니다.

재실행한 검토 결과입니다.

검토한 head: 562d3925637d

@d1ng1724
d1ng1724 merged commit 9b0e3a5 into master Sep 10, 2026
1 check passed
@d1ng1724
d1ng1724 deleted the refactor/reservation-currently-active-query branch September 10, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

리팩터링 코드를 개선합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[reservation] 활성 예약 판정을 도메인·쿼리 레벨로 이관

2 participants