컴포넌트
DatePicker (날짜선택)
VanillaFront
2026. 9. 10. 15:37
Va.DatePicker — 캘린더 팝업이 있는 날짜 선택 필드
날짜를 입력받는 컴포넌트. 좌측에 날짜 마스킹(YYYY-MM-DD) 입력창, 우측에 캘린더 아이콘이 있고, 아이콘 클릭 또는 Enter 시 월간 캘린더 팝업이 열립니다. ColorPicker와 같은 팝업 패턴을 따르되, 내부에 달력 렌더링 로직이 붙어 있습니다.
- 클래스: Va.DatePicker — va_component.js:6654
- short name: datePicker
- 상속: Va.PureField (Input/Combobox와 형제)
- isContainer: true
- 베이스 CSS: va-input (팝업은 va-menu-pop, 달력은 calendar-inner)
- 소스 크기: 약 566줄

1. 기본 사용
{
tagName: 'datePicker',
value: '20241225', // 저장 값은 YYYYMMDD (구분자 없이)
dateFormat: 'ymd', // 화면 표시 순서
dateSeperator: '-', // 화면 구분자
onSelect: 'onDateSelect'
}
- 화면 표시: 2024-12-25
- 저장 값(getValue()): 20241225
- 필드에 직접 타이핑도 가능 (마스킹 적용)
2. 다른 PureField 계열과의 차이
항목Va.InputVa.ComboboxVa.DatePicker
| 입력 방식 | 자유 텍스트 | 팝업 리스트 | 캘린더 팝업 + 마스킹 타이핑 |
| 팝업 | ✕ | 리스트 | 캘린더 (년/월 이동, 오늘 버튼) |
| 마스킹 | 옵션 | ✕ | 자동 (____-__-__) |
| 저장 값 형식 | 그대로 | 그대로 | YYYYMMDD 8자리 (기본) |
| 화면 표시 순서 | — | — | ymd / mdy / dmy 선택 |
| 최소/최대 날짜 | ✕ | ✕ | min / max |
| 캘린더 아이콘 | ✕ | 화살표(▼) | 캘린더 아이콘 |
한 줄 요약: "화면 표시 포맷과 저장 값 포맷을 분리해서 관리하는 날짜 입력."
3. 주요 속성
날짜 포맷
속성기본값설명
| dateFormat | 'ymd' | 화면 표시 순서 — ymd / mdy / dmy |
| dateSeperator | '-' | 화면 구분자 — -, /, . 등 |
| valueDateFormat | 'ymd' | 저장 값 순서 — 서버 규약에 맞춤 |
| valueDateSeperator | '' | 저장 값 구분자 — 기본 없음 (20241225 형태). '-'면 2024-12-25 |
| masking | 자동 (____-__-__) | dateFormat/dateSeperator에 따라 자동 설정 |
핵심 개념 — 화면 값과 저장 값 분리:
{
tagName: 'datePicker',
dateFormat: 'mdy', // 화면: 12-25-2024
dateSeperator: '-',
valueDateFormat: 'ymd', // 저장: 20241225 (서버가 원하는 형태)
valueDateSeperator: ''
}
미국식 표시(MM-DD-YYYY)로 사용자에게 보여주면서 서버엔 YYYYMMDD로 저장, 같은 컴포넌트로 처리 가능.
범위
속성설명
| min | 최소 선택 가능 날짜 (YYYYMMDD 문자열) |
| max | 최대 선택 가능 날짜 |
팝업
속성기본값설명
| expanded | false | 팝업 초기 상태 |
| popWidth | 260 | 팝업 폭 |
PureField 상속
value, placeholder, readonly, disabled, size, appearance, stopPropagation 등 모두 유효.
4. 날짜 포맷 조합 예시
한국 표준 (기본)
{ tagName: 'datePicker' }
// 화면: 2024-12-25
// 저장: 20241225
미국 표시 + 서버 저장
{
tagName: 'datePicker',
dateFormat: 'mdy',
dateSeperator: '/',
valueDateFormat: 'ymd'
}
// 화면: 12/25/2024
// 저장: 20241225
유럽 표시 + ISO 저장
{
tagName: 'datePicker',
dateFormat: 'dmy',
dateSeperator: '.',
valueDateFormat: 'ymd',
valueDateSeperator: '-'
}
// 화면: 25.12.2024
// 저장: 2024-12-25
범위 제한
{
tagName: 'datePicker',
min: '20240101',
max: '20241231',
value: '20240315'
}
5. 이벤트
이벤트시그니처발생 시점
| select | (component, element, value, evt) | 캘린더에서 날짜 클릭 시. value는 선택된 날짜 |
| beforePop / afterPop / hidePop | 팝업 표시/숨김 | |
| expand / collapse | 팝업 확장/축소 | |
| focus / blur | 표준 (blur 200ms debounce) | |
| change | 필드 값 변경 (직접 타이핑 등) | |
| keydown / keyup | 키 이벤트 |
6. 메서드
값 관리 — 두 벌의 setter/getter
DatePicker는 값 세팅 방식이 두 가지입니다:
메서드설명
| setValue(value) | valueDateFormat 규약을 따르는 값 세팅 (서버에서 받은 값을 세팅할 때) |
| getValue() | valueDateFormat 규약을 따르는 값 반환 (서버로 전송할 때) |
| setRawValue(value) | 항상 YYYYMMDD 원시 값 세팅 (내부용) |
| getRawValue() | 항상 YYYYMMDD 원시 값 반환 (내부용) |
| getDisplay() | 화면에 표시되는 형태 그대로 반환 (dateFormat+dateSeperator 적용) |
동작 흐름:
- setValue('20241225') → valueDateFormat 규약 해석 → 내부 저장은 YYYYMMDD → 화면은 dateFormat/dateSeperator로 변환 표시
- getValue() → 화면 값 파싱 → valueDateFormat/valueDateSeperator에 맞춰 반환
팝업 제어
메서드설명
| showDatePickerPop(evt) | 팝업 강제 열기 |
| hideDatePickerPop() | 팝업 강제 닫기 |
| showPop() | drawCalendar() 호출 (레거시) |
| hidePop() | expanded=false + update() |
| drawCalendar() | 캘린더 렌더링 (내부) |
상태 (PureField 상속)
메서드설명
| setDisabled(bool) / setReadOnly(bool) | 상태 |
| focus() / blur() | 포커스 |
7. 팝업 캘린더 UI
drawCalendar()가 렌더링하는 구성:
- 헤더: 년월 이동 화살표 (buttonLeft, buttonRight), 년/월 표시
- 본문: 7열 × 6행 날짜 그리드 (일 ~ 토)
- "오늘" 버튼: 오늘 날짜로 즉시 세팅
- 선택된 날짜 강조
- min / max 범위 밖 날짜 비활성화
버튼들은 innerComponents에 등록됨: buttonLeft, buttonRight, buttonToday (va_component.js:6661-6662)
8. 내부 구조
<div elname="element" class="va-input [size] [focused]..." tag-name="datePicker" field="true">
<div elname="fieldWrapper" class="field-wrapper">
<input elname="field" type="text" placeholder="____-__-__"
style="border:0px"> ← 마스킹 필드
<div elname="focusLine" class="focus-line"></div>
<div elname="calendarIconWrapper">
<span elname="calendarIcon" class="icon menu ico_calender_ltr">📅</span>
</div>
</div>
<div elname="popDiv" class="menu-button-pop-div">
<div elname="pop" class="va-menu-pop" style="position:absolute; display:none">
<div elname="popInner" class="calendar-inner">
<!-- 년월 헤더 + 날짜 그리드 + 오늘 버튼 -->
</div>
</div>
</div>
</div>
핵심 트릭:
- 팝업이 열릴 때 getHiddenAreaElement()로 이동해 부모 stacking 회피
- 자동 위치 조정 (뷰포트 하단 넘치면 위로 뒤집기)
- 팝업 상태머신 참여 (Va.addAutoHide, Va.hideOtherComponents)
9. 캘린더 아이콘 vs 필드 클릭
- 캘린더 아이콘 클릭 → 팝업 열기
- 필드 클릭 → 필드 포커스 (팝업 안 열림)
- 필드에서 Enter → 팝업 열기
- 필드에 타이핑 → 마스킹된 텍스트로 직접 입력 가능 (2024-12-25)
즉, 캘린더 선택과 키보드 직접 입력을 둘 다 지원합니다.
10. Va.DatePicker vs 관련 컴포넌트
컴포넌트역할
| Va.DatePicker | 단일 날짜 선택 (이 문서) |
| Va.DatePickerField | DatePicker + Field 래퍼 (라벨/검증) |
| Va.YearPicker | 년도만 선택 (바로 위 클래스 va_component.js:6624) |
| Va.MonthPicker | 년-월 선택 |
| Va.DateRangePicker | 시작-종료 날짜 범위 |
| Va.DateTimePicker | 날짜 + 시간 |
| Va.TimePicker | 시간만 |
11. 팝업 상태머신 연동
프레임워크의 공용 팝업 상태머신 참여:
- 다른 팝업(Combobox, ColorPicker 등) 열려 있으면 자동 닫고 표시
- 외부 클릭 시 자동 닫힘
- _hiddenRootElement = this.popElement — hidden area로 이동 가능
CLAUDE.md 6장 "민감 영역"의 팝업 상태머신 사용 컴포넌트 중 하나.
12. 언제 쓰나
DatePicker가 맞을 때
- 생일·계약일·마감일 등 단일 날짜 입력
- 화면 표시 포맷과 서버 저장 포맷이 다를 때
- 캘린더 UI로 시각적으로 날짜 선택하고 싶을 때
- min/max로 날짜 범위 제한
다른 걸 쓸 때
- 라벨 붙은 폼 필드 → Va.DatePickerField
- 년도만 → Va.YearPicker
- 시작-종료 범위 → Va.DateRangePicker
- 날짜+시간 → Va.DateTimePicker
- 시간만 → Va.TimePicker
13. 흔한 조합 예시
// 한국 기본
{ tagName: 'datePicker', value: '20241225' }
// 서버가 하이픈 포함 원할 때
{
tagName: 'datePicker',
valueDateSeperator: '-',
value: '2024-12-25' // → 화면: 2024-12-25, 저장: 2024-12-25
}
// 미국식 표시
{
tagName: 'datePicker',
dateFormat: 'mdy',
dateSeperator: '/',
value: '20241225' // 화면: 12/25/2024
}
// 범위 제한 (올해만)
{
tagName: 'datePicker',
min: '20240101',
max: '20241231'
}
// 슬래시 구분
{
tagName: 'datePicker',
dateSeperator: '/',
value: '20241225' // 화면: 2024/12/25
}
// 오늘 이후만 (예약일)
{
tagName: 'datePicker',
min: new Date().toISOString().slice(0,10).replace(/-/g,'')
}
14. 알아두면 좋을 주의사항
- value는 문자열 — Date 객체가 아니라 '20241225' 같은 문자열. Date 객체를 넘기면 .substring() 호출에서 크래시.
- setValue()가 8자리 이상 요구 — 미만이면 조용히 무시 (va_component.js:7093-7095).
- value.trim() 호출 — setValue(null)은 안 되고 return, setValue('')는 비움 처리. 하지만 숫자 넘기면 크래시.
- dateFormat과 valueDateFormat 혼동 주의 — 화면 vs 저장. 각각의 seperator도 별도.
- getValue()는 항상 문자열 반환 — 빈 값일 땐 ''.
- 마스킹 자동 설정 — dateFormat에 따라 masking이 자동. 사용자가 직접 masking 지정하면 덮어씀.
- ymd가 기본 — 옵션 미지정 시. dateFormat / valueDateFormat 둘 다.
- 필드에 잘못된 날짜 타이핑 가능 — 마스킹은 자릿수만 강제. 2024-99-99 같은 잘못된 날짜도 입력 가능. 검증 별도 필요.
- 팝업 캘린더 언어 — 요일/월 이름이 하드코딩 또는 프레임워크 언어 설정에 의존. 다국어 필요 시 Va.Lang 확인.
- min / max 범위 검사는 팝업 UI에만 적용 — 필드 직접 타이핑으로 범위 밖 값 넣으면 안 막힘. 별도 검증 필요.
- showPop()이 drawCalendar() 호출 — 별칭이 아니라 캘린더 다시 그림. 성능 주의.
- 팝업 상태머신 참여 — 다른 팝업과 자동 상호 배타.
- 가상 스크롤 없음 — 캘린더는 고정 크기.
- 연도 이동 UI 없음(?) — 기본 UI는 월 단위 이동. 년 단위 빠른 이동이 필요하면 YearPicker 조합.
- 한글 요일 표시 — 프로젝트 언어 설정 확인 필요.
- timezone 개념 없음 — 로컬 문자열 처리만. UTC 시각 정확도가 중요하면 별도 처리.