어느덧 실전 프로젝트 3주차에 접어들었다.
매일 아침 해야할 일들을 정리하고 저녁 회의 때 진행사항을 확인하는데, 팀원들이 각자 맡은 부분을 잘 만들어줘서 서로 결과를 공유하는 시간이 기대된다.
주차장 예약과 입차 프로세스에 대한 코어 알고리즘을 구현하여 예약 안정성, 주차장 운영 효율성을 모두 잡을 수 있도록 남은 시간 열심히 또 해볼 것이다!
WIL에는 이번주 프로젝트 진행상황과 멘토링 피드백을 정리해서 기록해본다.
이번주 한 일
데이터 저장
- 주차장 정보 크롤링 완료
- 전국 주차장 정보 저장 완료 (약 78,000건)
- 예약정보, 주차현황정보 저장 완료 (약 220만건)
예약 알고리즘
- 1차 개선 예약 알고리즘 구현
- 2차 개선 예약 알고리즘 구상
주차장 검색 및 조회
- 주차장 검색 성능 개선
- 주차장 조회 성능 테스트
- 레디스 캐시 공부
- QueryDSL 적용
동시성 제어
- 입차시 Redis 스핀락 적용(추후 변경 예정)
테스트코드
기타
- https 적용
- Chat GPT 코드리뷰 Workflow 추가
기술 공부 & 정리
피드백 정리
레디스 캐시 적용
- Hit rate : 캐시에서 요청된 데이터 중 캐시에 이미 저장되어 있는 데이터의 비율
- (캐시에서 찾은 데이터 수 / 전체 요청 수) * 100
- 보통 Redis 캐시에서 hit rate가 90% 이상인 경우, 캐시가 효율적으로 작동한다고 본다.
- Cache hit : 캐시에 해당 데이터가 이미 저장되어 있는 경우
- Cache miss : 캐시에 해당 데이터가 저장되어 있지 않은 경우
- Key가 계속 달라지고 조건에 따라 달라지는 결과가 많을수록 Hit rate가 떨어진다.
- 모든 주차장의 모든 시간대의 주차 가능 대수를 캐시에 넣는 것은 비효율적
- 캐시를 적용할만한 부분이 무엇이 있을지는 좀 더 고민해볼 것
예약 알고리즘 - version 2
기본 설정
- 기존 일반구획, 예약구획, 공통구획을 없앤다.
- 일반차량이 입차할 때 즉시 예약처리한다. → 주차장에 들어오는 모든 차들은 예약차량이다.
- 예약하지 않은 차량은 입차할 때 언제 나갈 것인지 시간을 입력 받는다. (1시간, 2시간, …)
- 예약여부는 입차할 때 사용자가 입력한다고 가정한다. (입차 request에 예약여부 포함하여, 예약차량이 아닌 경우에만 언제 나갈 것인지 시간을 입력한다.)
- (15분 전에 주차장 자리가 부족하면 예약자에게 알림을 보낸다. + 보너스)
- (예약종료시간을 지키지 않았을 경우 페널티를 부과한다.)
- (초기주차요금과 최종주차요금을 보여준다.)
테이블 설계
사전예약 로직
-
예약시간을 입력하면 다음 정보를 보여준다.
- 선택시간 사이에 예약불가한 시간이 있다면 → 예약불가 시간대 출력
- 선택시간 사이에 운영을 안한다면 → 운영시간 출력
- init_charge 출력
1-1. 선택시간 사이 예약불가 시간대 구하기
park_booking_by_hour
에서 선택 시간대별 available
값이 있는지 확인
- ex) 2023-04-02 10:00 ~ 13:00 시간을 입력했다면,
park_booking_by_hour
에서 {date = 2023-04-02, time = 10}, {date = 2023-04-02, time = 11}, {date = 2023-04-02, time = 12}인 데이터를 찾는다.
- 조건에 맞는 데이터가 없다면 → 해당 주차장에 예약자가 없으므로 해당 시간대는 예약이 가능하다.
- 조건에 맞는 데이터가 있고 available > 0 이라면 → 해당 시간대에 예약 가능하다.
- 조건에 맞는 데이터가 있고 available ≤ 0 이라면 → 해당 시간대는 예약이 불가하다.
1-2. 선택시간 사이 운영시간 확인
- 선택시간 사이에 운영하지 않는 시간이 있다면 isOperation = false 리턴
1-3. 선택시간 사이 요금 계산 후 리턴
-
예약을 진행한다.
1) park_booking_info
에 예약 데이터 생성
- park_info_id, users_id, car_num, start_time, end_time 입력
2) park_booking_by_hour
, park_booking_slot
에 데이터 생성
park_booking_by_hour
에 start_time ~ end_time 사이 시간대별 데이터가 있는지 확인
- ex) 2023-04-02 10:00 ~ 13:00 시간을 입력했다면,
park_booking_by_hour
에서 {date = 2023-04-02, time = 10}, {date = 2023-04-02, time = 11}, {date = 2023-04-02, time = 12}인 데이터를 찾는다.
- 해당하는 데이터가 없으면 park_info_id, date, time, available 새로 생성하여 저장 후,
park_booking_slot
에 park_booking_by_hour_id, park_booking_info_id를 저장
- 해당하는 데이터가 있으면 availbale 에서 1을 빼고,
park_booking_slot
에 park_bookin_by_hour_id, park_booking_info_id를 저장
즉시예약 로직
예약하지 않고 주차장에 입차하려는 차량은 즉시예약 로직을 사용한다. 즉시예약은 비회원으로 예약된다.
-
출차시간을 입력한다. (ex. 1시간, 2시간 등 시간단위)
- 선택시간 사이에 예약불가한 시간이 있다면 → 예약불가 시간대 출력
- 선택시간은 예약이 가능하다면 → 예약 진행
1-1. 선택시간 사이 예약불가 시간대 구하기
park_booking_by_hour
에서 선택 시간대별 available
값이 있는지 확인
- available이 null이라면 → 기존 예약자가 없으므로 해당 시간대는 예약이 가능하다.
- available의 값이 있다면 → 값이 0 이하이면 해당 시간대는 예약이 불가하다.
-
즉시예약을 진행한다.
1) park_booking_info
에 예약 데이터 생성
- park_info_id,
users_id, car_num, start_time(현재시간), end_time 입력
2) park_booking_by_hour
, park_booking_slot
에 데이터 생성
park_booking_by_hour
에 start_time ~ end_time 사이 시간대별 데이터가 있는지 확인
- 해당하는 데이터가 없으면 park_info_id, date, time, available 새로 생성하여 저장 후,
park_booking_slot
에 park_booking_by_hour_id, park_booking_info_id를 저장
- 해당하는 데이터가 있으면 availbale 에서 1을 빼고,
park_booking_slot
에 park_bookin_by_hour_id, park_booking_info_id를 저장
주의할 점
입차 알고리즘
입차 요청시 parkInfoId
, carNum
, parkingTime
을 입력받는다.
parkingTime
은 입차 후 몇시간을 사용할지 시간을 입력받는다.
사전예약차량이 parkingTime을 입력한 건은 무시된다.
사전예약 차량 입차 로직
park_booking_info
에서 입차하려는 차량의 예약 ID를 찾는다.
- 입차하려는 시간에 주차중인 차량의 대수를 구한다.
park_mgt_info
에서 exit_time = null 인 수를 구하거나,
park_booking_slot
에서 카운트한다.
- 주차중인 차량 대수 < 총 구획 수 일때만 입차한다.
즉시예약 차량 입차 로직
isBooking
= false, parkingTime
= 2 요청이 들어온대로 즉시예약을 진행한다.
park_booking_info
에서 입차하려는 차량의 예약 ID를 찾는다.
- 입차하려는 시간에 주차중인 차량의 대수를 구한다.
park_mgt_info
에서 exit_time = null 인 수를 구하거나,
park_booking_slot
에서 카운트한다.
- 주차중인 차량 대수 < 총 구획 수 일때만 입차한다.
화잇팅 =D