3 분 소요

allDay 플래그 하나로 갈리는 캘린더 이벤트 렌더링 분기

설계 노트 — 캘린더 이벤트 시작시간 표기 및 멀티데이 “(전체 N일)” 표기

배경

캘린더(월/주/일 뷰)의 이벤트 표시 방식을 개선하기로 했다. 개선 항목은 세 가지다.

  1. 월뷰 이벤트 title 앞에 시작시간을 표기한다.
  2. 주뷰(및 일뷰) 종일줄에서 여러 날에 걸친 이벤트는 title 옆에 “(전체 N일)”을 표기한다.
  3. 월뷰에서 종료시간이 있는(하루종일이 아닌) 이벤트가 여러 날에 걸쳐 “긴 바” 형태로 표시될 때, 디자인을 종일뷰 이벤트와 동일하게(호버 효과 제외) 바꾼다.

현재 구조 확인

  • 이벤트 생성 로직이 각 일정에 allDay, start_time, end_time, start_date, end_date 등을 계산해 담고, 캘린더 컴포넌트가 이를 그대로 FullCalendar의 events prop에 넘긴다. title/start/end/allDay 외 필드는 FullCalendar가 자동으로 event.extendedProps에 담아준다.
  • 이벤트 콘텐츠 렌더링은 캘린더 컴포넌트의 커스텀 이벤트 콘텐츠 함수 한 곳에서 처리한다.
    • 주뷰/일뷰의 timeGrid에서 !allDay(시간이 있는 이벤트)인 경우: 전용 분기를 탄다.
    • 그 외 모든 경우(월뷰 전체 + 주/일뷰 종일줄): 공용 fallback 분기(title만 렌더링)를 탄다.
    • 즉 fallback 분기에서 !event.allDay이면 항상 “월뷰(단일일자 또는 멀티데이 바)”이고, event.allDay이면 항상 “주/일뷰의 종일줄 또는 월뷰의 all-day 이벤트”다. 뷰 타입을 별도로 검사하지 않아도 allDay 플래그만으로 대상이 정확히 갈린다.
  • 주/일뷰 종일줄 이벤트는 이미 전용 스타일(가운데정렬, 스트라이프 없음, 둥근모서리, inset box-shadow, hover 시 배경색 변경)을 갖고 있는데, 이 스타일이 각 뷰별로 스타일시트에 중복 정의되어 있다. 반면 월뷰 이벤트는 좌측 스트라이프가 있는 별도 스타일 하나만 존재하며, all-day/timed/단일/멀티 구분 없이 전부 동일한 스타일을 공유한다.
  • 이벤트가 종일 이벤트인지 판단하는 로직은 시작시각이 자정이 아니면 무조건 “시간 있는 이벤트”로 판단한다. 따라서 allDay=false인 이벤트는 항상 “실제로 의미 있는 시작시각”을 가진다(우연히 00:00:00인 극단적 케이스가 있어도, allDay=false이면 시간 표기 규칙을 그대로 적용한다).

결정된 규칙

1) 월뷰 시작시간 표기

fallback 분기에서 !event.allDay일 때, 시작시각 문자열(“HH:mm:ss.SSS”)을 앞 5글자(HH:mm)만 잘라 title 앞에 붙인다. 판단 기준은 allDay 플래그뿐이다(개별 시각 문자열이 우연히 “00:00”이어도 allDay=false면 표기한다). 단일일자 이벤트와 멀티데이 바 이벤트에 동일하게 적용되므로 별도 분기가 필요 없다.

2) “(전체 N일)” 표기

같은 fallback 분기에서, FullCalendar가 넘겨주는 event.start/event.end(end는 exclusive)로 전체 일수를 계산한다.

totalDays = Math.round((end - start) / 86400000)

totalDays > 1이면 title 뒤에 (전체 N일)을 이어붙인다. title과 동일한 엘리먼트/스타일을 그대로 사용하므로(문자열만 이어붙임) 별도 CSS가 필요 없다.

적용 대상은 “여러 날에 걸치는 모든 이벤트”로 일관되게 정했다: 주뷰 종일줄(원 요청), 일뷰 종일줄, 월뷰의 기존 all-day 멀티데이 바, 그리고 월뷰의 새로 디자인이 바뀌는 timed 멀티데이 바(3번 항목)까지 전부 포함한다. 월뷰 all-day 바의 기존 디자인(좌측 스트라이프)은 변경하지 않고 텍스트만 추가된다.

3) 월뷰 timed 멀티데이 바 디자인 변경

적용 대상은 월뷰이면서 !event.allDay이고 totalDays > 1인 이벤트만이다. 기존 all-day 멀티데이 바(월뷰)는 지금의 좌측 스트라이프 디자인을 그대로 유지한다.

  • 이벤트 클래스명을 결정하는 콜백에 위 조건을 추가해 새 클래스를 부여한다.
  • 스타일시트에 해당 클래스 전용 규칙을 추가한다. 주/일뷰 종일줄 스타일(가운데정렬, 스트라이프 없음, 둥근모서리, inset box-shadow)을 그대로 재사용하되, hover 시 배경색/box-shadow가 바뀌는 규칙은 포함하지 않는다(“hover 기능 제외” 요구사항).
  • 시간 표기(1번)와 “(전체 N일)” 표기(2번)는 별도 구현 없이 동일 fallback 분기 로직이 그대로 적용된다.

영향 범위 (Blast Radius)

  • 캘린더 컴포넌트
    • 커스텀 이벤트 콘텐츠 함수: fallback 분기 로직 추가(시간 prefix, 일수 suffix)
    • 이벤트 클래스명 콜백: 월뷰 timed 멀티데이 바 전용 클래스 추가
  • 캘린더 스타일시트
    • 새 클래스용 규칙 추가(주/일뷰 종일줄 스타일 재사용, hover 제외)
    • 주의: 리스트뷰의 “오늘” 행 관련 스타일 블록은 수동 관리 중이므로 건드리지 않는다
  • 이벤트 데이터 생성 로직: 수정 불필요(필요한 데이터는 이미 충분함)

Non-goals

  • 리스트/agenda 뷰의 표기 방식((dayIndex/totalDays일) 형식)은 이번 변경 대상이 아니다. 별개 뷰, 별개 포맷이며 그대로 둔다.
  • 이벤트 드래그/리사이즈 등 상호작용 로직은 변경하지 않는다(디자인만 변경, “hover 기능 제외”는 시각 효과 제거를 의미하며 드래그/리사이즈 가능 여부 자체는 건드리지 않는다).
  • 종일 이벤트 판단 로직 등 이벤트 데이터 생성 로직은 변경하지 않는다.

테스트 시나리오

  1. 월뷰 단일일자 이벤트(시작 09:00): title 앞에 “09:00 “ 표기
  2. 월뷰 단일일자 종일 이벤트(allDay=true): 시간 표기 없음(기존과 동일)
  3. 월뷰 멀티데이 all-day 바(예: 3일): 좌측 스트라이프 디자인 유지, title 뒤에 “(전체 3일)” 추가
  4. 월뷰 멀티데이 timed 바(시작 09:00, 여러 날): 종일뷰와 동일한 가운데정렬/스트라이프없음 디자인 + 호버 효과 없음 + “09:00 “ 접두 + “(전체 N일)” 접미
  5. 주뷰 종일줄, 여러 날짜에 걸친 이벤트: title 뒤에 “(전체 N일)” 표기, 디자인은 기존 그대로
  6. 주뷰 종일줄, 단일일자 이벤트: 일수 표기 없음(기존과 동일)
  7. 일뷰 종일줄, 여러 날짜에 걸친 이벤트: 5번과 동일하게 “(전체 N일)” 표기
  8. 주/일뷰의 시간 있는(timed, 종일줄 아님) 이벤트: 이번 변경으로 영향받지 않음(기존 timed 이벤트 분기 그대로)

댓글남기기