[Javascript] 기본 캘린더 구현

2025. 1. 25. 19:58Calender Website

캘린더 웹사이트를 만들기 위해 Javascript로 캘린더를 직접 구현하게 만들었다. 

 

[HTML]

calendar-container에는 그게 유저 정보를 나타내는 user-info와 달력을 표시하는 calendar가 있다.

user-info는 current_user에서 받아와 사용자 프로필을 표시하도록 만들어 주었다.

 

calendar는 calendar-header에 월, 년도를 표시하고 달력을 넘길 수 있는 버튼과, 일정을 추가하는 버튼을 달아주었다.

그리고 실제 달력을 출력하는 calendar-grid는 Javascript에서 구현을 담당한다.

    <div class="calendar-container">
        <div class="user-info">
            <img src="{{ url_for('static', filename='images/profile/woman.png' if user.image_path == ''
                else user.image_path) }}" class="profile-picture">
            <div>
                <p class="user-name">{{ user.username }}</p>
                <p class="description">{{ user.description }}</p>
            </div>
        </div>
        <div class="calendar">
            <div class="calendar-header">
                <button id="currentMonth"></button>
                <div class="calendar-buttons">
                    <button id="prevMonth" class="arrow-button"><img src="{{ url_for('static', filename='images/left-arrow.png') }}" class="arrow-picture"></button>
                    <button id="nextMonth" class="arrow-button"><img src="{{ url_for('static', filename='images/right-arrow.png') }}" class="arrow-picture"></button>
                    <button id="addEventButton">Add</button>
                </div>
            </div>
            <div class="calendar-grid" id="calendarGrid"></div>
        </div>
    </div>

 

[Javascript]

1. Calendar 클래스 정의

constructor를 사용하여 생성자를 정의해주고 init()로 달력을 초기화 해준다.

class Calendar {
    // 생성자
    constructor() { 
        this.date = new Date();
        this.currentMonth = this.date.getMonth();
        this.currentYear = this.date.getFullYear();
        this.days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
        this.events = {};
        this.init();
    }

 

2. Calendar 초기화

이벤트 리스너를 설정하고, 달력을 렌더링한다.

    init() {
        this.setupEventListeners();
        this.render();
    }

 

3. setupEventListeners()

이벤트 리스너를 설정해준다. 

prevMonth 버튼을 클릭하면 전달로 이동, nextMonth 버튼을 클릭하면 다음달로 이동한다.

    setupEventListeners() {
        document.getElementById('prevMonth').addEventListener('click', () => {
            this.currentMonth--;
            if (this.currentMonth < 0) {
                this.currentMonth = 11;
                this.currentYear--;
            }
            this.render();
        });

        document.getElementById('nextMonth').addEventListener('click', () => {
            this.currentMonth++;
            if (this.currentMonth > 11) {
                this.currentMonth = 0;
                this.currentYear++;
            }
            this.render();
        });
    }

 

4. Calendar 랜더링

    render() {
        const grid = document.getElementById('calendarGrid');
        const monthDisplay = document.getElementById('currentMonth');
        
        grid.innerHTML = '';
        
        monthDisplay.textContent = `${this.getMonthName(this.currentMonth)} ${this.currentYear}`;
        
        this.days.forEach(day => {
            const dayHeader = document.createElement('div');
            dayHeader.className = 'day-header';
            dayHeader.textContent = day;
            grid.appendChild(dayHeader);
        });

 

    getMonthName(month) {
        const months = ['January', 'February', 'March', 'April', 'May', 'June',
                      'July', 'August', 'September', 'October', 'November', 'December'];
        return months[month];
    }

 

- 달력 내용을 초기화시킨다.

- Calendar 객체에 현재 월, 년도가 currentMonth, currentYear에 자장되어 있으므로 이를 불러내어 monthDisplay에 표시해준다.

- this.days에서 Sun~Mon을 불러와 div class='day-header'로 설정한 후 textContent를 넣어 grid에 요일 헤더를 추가

 

	const firstDay = new Date(this.currentYear, this.currentMonth, 1);
        const startingDay = firstDay.getDay();
        const lastDay = new Date(this.currentYear, this.currentMonth + 1, 0);
        const totalDays = lastDay.getDate();
        const prevMonthLastDay = new Date(this.currentYear, this.currentMonth, 0).getDate();

 

firstDay 현재 날짜 2025년 2월 1일
startingDay 현재 날짜의 요일 6 (일~토 : 0~6)
lastDay 현재 월의 마지막 날짜 2025년 2월 28일
totalDays 현재 월의 총날짜 28
prevMonthLastDay 전월의 마지막 날짜 2025년 1월 31일

 

        for (let i = startingDay - 1; i >= 0; i--) {
            const prevMonthDate = new Date(this.currentYear, this.currentMonth-1, prevMonthLastDay - i);
            this.createDayCell(prevMonthDate, 'other-month');
        }

 

- i는 startingDay-1부터 0까지 순회 (5 -> 0)

- prevmonthDate는 2025년 1월 26일 ~ 2025년 1월 31일까지 순회

- 해당 날짜에 맞추어 class가 other-month인 cell을 생성

 

        const today = new Date();
        for (let i = 1; i <= totalDays; i++) {
            const currentDate = new Date(this.currentYear, this.currentMonth, i);
            const isToday = i === today.getDate() && 
                          this.currentMonth === today.getMonth() && 
                          this.currentYear === today.getFullYear();
            this.createDayCell(currentDate, isToday ? 'today' : '');
        }

 

- 2025년 2월 1일 ~ 2025년 2월 28일까지 cell을 생성

- 만약 만드는 cell과 현재 날짜가 일치하면 class를 today로 지정

 

        const remainingCells = 42 - (startingDay + totalDays);
        for (let i = 1; i <= remainingCells; i++) {
            const nextMonthDate = new Date(this.currentYear, this.currentMonth+1, i);
            this.createDayCell(nextMonthDate, 'other-month');
        }

 

- 2025년 3월 1일 ~ 2025년 3월 8일

- 42칸 중 남은 칸들을 class가 other-month인 cell로 생성

 

5. createDayCell

    createDayCell(date, className) {     
        const cell = document.createElement('div');
        cell.className = `calendar-cell ${className}`;
        cell.dataset.date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())).toISOString().split('T')[0];

        const dateDiv = document.createElement('div');
        dateDiv.className = 'calendar-date';
        dateDiv.textContent = date.getDate();
        cell.appendChild(dateDiv);

        document.getElementById('calendarGrid').appendChild(cell);
    }

 

- 달력 한칸을 나타내는 cell의 클래스를 지정해준다. (현재 월 -> calendar-cell , 다른 월 -> calendar-cell other-month, 오늘 -> calendar-cell today)

- date는 Date 객체로 이를 문자열로 변환하여 '2025-01-01'을 cell.dataset.date로 설정한다.

- 날짜를 나타내는 dateDiv를 cell에 추가한 다음, cell도 grid에 추가한다.