Skip to content

프론드엔드 시간 예약 블록 색상 버그 분석 & 수정 ​

증상: 프론드엔드 시간 블록 색이 "진행중/예정/종료"로 딱 떨어지지 않고 들쭉날쭉. 같은 오전 시간대 회의인데 어떤 건 초록(예정), 어떤 건 파랑(종료)으로 뒤죽박죽 칠해짐.

1. 무엇이 문제인가 ​

세 개의 뷰(EnterStylePage → TimelineView, KakaoStylePage → ReservationGrid, DailyBoardPage)가 모두 공통 모듈 constants/meetingStatus.ts 의 getMeetingStatus() 로 색을 정한다. 의도는 "현재 시각 기준 예정/진행중/종료 3색"인데, 화면에서는 색이 시간과 무관하게 섞여 나온다.

핵심은 블록을 그리는 기준과 색을 정하는 기준이 서로 다르다는 점이다.

구분사용하는 값코드
블록 위치(가로/세로 배치)ISO 문자열의 시:분(벽시계)만, 날짜는 버림iso.split('T')[1] → HH:MM
블록 색상(상태 판정)전체 타임스탬프(날짜+시각+오프셋)new Date(startTime).getTime() vs Date.now()

2. 근본 원인 ​

2-1. 백엔드는 하루치가 아니라 4일치를 내려준다 ​

GET /reservations?date=... 의 구현이 단일 날짜가 아니라 넓은 윈도우를 조회한다.

kotlin
// place-back/.../ReservationRepositoryImpl.kt
override fun findAllReserveAtDate(date: LocalDate): List<Reservation> {
    val start = date.minusDays(1).atStartOfDay()...   // 전날
    val end   = date.plusDays(3).atStartOfDay()...     // +3일
    return reservationJpaRepository.findByStartTimeLessThanAndEndTimeGreaterThan(end, start)
}

즉 date = 6/29 로 조회해도 6/28 ~ 7/1 의 예약이 함께 내려온다.

2-2. 프론트는 날짜를 무시하고 시:분만으로 블록을 배치한다 ​

TimelineView / ReservationGrid / DailyBoardPage 모두 위치 계산에서 날짜 부분을 떼고 시:분만 쓴다. 그래서 내일(6/30) 10:30 회의도 오늘(6/29) 보드의 10:30 칸에 그려진다. 또한 어느 페이지도 받은 예약을 보드 날짜로 필터링하지 않는다.

2-3. 색은 전체 타임스탬프로 판정한다 → 위치와 색의 기준이 어긋남 ​

같은 블록인데 위치는 "오늘 10:30", 색은 "실제로는 6/30 10:30 = 미래" 로 계산된다. 결과적으로 오늘 오전 칸에 그려졌지만 색은 '예정(초록)' 인 블록이 잔뜩 생긴다. 며칠치가 섞여 들어오므로 색이 시간순으로 정렬되지 않고 무작위처럼 보이는 것이다.

요약: "자리는 시:분으로, 색은 날짜까지" 라는 두 기준의 불일치 + 백엔드의 4일치 응답이 겹쳐서 색이 들쭉날쭉해졌다. 색 토큰(index.css)이나 클래스 매핑(meetingStatus.ts) 자체는 잘못이 아니다.

2-4. (별개) 현재시각 표시선이 뷰마다 제각각 ​

  • TimelineView: 빨강 세로선 (bg-red-400)
  • ReservationGrid: 파랑 가로선 (border-blue-500)
  • DailyBoardPage: 아예 없음

3. 어떻게 고치나 (프론트 전용) ​

사용자 요구대로 백엔드는 그대로 두고 프론트에서 보여지는 것만 바로잡는다.

  1. 보드 날짜로 필터링 — 각 뷰에서 startTime 의 날짜(YYYY-MM-DD)가 선택된 보드 날짜와 같은 예약만 그린다. 이걸로 다른 날짜 블록이 섞이는 문제가 사라지고, 위치와 색의 기준이 일치한다.
  2. 상태 판정을 배치와 동일한 '벽시계' 기준으로 — getMeetingStatus 가 오프셋(+09:00/Z)에 휘둘리지 않도록, 블록 배치와 똑같이 ISO의 날짜+시:분을 로컬 벽시계로 읽어 현재 시각과 비교한다. 포맷이 어떻게 오든 "화면에 보이는 시각" 기준으로 색이 정해진다.
  3. 현재시각 선 공통화 — index.css 에 --color-now 토큰과 .now-line(+-vertical/-horizontal) 클래스를 선언하고 세 뷰가 같은 색·두께를 쓰게 한다. 빠져 있던 DailyBoardPage 에도 추가.

4. 상태 정의 (확정) ​

상태조건색(토큰)
예정 upcomingnow < start연초록 (--color-meeting-upcoming*)
진행중 ongoingstart ≤ now < end주황 (--color-meeting-ongoing*)
종료 endednow ≥ end회청색 (--color-meeting-ended*)

판정 기준 시각 now 는 1분마다 갱신(setInterval)되어 진행중→종료 전이가 자동 반영된다. 보드 날짜가 오늘이 아니면 자연히 전부 예정(미래 날짜) 또는 전부 종료(과거 날짜)로 나온다.

5. 변경 파일 ​

  • place-front/src/index.css — --color-now 토큰, .now-line* 공통 클래스 추가
  • place-front/src/constants/meetingStatus.ts — 벽시계 기준 getMeetingStatus, 날짜키 헬퍼 추가
  • place-front/src/components/reservation/TimelineView.tsx — 날짜 필터 + 공통 현재시각 선
  • place-front/src/components/reservation/ReservationGrid.tsx — 날짜 필터 + 공통 현재시각 선
  • place-front/src/pages/reservation/DailyBoardPage.tsx — 날짜 필터 + 현재시각 선 추가

6. (후속 권장) 백엔드 ​

프론트 필터로 증상은 해결되지만, findAllReserveAtDate 가 4일치를 내려주는 건 별도 이슈다. 하루치만 필요하다면 date 당일 범위로 좁히는 편이 트래픽·혼선 모두에 낫다. (이번 변경 범위 밖)