MonthField (년월필드)
Va.MonthField — 라벨 + 년-월 선택 필드
Va.MonthPicker가 순수 년-월 입력이라면, Va.MonthField는 그 위에 라벨·필수 표시·검증 메시지를 얹은 완성 폼 필드입니다. Field 계열 아키텍처 그대로, 내부에 Va.MonthPicker를 소유하는 Composition 구조. DateField·YearField와 같은 형제로, 월간 리포트·월별 필터 폼에 정확히 맞습니다.
- 클래스: Va.MonthField — va_component.js:8743
- short name: monthField
- 상속: Va.Field (다른 Field 형제들과 같음)
- 내부 컴포넌트: Va.MonthPicker 인스턴스 (fieldComponent)
- isContainer: true
- 베이스 CSS: va-field (role="date-field" 자동 부여)

1. 기본 사용
{
tagName: 'monthField',
label: '대상 월',
value: '202412', // YYYYMM 6자리
required: true,
onSelect: 'onMonthChange'
}
라벨 + 검증 + 12개월 격자 팝업이 한 번에 세팅. 저장 값은 6자리 문자열.
2. Field 계열에서의 위치
Va.Field
├─ Va.InputField ← Va.Input
├─ Va.SearchField ← Va.Search
├─ Va.NumberField ← Va.Number
├─ Va.ComboboxField ← Va.Combobox
├─ Va.YearField ← Va.YearPicker (년만)
├─ Va.MonthField ← Va.MonthPicker (년-월) ← 이 문서
├─ Va.DateField ← Va.DatePicker (년-월-일)
├─ Va.DateTimeField ← Va.DateTimePicker (년-월-일 + 시분초)
└─ ...
MonthField의 정체: Field 베이스 + 내부에 Va.MonthPicker 인스턴스.
⚠️ 다른 Field 형제와 함께 "Picker"가 이름에서 생략되는 그룹. 등록명은 monthField.
3. Va.MonthPicker / 다른 Date 계열 Field와의 차이
항목Va.MonthPickerVa.MonthFieldVa.YearFieldVa.DateField
| 라벨 | ✕ | ✓ | ✓ | ✓ |
| 검증 메시지 | ✕ | ✓ | ✓ | ✓ |
| info 툴팁 | ✕ | ✓ | ✓ | ✓ |
| 입력 대상 | 년-월 | 년-월 | 년만 | 년-월-일 |
| 저장 값 길이 | 6자리 | 6자리 | 4자리 | 8자리 |
| 팝업 UI | 12개월 격자 | 12개월 격자 (내부 위임) | 10년 격자 | 일 단위 캘린더 |
| role="date-field" 자동 | ✕ | ✓ | ✓ | ✓ |
| setValue() / getValue() 오버라이드 | 원본 | 부모(Field) 상속 | 없음 (단순 통과) | 있음 (포맷 변환) |
한 줄 요약: "폼 안 라벨 붙은 년-월 필드 — 월간 리포트에 최적."
4. 주요 속성
날짜 포맷
속성기본값설명
| dateFormat | 'ym' | 화면 순서 — ym / my |
| dateSeperator | '-' | 화면 구분자 |
| valueDateFormat | 'ym' | 저장 값 순서 |
| valueDateSeperator | '' | 저장 값 구분자 |
| masking | 자동 (____-__ 또는 __-____) | dateFormat에 따라 자동 |
팝업
속성기본값설명
| popWidth | 240 | 팝업 폭 |
| expanded | false | 초기 상태 |
| min / max | — | properties에 있으나 MonthPicker에서 강제 로직 없음 |
라벨 (Field 상속)
속성설명
| label | 라벨 텍스트 또는 객체 |
| labelPosition | top / bottom / left / right |
| labelWidth | 라벨 폭 |
| noLabel | 라벨 숨김 |
| infoButton | info 아이콘 |
| required | 필수 표시 |
필드 관련 (MonthPicker로 위임)
속성설명
| value | 년-월 값 (YYYYMM 문자열) |
| placeholder | 플레이스홀더 |
| readonly / disabled | 상태 |
| size / appearance / shape | 시각 스타일 |
| textAlign | 정렬 |
| stopPropagation | 이벤트 버블링 |
검증
속성설명
| validation | {state, size, message} |
| validationState | success / warning / error |
| validationMessage | 메시지 |
세부 커스터마이즈 (monthPicker 옵션 키)
{
tagName: 'monthField',
label: '대상 월',
monthPicker: { // ← 내부 MonthPicker에 전달
popWidth: 320
}
}
MonthField는 옵션 키가 정확히 monthPicker — YearField(잘못 남은 monthPicker)와 달리 이건 의도된 매핑입니다.
각 Field 계열 옵션 키:
- InputField → input
- ComboboxField → combobox
- DateField / DateTimeField → datePicker
- YearField → monthPicker (잔재)
- MonthField → monthPicker (정상)
5. 이벤트
MonthPicker의 이벤트를 재발화:
이벤트시그니처발생 시점
| select | (component, element, value, evt) | 팝업에서 월 클릭 시. value는 선택된 값 |
| beforePop / afterPop / hidePop | 팝업 표시/숨김 | |
| expand / collapse | 팝업 확장/축소 | |
| focus / blur | 표준 | |
| change / keydown | Field 표준 |
주목: select 콜백 시그니처에 value 인자가 전달됩니다. DateField는 인자가 짧아 component.getValue()로 조회해야 했지만, MonthField는 직접 받을 수 있어요.
6. 메서드
값 관리 (Field 상속 그대로)
메서드설명
| getValue() | 내부 MonthPicker의 getValue() 위임 (valueDateFormat 규약) |
| setValue(value) | Field 상속 — 포맷 변환은 내부 MonthPicker에 위임 |
주목: MonthField는 setValue() / getValue()를 오버라이드하지 않습니다. DateField·DateTimeField는 자체 재구현했지만, MonthField는 Field 베이스의 것을 그대로 사용 — 값 처리는 전적으로 내부 MonthPicker에 위임됩니다.
상태 (Field 상속)
메서드설명
| setDisabled(bool) / getDisabled() | 비활성화 |
| setReadOnly(bool) / setReadonly(bool) | 읽기 전용 |
| setLabel(label) | 라벨 변경 |
| setPlaceholder(text) | 플레이스홀더 |
| setSize(size) | 크기 |
검증
메서드설명
| setValidation(state, message) | 검증 표시 + aria |
| clearValidation() | 검증 해제 |
포커스
메서드설명
| focus() / blur() | 내부 MonthPicker의 fieldElement에 위임 |
주의: showMonthPickerPop, hideMonthPickerPop, setRawValue, getRawValue 같은 MonthPicker 세부 메서드는 위임 없음. 필요하면 component.fieldComponent.xxx()로 직접.
7. 내부 구조
<div elname="element" class="va-field [vertical|horizontal]"
role="date-field" field="true">
<div elname="inner" class="field-inner">
<div elname="labelDiv" class="label-div">
<label cpname="label">대상 월 <span class="required">*</span></label>
</div>
<div elname="comment" class="field-comment"></div>
<div elname="fieldDiv" class="field-div">
<div cpname="field" class="va-monthpicker"> ← 내부 Va.MonthPicker
<div class="field-wrapper">
<input type="text" placeholder="____-__">
<div class="focus-line"></div>
<div class="calendar-icon-wrapper">
<span class="icon menu ico_calender_ltr">📅</span>
</div>
</div>
<!-- 팝업은 hiddenArea로 이동 -->
</div>
</div>
</div>
<div elname="validationDiv" style="display:none">
<div class="va-validation">...</div>
</div>
</div>
8. 마스킹 이중 설정
DateField와 마찬가지로 생성자에서 마스킹을 두 번 설정합니다:
- option.masking = '____-__'로 초기값 세팅 (va_component.js:8754)
- optionField.masking에 넣어 MonthPicker 생성자로 전달
- MonthPicker 생성 후 this.fieldComponent.setMasking(this.masking) 재호출 (va_component.js:8813)
의도는 dateFormat이 바뀌어도 정확한 마스킹 패턴이 반영되도록 하기 위함.
9. 언제 쓰나
MonthField가 맞을 때
- 폼 안 월별 리포트 필터 — 대상 월 선택
- 월별 예산·매출 등록
- 월간 근태·급여 대상 월
- 분기 통계 (월 선택으로 분기 유추)
- 라벨·필수·검증이 필요한 폼 필드
다른 걸 쓸 때
- 라벨 없이 인라인 → Va.MonthPicker
- 년도만 필요 → Va.YearField
- 년-월-일 필요 → Va.DateField
- 시간까지 → Va.DateTimeField
- 년-월을 두 개 콤보로 → Va.ComboboxField 두 개 조합
- 최근 몇 개월 목록만 → Va.ComboboxField (동적 데이터)
10. 흔한 조합 예시
// 표준
{
tagName: 'monthField',
label: '대상 월',
value: '202412',
required: true
}
// 미국식 표시
{
tagName: 'monthField',
label: 'Month',
dateFormat: 'my',
dateSeperator: '/',
valueDateFormat: 'ym',
value: '202412' // 화면: 12/2024, 저장: 202412
}
// 서버가 하이픈 포함 원할 때
{
tagName: 'monthField',
label: '결산 월',
valueDateSeperator: '-',
value: '2024-12'
}
// 좌측 라벨
{
tagName: 'monthField',
label: '기준 월',
labelPosition: 'left',
labelWidth: 100,
value: '202412'
}
// 오늘 년-월로 초기화
mounted() {
const now = new Date();
const ym = now.getFullYear() +
String(now.getMonth() + 1).padStart(2, '0');
this.getRef('month').setValue(ym);
}
// info 툴팁
{
tagName: 'monthField',
label: '급여 지급 월',
infoButton: {
tooltip: '급여가 지급되는 월을 선택하세요'
}
}
// 검증
{
tagName: 'monthField',
label: '대상 월',
ref: 'month',
required: true,
onSelect: 'onMonthPicked'
}
11. 알아두면 좋을 주의사항
- 컴포넌트명 — monthField (not monthPickerField).
- value는 6자리 문자열 — '202412' 형태. Date 객체 안 됨.
- setValue() / getValue()가 오버라이드되어 있지 않음 — 값 처리는 내부 MonthPicker에 위임. 포맷 변환도 MonthPicker의 것 그대로.
- dateFormat / valueDateFormat 혼동 주의 — 화면 vs 저장.
- 마스킹 자동 — dateFormat에 따라 자동 설정. 사용자 지정 시 덮어씀.
- 필드에 잘못된 값 타이핑 가능 — 마스킹은 자릿수만. 9999-99 같은 값 들어감. 별도 검증 필요.
- 옵션 키 monthPicker — 정확히 이 키. YearField와 동일하지만 YearField는 잔재라 반영 안 됨. MonthField는 정상 반영.
- popWidth 기본 240 — DatePicker(260)보다 작음. 12개월 격자엔 충분.
- min/max 실질 강제 없음 — MonthPicker 자체가 범위 필터 없음.
- 팝업 상태머신 참여 — 다른 팝업과 자동 상호 배타.
- role="date-field" 자동 — Month이지만 role은 date-field. ARIA 힌트.
- 일부 메서드 위임 누락 — showPop/hidePop/setRawValue/getRawValue. fieldComponent로 직접.
- timezone은 KST 기준 — 내부 MonthPicker가 한국 시간대 계산. UTC 정확도 중요하면 확인.
12. 실전 예 — 월별 매출 리포트 (Field 버전)
MonthPicker 편의 예제를 Field로 감싼 버전:
class MonthlySalesReport extends Va.View {
mounted() {
// 지난 달로 초기화
const now = new Date();
now.setMonth(now.getMonth() - 1);
const lastMonth = now.getFullYear() +
String(now.getMonth() + 1).padStart(2, '0');
this.getRef('month').setValue(lastMonth);
this.loadReport(lastMonth);
}
onMonthSelect(field, el, value, evt) {
this.loadReport(value);
}
loadReport(yyyymm) {
if (!yyyymm || yyyymm.length !== 6) {
this.getRef('month').setValidation('error', '월을 선택하세요');
return;
}
this.getRef('month').clearValidation();
SalesService.getMonthly(this, { yyyymm }, (view, ok, res) => {
if (ok) view.getRef('grid').setData(res.data.list);
});
}
config() {
return {
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [
{ tagName: 'h2', innerHTML: '월별 매출 리포트' },
{
tagName: 'div',
layout: 'ds-flex fd-row ai-end gap-s',
tags: [
{
tagName: 'monthField',
ref: 'month',
label: '대상 월',
required: true,
onSelect: 'onMonthSelect',
style: { width: '180px' }
}
]
},
{
tagName: 'grid',
ref: 'grid',
columns: [
{ key: 'day', title: '일', width: 60 },
{ key: 'revenue', title: '매출', fillRatio: 1 },
{ key: 'orders', title: '건수', width: 100 }
]
}
]
}]
};
}
}
MonthPicker 단독 사용과 비교하면 라벨 + 필수 표시 + 검증 메시지가 자동 세팅되어 폼 UX가 자연스럽습니다.
13. monthField vs 다른 Field 선택 기준
상황추천
| 월별 매출·통계 리포트 필터 | monthField |
| 급여 지급 월, 결산 월 | monthField |
| 정확한 날짜(일)까지 필요 | Va.DateField |
| 년도만 (연간 리포트) | Va.YearField |
| 시간까지 필요 | Va.DateTimeField |
| 시작-종료 월 범위 | 두 MonthField 조합 |
| 년/월을 별개 UI로 (드롭다운 두 개) | Va.ComboboxField × 2 |
| 최근 12개월 목록만 선택 | Va.ComboboxField (동적 데이터) |