728x90

[JavaScript] 캘린더 만들기 - 한 주 구하기

자바스크립트

얼마 전, 사이드 프로젝트를 진행하면서 달력이 필요한 적이 있었습니다. 기존의 캘린더 라이브러리의 경우 커스텀이 어렵고, 원하지 않는 기능까지 포함하고 있어서 간단하고 커스텀에도 용이한 달력을 직접 만들게 되었습니다.

이번 포스팅에서는 프로젟트를 진행하면서 만들었던 달력의 핵심 기능에 대해서 정리 후, 공유해보려 합니다. typscript를 이용해 작업했으며, arrow function 등과 같은 es6 문법을 사용했으며. date-fns 라이브러리를 사용해 Date를 관리하고 있습니다.

달력을 커스텀해서 작업해야 하는 분들에게 도움이 되었으면 합니다.

완성된 캘린더의 모습

달력의 구조

달력의 가장 기본적인 형태는 한 달의 전체 일자를 표시하며, 한 달은 대게 5주~6주로 나타낼 수 있습니다. 또한, 매월 시작 날짜와 종료 날짜가 달라지므로, 이번 달의 시작 날짜와 종료 날짜를 구해야 합니다. 시작 날짜와 종료 날짜를 구했다면, 이번 달력의 빈 칸에 지난 달과 다음 달의 데이터를 채워 넣기 위해 이 데이터를 구해야 합니다.

한 주 구하기

date-fns 라이브러리를 이용하면 날짜에 대한 기본적인 연산을 모두 이용할 수 있습니다.

필요한 상수 값

const DATE_WEEK_LENGTH = 7;
const TODAY = new Date();

TODAY 상수는 생성한 데이터 중 오늘이 포함되어 있는지 확인하기 위함입니다.

generateOneWeek

const generateOneWeek = (dateStart: Date, monthStart: Date) => {
  const daysOfWeek = [];
  let currentDay = dateStart;

  for (let i = 0; i < DATE_WEEK_LENGTH; i++) {
    daysOfWeek.push({
      currentDay,
      formattedDate: format(currentDay, 'd'),
      isToday: isSameDay(currentDay, TODAY),
      isCurrMonth: isSameMonth(currentDay, monthStart),
    });

    currentDay = addDays(currentDay, 1);
  }

  return daysOfWeek;
};

위 코드에서 사용된 format, addDays, isSameDay, isSameMonth 함수가 모두 date-fns 에서 제공하는 함수입니다. 복잡한 Date 객체의 연산에 대한 함수를 미리 정의해주고 있어서 보다 쉽게 개발을 진행할 수 있습니다.

결과

위 코드를 실행했을 때의 결과는 다음과 같습니다

const currentDate = new Date('2020.12.01');
const const monthStart = startOfMonth(currentDate);

generateOneWeek(currentDate, monthStart);
[
  {
    currentDay: 2020-12-01T00:00:00.000Z,
    formattedDate: '1',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-02T00:00:00.000Z,
    formattedDate: '2',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-03T00:00:00.000Z,
    formattedDate: '3',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-04T00:00:00.000Z,
    formattedDate: '4',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-05T00:00:00.000Z,
    formattedDate: '5',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-06T00:00:00.000Z,
    formattedDate: '6',
    isToday: false,
    isCurrMonth: true
  },
  {
    currentDay: 2020-12-07T00:00:00.000Z,
    formattedDate: '7',
    isToday: false,
    isCurrMonth: true
  }
]

startOfWeek

2020년 12월 달력을 보면 첫 째주는 11월 29일에서 시작함을 알 수 있습니다. 이것은 date-fnsstartOfWeek를 이용해 구현할 수 있습니다.

const currentDate = new Date('2020.12.01');
const startDate = startOfWeek(currentDate);
const monthStart = startOfMonth(currentDate);
const oneWeek = generateOneWeek(startDate, monthStart);

위와 같이 작성하면 29일부터 5일까지 반환하는데, 이는 2020년의 12월 첫 째주 달력과 동일합니다.

위와 같은 방식을 이용해 한 달의 데이터를 생성한 뒤, 생성한 데이터에 UI를 입혀서 캘린더를 작성할 수 있습니다.

728x90
728x90