Blog Park - 활동 로그 켈린더

박상준

2024년 10월 30일

0

Blog Park
Next.js
캘린더

활동 로그를 왜 만들기로 했을까

내가 만들고자하는 목표는 깃헙의 활동 로그이다. 깃허브캘린더 내가 어느 날짜에 어떤 활동을 했는지 한눈에 확인도 가능하고 그걸 통해 내가 얼마나 활발하게 코딩을 하고있는지 확인하는 것이다. 이런 점에서 기존에 사용하던 블로그는 한눈에 확인이 어렵다. 물론 작성한 글 갯수를 보면 꾸준하다는 것을 알긴 알지만 요약하는 게 있으면 좋겠다는 내 생각이다.

그래서 나도 형식은 비슷하게 가져갈 것이다. 그리고 내가 추가할 정보들은

  • 작성한 글
  • 댓글
  • 좋아요
  • 커밋

이렇게 4가지 정보를 담을 것이다. 나는 Oauth로 깃헙 로그인도 지원하기 때문에 깃허브 레포와 커밋들을 가져와서 한번에 보여주면 좋을 것 같다.

캘린더 구현

캘린더는 직접 만들어볼 것이다. 기존에 있는 캘린더 라이브러리를 사용해도 되겠지만...그래도 직접 구현해야 내가 원하는 입맛대로 수정이 가능해진다. 우선 캘린더를 만들기 전에 필요한 값들이 필요하다.

  • 해당 연도
  • 해당 연도 일수
  • 해당 연도 1월 1일 요일

나는 깃헙의 캘린더처럼 1년 일수 전부를 보여줄 예정이기 때문에 전체 일수가 필요하다. 365일이 고정이면 좋겠지만 올해는 366일인것처럼 윤년을 적용해야하기에 일수를 따로 찾아줘야한다. 그리고 1월 1일의 요일이 필요한 이유는 1월 1일의 요일을 알아야 일수를 세팅할 수가 있다.

전체 일수 구하기

가장 먼저 해당 연도를 도출해보겠다. 간단하게

  const currentYear = new Date().getFullYear();

이제 현재 연도를 가지고 일수를 구해보겠다.

export const getDayInYear = (year: number) => {
  const firstDay = Number(new Date(year, 0, 1));
  const secondeDay = Number(new Date(year + 1, 0, 1));
  const dayInYear = (secondeDay - firstDay) / (1000 * 60 * 60 * 24);
  return dayInYear;
};

연도를 파라미터로 받아서 연도의 1월 1일과 다음 연도의 1월 1일을 구한다. 그리고 이 두개의 날짜를 비교한 시간을 하루로 변환해주면 된다. 그러면 올해 기준으로 366일이 나온다.

1월 1일 요일 구하기

아주 간단하게 요일을 구할수가 있다.

export const getFirstDay = (year: number) => {
  const firstDay = new Date(year, 0, 1);
  return firstDay.getDay();
};

연도를 넣고 1월 1일로 날짜를 생성후, 해당 날짜에 getDay()를 하면 요일 인덱스가 나온다. 2024년 1월 1일은 월요일로 해당 로직을 통해 리턴되는 값은 1이다.(일요일을 시작으로 0부터 6까지 인덱스로 요일이 표시된다.)

캘린더 만들어보기

이제 캘린더를 직접 만들어 보겠다. 일주일씩 끊어서 보여줄 예정이라 grid를 사용해서 표시해주겠다.

<div className='grid grid-flow-col grid-rows-7 gap-1'>
...
</div>

이제 세로 7칸의 그리드가 만들어졌고 위에서 만들어진 값을 기반으로 캘린더를 구현해주면 된다.

가장 먼저 1월 1일을 적용해주도록 하겠다.

{Array.from({ length: firstDayIndex }).map((_, index) => (
  <div key={index} className='w-3 h-3' />
))}

1월 1일이 월요일이기 때문에 gird를 통해 캘린더를 만들때 일요일인 첫번째 grid는 비우고 시작해야한다. 그래서 빈 칸을 만들어서 배열 앞에 우선적으로 렌더링해준다. Array.from({ length: number })는 length로 지정한 길이만큼의 배열을 생성해주는 메소드이다. 그래서 위에서 만든 getFirstDay의 결과값인 1을 활용해 길이 1의 빈칸 배열을 만들고, 캘린더 앞에 배치해 월요일부터 캘린더가 시작되도록 구현해줬다.

다음으로 전체 일수에 대한 칸을 구현해준다.

{Array.from({ length: totalDay }, (_, index) => {
  // 위에서 만들어진 객체에서 같은 날짜에 있는 프로퍼티값을 props로 전달
  const day = index + 1;

  return (
    <CalendarSingleDay
      key={day}
      day={day}
      year={currentYear}
    />
  );
})}

우선 캘린더의 각 칸을 클릭할 경우 확인해야하는 것은 날짜 정보이다. 날짜는 현재 인덱스로 만들어진 배열에 1을 더한 값이기 때문에 1을 더하면 바로 몇번째 날인지 알수 있다.

이제 이렇게 생성한 날짜를

export const getDateFromDay = (year: number, day: number) => {
  const date = new Date(year, 0);
  date.setDate(day);
  return date;
};

해당 연도의 몇번째 날인지 setDate를 통해 Date형식으로 변환시켜준다. 그리고 date-fns를 활용해 내가 원하는 포멧으로 바꿔준다. 캘린더 이미지 확인해보면 월요일부터 시작하는 캘린더가 구현되었고, 로그 이미지 각 칸을 클릭시 해당 날짜와 정보들이 표시된다.

마무리

date 메소드를 최대한 활용해서 로직을 작성해봤다. 나도 사용하면서 이렇게 많은 함수들이 있었다는 것을 다시 알게 되었고 어떻게 활용하면 좋은지 고민하는 시간이였다. 이제 로그를 어떻게 보여줄 것인지 고민해보고 적용해보겠다.

개의 댓글