Input (입력)
Va.Input — 텍스트 입력 필드 (PureField 계열)
가장 기본이 되는 폼 입력 컴포넌트입니다. HTML <input>을 감싸되, PureField 베이스가 제공하는 값 관리·마스킹·이벤트·상태 처리를 그대로 활용하고, Input 자신은 숫자 포맷팅(numberComma) 만 추가로 얹은 얇은 확장입니다.
- 클래스: Va.Input — va_component.js:1165
- short name: input
- 상속: Va.PureField (Component 직속 아님 — Field 계열의 베이스)
- DOM 태그: <input> (기본 type="text")
- isContainer: true
- 베이스 CSS: va-input (+ va-purefield)

1. 기본 사용
{
tagName: 'input',
value: '홍길동',
placeholder: '이름을 입력하세요',
onChange: 'onNameChange'
}
value / placeholder / disabled / readonly 등 흔한 폼 옵션이 모두 PureField 규약을 그대로 따르므로, Input 특유의 API는 사실상 numberComma 하나입니다.
2. PureField 위에서의 위치
VanillaFront의 폼 입력은 두 계층 구조로 되어 있습니다:
Va.Component
└─ Va.PureField ← 값·이벤트·상태 처리 로직 (라벨 없음)
├─ Va.Input ← 텍스트 입력 + 숫자 포맷
├─ Va.Search
├─ Va.Number
├─ Va.Textarea
├─ Va.Combobox / ComboboxRaw / Filterbox
├─ Va.Display
└─ ...
Va.Input은 PureField의 얇은 래퍼로, _beginClassBuild('va-input')으로 CSS 스코프만 확장하고 나머지는 부모에 위임합니다 (va_component.js:1203-1211).
라벨이 필요하면 Va.InputField(별도 클래스)를 사용 — Field 계열은 라벨/require/에러메시지까지 감싸는 컴포넌트입니다.
3. 주요 속성 (Input 자체 + PureField 상속)
Input 전용
속성설명
| numberComma | true로 두면 blur 시 천 단위 콤마 자동 삽입(1234567 → 1,234,567), focus 시 자동 제거. getValue()는 콤마 뺀 Number를 반환 |
PureField 상속 (매우 자주 씀)
속성설명
| value | 필드 값 |
| type | HTML input type — text / password / email / number / tel / url / date 등. 기본 'text' |
| placeholder | 플레이스홀더 |
| name | 폼 name 속성 |
| readonly | 읽기 전용 |
| disabled | 비활성화 |
| required | 필수 표시 |
| autocomplete | HTML autocomplete 속성 |
| textAlign | 텍스트 정렬 (CSS 클래스 `text-align-{left |
| size | 크기 (small/medium/large 등, CSS 클래스로 반영) |
| appearance | 시각 스타일 |
| masking | 마스킹 패턴 — '999-99-9999', 'AAA-000' 같은 포맷 강제 |
| maxLength | 최대 글자 수 (초과 시 keydown이 preventDefault됨) |
| byteMaxLength | true면 maxLength를 바이트 단위로 해석 (한글 3바이트 등, Va.Util.getByteLength) |
| valueType | 값 타입 힌트 |
| autoSetFieldValue | 기본 true. false면 value 세터가 DOM에 반영되지 않음 (수동 제어) |
| stopPropagation | 이벤트 버블링 차단 (기본 true) |
| preventParentFieldEvent | true면 PureField가 걸어두는 표준 이벤트 바인딩을 모두 건너뜀 (다른 컴포넌트가 fieldElement를 감쌀 때) |
4. 마스킹 (masking) — 핵심 기능
Va.Input이 일반 <input>과 가장 크게 다른 지점입니다. 패턴 문자로 입력 형식을 강제합니다.
패턴 문자
문자의미
| 0 | 숫자 자리 |
| A | 문자(알파벳/한글) 자리 |
| _ | 아무 문자 자리 |
| * | 숨김(마스킹) 자리 — focus 시 실값 표시, blur 시 마스킹 |
| 그 외 | 리터럴(구분자) — -, /, (, ) 등 |
사용 예
// 주민등록번호 — 뒷자리 숨김
{ tagName: 'input', masking: '000000-*******', value: '850315-1234567' }
// blur 상태: 850315-*******
// focus 상태: 850315-1234567
// getValue(): '8503151234567' (구분자·마스킹 제거된 원본)
// 전화번호
{ tagName: 'input', masking: '010-0000-0000' }
// 사용자가 숫자만 치면 자동으로 구분자 삽입
// 라이선스 키
{ tagName: 'input', masking: 'AAAA-AAAA-AAAA-AAAA' }
동작 흐름:
- keydown 시 keyDownMasking이 리터럴 문자를 자동으로 삽입/스킵
- getValue()는 리터럴 제거된 순수 값을 반환 (changeUnmaskingValue)
- * 마스킹 자리는 blur 시 별표로 표시, focus 시 실값 표시. 값은 별도로 보존
5. numberComma — 숫자 콤마 포맷
Input이 PureField 위에 추가로 붙인 유일한 로직.
{
tagName: 'input',
numberComma: true,
value: 1234567 // 화면 표시: 1,234,567
}
흐름:
- blur 시 → Va.Util.getNumberFormat(value)로 콤마 삽입
- focus 시 → 콤마 제거 (편집 편의)
- getValue() → Number 타입 반환 (콤마 뺀 뒤 Number(...) 변환)
- setValue() → 자동으로 콤마 포맷 반영
⚠️ 주의: masking과 numberComma는 동시 사용 불가 (둘 다 값 표시를 가로채기 때문). 둘 다 지정하면 순서상 numberComma가 우선 처리됩니다.
6. 이벤트
이벤트시그니처발생 시점
| change | (component, element, evt) | 값 변경 확정 시 (표준 change) |
| focus | (component, element, evt) | 필드 포커스 진입 |
| blur | (component, element, evt) | 필드 포커스 이탈 (200ms debounce) |
| click | (component, element, evt) | 필드 클릭 (포커스 자동 처리 후) |
| keydown | (component, element, keyCode, evt) | 키다운 (마스킹/maxLength 처리 이후) |
| keyup | (component, element, keyCode, evt) | 키업 |
| keypress | (component, element, evt) | 키프레스 |
| contextmenu | (component, element, evt) | 우클릭 |
| mousedown | (component, element, evt) | 마우스 다운 |
⚠️ blur가 200ms debounce됨 (va_component.js:734-744) — 팝업(Combobox 옵션 리스트 등)을 열었다가 클릭하는 짧은 순간에 blur가 튀는 걸 방지하기 위함. 즉 blur가 실제로는 200ms 늦게 도착합니다.
⚠️ Input 자체는 input (문자 입력마다) 이벤트를 dispatch 하지 않습니다 — 실시간 리스닝이 필요하면 keyup을 쓰거나, fieldElement에 직접 addEventListener('input', ...)을 바인딩해야 합니다.
7. 메서드 (PureField 상속)
값 관리
메서드설명
| getValue() | 현재 값 반환 — numberComma면 Number, masking이면 리터럴 제거된 순수값, 아니면 원시 문자열 |
| setValue(value) | 값 설정 (numberComma/masking 자동 포맷 반영) |
상태
메서드설명
| setDisabled(bool) | 비활성화 |
| disable() / enable() | 편의 메서드 |
| getDisabled() | 상태 조회 |
| setReadOnly(bool) / setReadonly(bool) | 읽기 전용 (두 시그니처 모두 지원 — camelCase/lowercase) |
| getReadOnly() | 상태 조회 |
포커스
메서드설명
| focus() | 필드에 포커스 |
| blur() | 필드에서 블러 |
8. 내부 구조
<div elname="element" class="va-input [size] [appearance] [focused] [readonly] [disabled]"
tag-name="input" field="true">
<div elname="fieldWrapper" class="field-wrapper">
<input elname="field" type="text" style="border:0px" ...>
<div elname="focusLine" class="focus-line"></div>
</div>
</div>
핵심 포인트:
- 바깥 <div>가 시각적 focus 표시를 담당 — 실제 <input>은 border:0이고, 부모 wrapper가 .focused 클래스로 border/underline을 표현
- focusLine element — focus 시 강조되는 하단 라인/보더 표현에 쓰이는 별도 요소
- tag-name="input" 속성 — 프레임워크가 필드를 식별하는 데이터 속성
이 구조 때문에 input에 직접 focus 표시를 넣지 말아야 합니다. CLAUDE.md 7장 FAQ의 "input 안에 사각형이 보임" 이슈가 정확히 이 지점 — .field-wrapper input:focus-visible { outline: none }을 넣어야 이중 표시가 안 됨.
9. Va.Input vs Va.InputField vs <input> 직접 사용
항목<input> (HTML)Va.InputVa.InputField
| 값 관리 | 수동 | ✓ | ✓ |
| 마스킹 | ✕ | ✓ | ✓ |
| numberComma | ✕ | ✓ | ✓ |
| 이벤트 시스템 | DOM 표준 | 프레임워크 통합 | 프레임워크 통합 |
| 라벨 | ✕ | ✕ | ✓ (자동 감쌈) |
| required 표시 | ✕ | ✕ | ✓ |
| 에러 메시지 영역 | ✕ | ✕ | ✓ |
| info 툴팁 | ✕ | ✕ | ✓ |
선택 기준:
- 폼 안에서 라벨과 함께 표준 폼 필드로 → Va.InputField
- 툴바·검색바·인라인 편집처럼 라벨 없이 값만 → Va.Input
10. 언제 어떤 옵션을 쓰나
흔한 조합 예시
// 표준 텍스트 입력
{ tagName: 'input', placeholder: '이름' }
// 이메일
{ tagName: 'input', type: 'email', placeholder: 'you@example.com' }
// 비밀번호
{ tagName: 'input', type: 'password', maxLength: 20 }
// 전화번호 마스킹
{ tagName: 'input', masking: '010-0000-0000' }
// 금액 (숫자 콤마)
{ tagName: 'input', numberComma: true, textAlign: 'right' }
// 한글 이름 (바이트 제한)
{ tagName: 'input', maxLength: 30, byteMaxLength: true }
// 주민번호 뒷자리 숨김
{ tagName: 'input', masking: '000000-*******' }
// 읽기 전용 표시
{ tagName: 'input', value: '값', readonly: true }