WEBBOOK CHAPTER

Spring Boot 4.1, 시작부터 런칭까지: 26장. 상태 전이를 도메인 안에 둔다

26장. 상태 전이를 도메인 안에 둔다

Controller에서 status=CLOSED를 그대로 저장하면 HIGH 위험 미확인 규칙을 모든 진입점에서 반복해야 한다. Handoff.close(actor, at)은 현재 상태, 미확인 위험, actor 권한, shift 종료 조건을 검사하고 성공하면 domain event를 만든다. 잘못된 전이는 명시적 예외로 거부한다.


public void close(UserId actor, Instant now) {
  if (status != Status.ACKNOWLEDGED) throw new IllegalTransition(status, "CLOSED");
  if (risks.stream().anyMatch(r -> r.high() && !r.acknowledged()))
    throw new UnacknowledgedHighRisk();
  status = Status.CLOSED;
  events.add(new HandoffClosed(id, actor, now));
}

상태 기계 표에는 출발·명령·도착·actor·전제·audit event·HTTP 결과를 넣는다. 같은 close 요청은 이미 닫힌 결과를 반환할지 409로 거부할지 계약으로 정한다. 시간을 Instant.now()로 내부에서 직접 만들지 않고 Clock을 주입해 경계 시각을 시험한다. 단위 테스트는 정상 경로보다 DRAFT close, 미확인 HIGH, 다른 현장 actor, 중복 요청을 더 자세히 검증한다.