병원 예약 시스템의 결제 프로세스 설계와 구현: 시퀀스 다이어그램을 통한 분석

momomoki·2025년 1월 9일
0

설계 배경

병원 예약 시스템에서 결제 프로세스는 여러 복잡한 요소들이 얽혀있습니다. 예약 정보 검증, 결제 처리, 데이터 정합성 유지 등 다양한 단계들이 순차적으로 실행되어야 하며, 각 단계별로 적절한 예외 처리가 필요합니다. 이러한 복잡한 프로세스를 체계적으로 설계하고 구현하기 위해 시퀀스 다이어그램을 활용했습니다.

시퀀스 다이어그램 설계 목적

  • 전체 프로세스의 명확한 시각화
  • 각 컴포넌트 간의 상호작용 정의
  • 예외 상황에 대한 체계적인 처리 흐름 설계
  • Redis를 활용한 동시성 제어 포인트 명확화

시퀀스 다이어그램 설명

예약 프로세스

  • 클라이언트가 필수 정보(병원 ID, 예약 날짜, 예약 시간)와 함께 예약 요청
  • 서비스 레이어에서 Redis를 통한 진행 중인 예약 여부 확인
  • 예약 가능 여부 검증 후 임시 예약 정보를 Redis에 저장
  • DB를 통한 최종 예약 가능 여부 확인

결제 프로세스

  • 포트원 API를 통한 결제 정보 획득
  • 결제 컨트롤러에서 필수 정보 검증
  • 병원 정보와 사용자 정보 유효성 검증
  • 결제 내역 저장 및 예약 정보 최종 등록
  • Redis의 임시 예약 정보 삭제

예외 처리

  • 진행 중인 예약 존재 시 예외 처리
  • 이미 예약된 시간대 처리
  • 결제 실패 시 Redis 데이터 정리
  • 사용자/병원 정보 누락 시 처리

핵심 코드

예약 프로세스 코드

 @Transactional(readOnly = true)
    public ReservationIsvalidAndLockResponse isValidReservaion(ReservationSaveRequest request){
        // 레디스에 예약중인지 체크
        if(!applicationLockClient.isvalidRedisKey(request.getHospId(), request.getReservationAt(), request.getReservationTime())) {
            throw new RuntimeException();
        }
        // 키값을 락을 걸어 키를 레디스에 저장후 락을 푼다.
        String redisKey = reservationLock(request);
        // false면 예약이 가능하다.
        Boolean isvalid = hospitalReservationRepository.findByHospIdAndReservationDateAndReservationTime(request).isPresent();
        if(isvalid) applicationLockClient.remove(redisKey);
        return new ReservationIsvalidAndLockResponse(redisKey, isvalid);
    }

주요 처리 단계

진행 중인 예약 확인

  • dis를 통해 해당 시간대의 진행 중인 예약이 있는지 확인
  • 진행 중인 예약이 있다면 예외 발생

동시성 제어

  • 키에 대한 락 획득 및 Redis에 임시 저장
  • 분산 환경에서의 동시 접근 제어

최종 유효성 검증

  • DB에서 실제 예약 정보 조회
  • 이미 예약된 경우 Redis의 임시 데이터 삭제

결제 프로세스 코드

@Transactional
public Boolean createPayment(CreatePaymentRequest createPaymentRequest){
    // 트랜잭션 완료 후 Redis 락 해제를 보장하기 위한 동기화 설정
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
        @Override
        public void afterCompletion(int status) {
            releaseLock(createPaymentRequest.getRedisKey());
        }
    });
    Optional<HospitalEntity> isValidHospital = hospitalRepository.findById(createPaymentRequest.getHospId());
    Optional<SocialUserEntity> isValidUser = socialUserJpaRepository.findByProviderId(createPaymentRequest.getProviderId());
    // 결제 유저, 병원 있는지 체크
    if(isValidUser.isPresent() && isValidHospital.isPresent()){
        PaymentEntity payment = PaymentEntity.from(createPaymentRequest, isValidHospital.get(), isValidUser.get());
        PaymentEntity createdPayment = paymentRepository.save(payment);
        // 결제정보를 저장되었는지
        HospitalReservationEntity hospitalReservation = HospitalReservationEntity.from(createPaymentRequest, isValidUser.get(), isValidHospital.get(), createdPayment);
        hospitalReservationService.createReservation(hospitalReservation);
    }
    return false;
}

주요 처리 단계

트랜잭션 동기화 설정

  • 트랜잭션 완료 후 자동으로 Redis 락 해제
  • 예외 발생 시에도 락 해제 보장

데이터 유효성 검증

  • 병원과 사용자 정보의 존재 여부 확인
  • 필수 데이터 검증

결제 및 예약 처리

  • 결제 정보 생성 및 저장
  • 예약 정보 최종 등록

결론

시퀀스 다이어그램을 통한 설계는 복잡한 예약-결제 프로세스의 흐름을 시각화하고, 컴포넌트 간의 상호작용을 명확히 파악할 수 있게 해주었습니다. 이러한 설계를 바탕으로 Redis를 활용한 동시성 제어와 트랜잭션 처리를 구현하여, 분산 환경에서도 안정적으로 동작하는 예약 시스템을 구축할 수 있었습니다.

profile
얍얍엽엽욥욥

0개의 댓글

관련 채용 정보