모도리는 공부중

달력 라이브러리 비교 테스트 결과 본문

내 지식 정리/날것 그 자체

달력 라이브러리 비교 테스트 결과

공부하는 모도리 2025. 3. 13. 16:54
728x90
반응형

 

최종 선택: air date picker

 

🚀 1. Flatpickr

 

✅ 첫 번째로 테스트
문제점:

  • range: true 설정 시 하루만 선택하면 endDate 자동 설정이 안됨
  • UI 커스텀 및 크기 조절이 어려움
  • 기능적으로 부족하다고 판단해서 포기

🛑 화남 포인트:
👉 "하루만 선택하면 endDate 자동 설정 안 되는 것"

 

🚀 2. Air Datepicker (1차 시도)

UI가 가장 마음에 들었음
문제점:

  • range: true에서 하루만 선택하면 자동으로 EndDate 채우는 기능이 안됨
  • 같은 날짜를 두 번 선택하면 선택이 취소됨 (불편)
  • 크기 조절이 자유롭지 않음

🛑 화남 포인트:
👉 "하루만 선택 시 EndDate 자동 설정 안 됨 & 같은 날짜 두 번 클릭하면 선택 취소됨"
👉 "UI는 맘에 드는데 기능적으로 부족해서 고민"

➡ 이때 대체 가능성 찾으려고 다른 라이브러리 테스트하러 떠남

 

🚀 3. Date Range Picker

기능적으로 가장 마음에 들었음

  • range: true에서 하루만 선택하면 endDate 자동 채우기 지원됨
  • 기본 날짜 설정 문제없이 가능
    문제점:
  • UI가 기대만큼 깔끔하지 않음
  • 크기 조절이 어렵고 스타일링이 제한적임

🛑 화남 포인트:
👉 "UI가 별로다. 크기 조절도 어렵다."
👉 "Air Datepicker가 더 예쁘긴 한데.. 기능은 이게 더 좋다."

➡ 최종 선택을 위해 다른 라이브러리 더 찾아보기로 결정

 

 

🚀 4. Material Datepicker

포기 이유:

  • 완전히 새로운 방식이라 기존 코드와 통합 어려움
  • UI 커스텀이 어렵고, Tailwind + Jinja2 환경에서 적용 난항

🛑 화남 포인트:
👉 "이건 내가 원하던 방식이 아냐. 그냥 포기하자."

➡ 다음 후보 라이브러리로 이동

 

🚀 5. Litepicker

포기 이유:

  • range: true 설정 시 하루만 선택하면 endDate 자동 설정 안됨
  • 스타일이 깔끔하지 않음

🛑 화남 포인트:
👉 "이건 뭘 해도 마음에 안 드는데?"

➡ 이 시점에서 다시 UI와 기능을 모두 만족하는 라이브러리 찾으려 고민

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Litepicker 테스트 (완벽 정렬)</title>
    <script src="https://cdn.jsdelivr.net/npm/litepicker/dist/litepicker.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/litepicker/dist/css/litepicker.css">
    
    <style>
        /* 📌 Litepicker 전체 크기 조정 */
        :root {
            --litepicker-day-width: 62px !important; /* 날짜 크기 증가 */
            --litepicker-month-width: calc(var(--litepicker-day-width) * 7) !important;
        }

        /* 📌 캘린더 컨테이너 */
        .litepicker {
            font-size: 24px !important;
            width: 470px !important;
            max-width: 470px !important;
        }

        .litepicker .container__main {
            width: 484px !important;  /* 전체 컨테이너 크기 고정 */
        }
        
        .litepicker .container__months {
            width: 100% !important; /* 부모 컨테이너에 맞춤 */
        }

        /* 📌 월/년 표기 */
        .litepicker .month-item-header {
            font-size: 24px !important;
            font-weight: bold !important;
            padding: 12px 0 !important;
            text-align: center !important;
            width: 100% !important; /* 📌 너비 강제 조정 */
        }
        .litepicker .month-item-header {
            width: 100% !important;
            display: flex;
            align-items: center;
            justify-content: center;  /* 월 텍스트 중앙 정렬 */
            padding: 10px 0; /* 위아래 여백 조정 */
        }
        .litepicker .month-item-header button {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
        }
        .litepicker .month-item-header .button-previous-month {
            left: 10px;  /* 왼쪽 버튼 위치 조정 */
        }
        
        .litepicker .month-item-header .button-next-month {
            right: 10px;  /* 오른쪽 버튼 위치 조정 */
        }

        /* 📌 요일 행 */
        .litepicker .month-item-weekdays-row {
            display: grid !important;
            grid-template-columns: repeat(7, 1fr) !important;
            text-align: center !important;
            width: 100% !important;
            font-size: 20px !important;
            font-weight: bold;
            padding-bottom: 10px;
            gap: 6px !important; /* 📌 간격 맞추기 */
        }

        /* 📌 날짜 컨테이너 */
        .litepicker .container__days {
            display: grid !important;
            /* grid-template-columns: repeat(7, 1fr) !important; */
            grid-template-columns: repeat(7, auto) !important;
            /* gap: 6px !important;
            width: 100% !important; */
            justify-content: center !important;
        }

        /* 📌 날짜 크기 조정 */
        .litepicker .day-item {
            /*width: 62px !important;*/
            width: calc((var(--litepicker-month-width) + 50px) / 7) !important;
            height: 62px !important;
            line-height: 62px !important;
            text-align: center !important;
            font-size: 20px !important;
            font-weight: bold;
            border-radius: 6px !important;
        }


        /* 📌 이전/다음 달 버튼 크기 */
        .litepicker .month-item-header span {
            width: 35px !important;
            height: 35px !important;
            font-size: 26px !important;
        }

        /* 📌 선택된 날짜 스타일 */
        .litepicker .day-item.is-start-date,
        .litepicker .day-item.is-end-date {
            background-color: #007bff !important;
            color: white !important;
        }

        .litepicker .day-item.is-in-range {
            background-color: #cce5ff !important;
            color: black !important;
        }

        /* 📌 입력 필드 스타일 */
        input {
            font-size: 20px;
            padding: 12px;
            width: 300px;
            text-align: center;
            border: 1px solid #ccc;
            border-radius: 6px;
        }

        .litepicker .container__months .month-item-header,
        .litepicker .container__months .month-item-weekdays-row,
        .litepicker .container__days {
            width: calc(var(--litepicker-month-width) + 50px) !important;
        }

    </style>
</head>
<body>

    <h3>📅 Single Date Picker (완벽 정렬)</h3>
    <input type="text" id="single-datepicker" placeholder="날짜 선택">

    <h3>📅 Range Date Picker (완벽 정렬)</h3>
    <input type="text" id="range-datepicker" placeholder="기간 선택">

    <script>
        // 📌 Single Date Picker
        new Litepicker({
            element: document.getElementById('single-datepicker'),
            format: 'YYYY-MM-DD',
            lang: 'ko',
            autoApply: true,
            singleMode: true,
            numberOfMonths: 1,  // 한 개의 달만 표시
            splitView: false,  // 📌 두 개의 달력이 표시되지 않도록 강제 설정
        });

        // 📌 Range Date Picker
        new Litepicker({
            element: document.getElementById('range-datepicker'),
            format: 'YYYY-MM-DD',
            lang: 'ko',
            autoApply: true,
            singleMode: false,
            numberOfMonths: 1,  // 한 개의 달만 표시
            splitView: false,  // 📌 두 개의 달력이 표시되지 않도록 강제 설정
        });
    </script>

</body>
</html>

 

🚀 6. Pikaday

✅ 테스트 진행
문제점:

  • UI 크기 조절 가능하지만, 글씨 크기 조절이 제대로 안 됨
  • range: true 기능이 기본 제공되지 않아서 별도로 구현 필요

🛑 화남 포인트:
👉 "이건 내가 직접 range 기능 추가해야 하는데.. 너무 번거로워!"
👉 "패스. 다른 거 해보자."


🚀 7. 다시 Air Datepicker 재도전 (2차 시도)

✅ 다시 시도한 이유:

  • UI가 가장 마음에 들었기 때문
  • "하루만 선택하면 EndDate 자동 채우기 기능 추가해보자"

✅ 해결 과정:

  1. onSelect에서 선택된 날짜 확인 & 자동 채우기 로직 추가
  2. onHide 이벤트에서 EndDate 자동 설정 시도
  3. setDate 함수가 존재하지 않아서 여러 번 오류 발생
  4. selectedDates 전역 변수로 관리하여 해결 시도
  5. update() 메서드를 사용하여 해결 완료 🎉

🎯 최종 해결됨!!

  • range: true에서 하루만 선택하면 자동으로 endDate도 채워짐
  • UI는 그대로 유지
  • 이제 원하는 기능 + 예쁜 UI + 크기 조절 가능까지 만족

성공!! 🚀🎉


📌 최종 결론

  • Flatpickr, Litepicker, Pikaday, Material Datepicker → 다 포기
  • Date Range Picker는 기능적으로 좋지만, UI가 별로라 패스
  • Air Datepicker로 돌아와서 기능 직접 수정하여 해결

🔥 그래서 결국 Air Datepicker로 원하는 기능을 완벽하게 구현 성공!! 🎉🎉

 

 

728x90
반응형
Comments