ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] 일반적인 달력 만들기 - 날짜 가져오기
    만학도 프로젝트/JavaScript Calendar 2020. 8. 5. 01:03

    HTML 뼈대를 잘 잡았으니, 이제 우리가 필요한 날짜 데이터를 만들어 봅시다.

    날짜 데이터니깐 Date객체를 활용해야 되겠죠?

    const date = new Date();
    
    const viewYear = date.getFullYear();
    const viewMonth = date.getMonth();

    그리고 년도와 월은 중간중간에 몇 번 더 사용해야 돼서 메서드를 자꾸 호출하는 것보다는 미리 값을 가지고 있는 게 더 좋을 것 같다는 생각에 변수 두 개를 따로 만들어 줬습니다.

     

    성능에는 큰 영향은 없을 것 같긴 하지만, 필요한 부분에 메서드를 호출하는 것 보다는 이렇게 호출된 값을 미리 만들어 두고 사용하는 게 가독성 측면에서 좀 더 좋은 것 같아서 이렇게 작성해 봤습니다.

    혹시나 이 부분에 데해서 좋은 의견이 있으신 분은 댓글 달아주시면 좋을 것 같습니다 :)

     

    자, 아무튼 이렇게 date 정보가 정리가 되면, 꽤 간단하게 '.year-month' 부분의 내용은 채워줄 수 있습니다.

    document.querySelector('.year-month').textContent = `${viewYear}년 ${viewMonth + 1}월`;

    querySelector를 통해서 year-month 태그에 접근해서, 여기에 맞는 연도와 월을 넣어주는 것이죠.

    그러면 이렇게 버튼 위에 년도와 월이 잘 들어간걸 확인할 수가 있습니다.

    이 정도면 이제 날짜만 출력하면 되니깐 거의 다 한 것 같지만 아직 할 일들이 꽤 남아있는데요.

    단순하게 이번달 날짜만 표현하고자 한다면 상대적으로 더 간단하게 해결할 수 있을지도 모르겠지만,

    지난달 날짜와, 다음 달 날짜가 부분적으로 표시되어야 합니다.

    이 부분 말이죠.

    그러려면 일단 몇 가지 알아내야 할 것들이 있는데요

    1. 지난 달 마지막 날짜와 요일

    2. 이번 달 마지막 날짜와 요일입니다.

     

    왜냐하면 매월마다 마지막 날짜의 수가 31일인 경우도 있고 30일인 경우도 있고 2월에는 또 다르죠?

    그래서 1번 정보를 통해서 지난 달 날짜 며칠을 몇 개를 그려내야 될지 결정하고

    2번 정보를 통해서 다음 달 날짜 며칠, 몇 개를 그려내야 될지를 결정해 볼까 하는 겁니다 :)

     

    자, 그럼 코드를 작성해야 하는데요.

    새로운 Date객체를 생성할 때, 파라미터 date에 해당하는 부분에 0을 전달하게 되면, 지난달의 마지막 날의 Date 객체가 생성됩니다.

    같은 원리로 파라미터 다음 달의 0번째 날을 뽑으면, 이번 달의 마지막 날 Date객체가 생성되겠죠?

    const prevLast = new Date(viewYear, viewMonth, 0);
    const thisLast = new Date(viewYear, viewMonth + 1, 0);
    
    const PLDate = prevLast.getDate();
    const PLDay = prevLast.getDay();
    
    const TLDate = thisLast.getDate();
    const TLDay = thisLast.getDay();

    이렇게 코드를 작성하면 방금 필요했던 지난달 마지막 날짜(PLDate)와 요일(PLDay), 그리고 이번 달 마지막 날짜(TLDate)와 요일(TLDay)가 완성되는 것이죠!

     

    그러면 이제 이 데이터를 가지고 전체 달력에 필요한 날짜들을 만들어줄 필요가 있는데요,

    const prevDates = [];
    const thisDates = [...Array(TLDate + 1).keys()].slice(1);
    const nextDates = [];

    이렇게 날짜들은 담아둘 배열을 만들어 줬습니다.

    지난 달 날짜와 다음 달 날짜는 상황에 따라 그릴 수도, 그리지 않을 수도 있기 때문에 일단 초기값은 빈 배열로 두고, 이번 달 날짜는 조금 독특한 방식으로 배열을 생성했는데, 천천히 살펴보면 원리는 다음과 같습니다.

     

    1. Array(n)으로 배열을 만들면 길이가 n인 배열이 생성됩니다. (이때 모든 요소들은 undefined)

    2. 그런데 모든 요소들이 empty 값이기 때문에 keys() 메서드를 활용하면 0부터 n - 1까지의 Array Iterator가 생성되는데,

    3. 전개 구문을 통해서 이 Array Iterator를 배열로 만들어 내면 0부터 n-1까지의 배열을 얻어낼 수가 있습니다.

    4. 그래서 이번 달 마지막 날짜 + 1을 n에 전달해주고

    5. 제일 앞에 있는 0을 없애기 위해서 slice 메서드를 활용한 것이죠.

     

    그러고 나면 이제 prevDates와, nextDates를 채워야 하는데 단순 반복문으로 한 번 채워봅시다.

    if (PLDay !== 6) {
      for (let i = 0; i < PLDay + 1; i++) {
        prevDates.unshift(PLDate - i);
      }
    }
    
    for (let i = 1; i < 7 - TLDay; i++) {
      nextDates.push(i);
    }

    두 개의 반복문을 작성해 봤는데요.

     

    첫 번째는 이전 달을 표현할 날짜들을 생성하는데, 만약 지난달 마지막 요일이 토요일(6)이라면 굳이 그릴 필요 없으니깐 조건문을 먼저 달아줬습니다. 그러고 나서 반복문의 조건 부분은 0부터 시작해서 지난달 마지막 요일이 될 때까지 반복하게 작성했고. 지난달의 마지막 날짜부터  1씩 줄어든 값을 unshift 메서드를 통해 prevDates 배열에 앞쪽으로 계속 채워 넣는 방식입니다.

     

    두 번째는 다음 달을 표현할 날짜들인데 생각보다 간단하게 이번 달 마지막 날짜의 요일을 기준으로 필요한 개수를 파악해서 1부터 1씩 증가시키며 nextDates 배열에 하나씩 채워 넣는 방식입니다.

     

    자, 그럼 이제 3개의 배열이 모두 잘 정리가 된 것 같은데요.

     

    아무튼 이렇게 잘 만들어진 데이터들을 이제 html에 그려내야겠죠?

    const dates = prevDates.concat(thisDates, nextDates);
    
    dates.forEach((date, i) => {
      dates[i] = `<div class="date">${date}</div>`;
    })
    
    document.querySelector('.dates').innerHTML = dates.join('');

    concat 메서드를 통해서 세 배열을 합친 다음에, forEach 메서드로 전체 요소들을 돌면서, html 코드로 데이터를 하나씩 수정해 줍니다.

    그러고 나서 .dates 태그의 innerHTML 프로퍼티에다가, dates 배열에 join 메서드를 호출한 결과를 할당해주면!

    필요한 데이터들이 얼추 잘 정리돼서 나온 것 같죠!?

     

    조금 복잡한 것 같지만 혹시 이보다 더 괜찮은 방법이 있으면 또 댓글로 알려주시면 좋을 것 같습니다 :)

     

    오늘 날짜도 표기하고, 다음 달 이전달 움직이는 것도 해야 되지만, 일단은 지금 이 상태가 너무 못생겼으니깐 다음 포스트에서는 css로 일단 어느 정도 보기 좋게 정리하는 시간을 가져보도록 하겠습니다 :)

    댓글

Designed by BigTop.