프론드엔드 시간 예약 블록 색상 버그 분석 & 수정
증상: 프론드엔드 시간 블록 색이 "진행중/예정/종료"로 딱 떨어지지 않고 들쭉날쭉. 같은 오전 시간대 회의인데 어떤 건 초록(예정), 어떤 건 파랑(종료)으로 뒤죽박죽 칠해짐.
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=... 의 구현이 단일 날짜가 아니라 넓은 윈도우를 조회한다.
// 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. 어떻게 고치나 (프론트 전용)
사용자 요구대로 백엔드는 그대로 두고 프론트에서 보여지는 것만 바로잡는다.
- 보드 날짜로 필터링 — 각 뷰에서
startTime의 날짜(YYYY-MM-DD)가 선택된 보드 날짜와 같은 예약만 그린다. 이걸로 다른 날짜 블록이 섞이는 문제가 사라지고, 위치와 색의 기준이 일치한다. - 상태 판정을 배치와 동일한 '벽시계' 기준으로 —
getMeetingStatus가 오프셋(+09:00/Z)에 휘둘리지 않도록, 블록 배치와 똑같이 ISO의 날짜+시:분을 로컬 벽시계로 읽어 현재 시각과 비교한다. 포맷이 어떻게 오든 "화면에 보이는 시각" 기준으로 색이 정해진다. - 현재시각 선 공통화 —
index.css에--color-now토큰과.now-line(+-vertical/-horizontal) 클래스를 선언하고 세 뷰가 같은 색·두께를 쓰게 한다. 빠져 있던DailyBoardPage에도 추가.
4. 상태 정의 (확정)
| 상태 | 조건 | 색(토큰) |
|---|---|---|
예정 upcoming | now < start | 연초록 (--color-meeting-upcoming*) |
진행중 ongoing | start ≤ now < end | 주황 (--color-meeting-ongoing*) |
종료 ended | now ≥ 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 당일 범위로 좁히는 편이 트래픽·혼선 모두에 낫다. (이번 변경 범위 밖)