VanillaFront 2026. 9. 9. 17:38

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 }