VanillaFront 2026. 9. 14. 18:14

Va.Label — 텍스트 라벨 (info 버튼 포함)

폼 필드의 라벨이나 화면의 짧은 텍스트 라벨을 표현하는 컴포넌트. 단순한 <label> 태그를 감싸지만 info 툴팁 버튼 통합, 필수 표시(별표), 라벨 위치·정렬 등 폼 라벨에 필요한 기능이 함께 들어 있습니다.

  • 클래스: Va.Label  va_component.js:22
  • short name: label
  • 상속: Va.Component
  • DOM 태그: <label>
  • isContainer: false
  • 베이스 CSS: va-label


1. 기본 사용

{
    tagName: 'label',
    label: '이름',
    required: true,
    infoButton: {
        tooltip: '이름을 정확히 입력하세요'
    }
}
  • 텍스트: 이름
  • 우측: 필수 별표(빨간 *)
  • 옆에: info 아이콘 (마우스 올리면 툴팁)

2. Va.Label의 특징

일반 HTML <label>과 크게 다른 점:

항목HTML <label>Va.Label

info 툴팁 통합 ✓ (내부 Va.Button)
필수 표시(별표) ✓ (required 옵션)
라벨 위치 클래스 ✓ (labelPosition)
정렬 개발자 CSS ✓ (labelAlign)
구분자 표시 ✓ (seperator)
비활성 상태 스타일 ✓ (disabled)

한 줄 요약: "폼 라벨에 필요한 부가 요소를 모두 통합한 라벨 컴포넌트."


3. 주요 속성

텍스트

속성설명

label 라벨 텍스트 (Field 계열에서 넘겨받을 때 이 필드)
text 순수 텍스트 (label 미지정 시 사용)
innerHTML HTML 콘텐츠 (_sanitize 적용)

우선순위: label > text > innerHTML

표시 옵션

속성기본값설명

required true면 필수 별표 표시 (required 클래스 추가)
disabled 비활성화 스타일
infoButton info 아이콘 옵션 (Va.Button 옵션 그대로)

배치·정렬

속성기본값설명

labelPosition top / bottom / left / right — 라벨의 위치 (Field에서 관리)
labelAlign 텍스트 정렬. CSS 클래스 align-{값} 추가
seperator true면 라벨-필드 사이 구분자(콜론 등) 표시. left/right일 땐 자동
labelWidth '100%' 라벨 폭

4. infoButton — info 툴팁 통합

라벨 옆에 정보 아이콘을 붙이는 흔한 UX를 하나의 옵션으로 처리합니다.

기본

{
    tagName: 'label',
    label: '비밀번호',
    infoButton: {
        tooltip: '8자 이상, 영문/숫자/특수문자 포함'
    }
}

아이콘 변경

{
    tagName: 'label',
    label: '주의',
    infoButton: {
        icon: 'ico_warning',
        tooltip: '이 항목은 저장 후 수정 불가'
    }
}

클릭 이벤트

{
    tagName: 'label',
    label: '도움말 보기',
    infoButton: {
        onClick: 'onHelpClick'
    }
}

내부 구조: infoButton은 실제로 Va.Button 인스턴스. iconOnly: true, size: 'small', appearance: 'transparent'가 기본. infoButtonComponent로 접근 가능.


5. 이벤트

이벤트시그니처발생 시점

click (component, element, evt) 라벨 클릭 시 (preventDefault 자동 — 폼 포커스 이동 안 함)
contextmenu (component, element, evt) 우클릭

⚠️ click에서 preventDefault() 자동 호출 — HTML <label>의 표준 동작(연관 input에 포커스 자동 이동)을 차단합니다. VanillaFront는 폼 필드가 자체적으로 클릭 처리를 하므로.


6. 메서드

메서드설명

setText(text) 텍스트 변경 (sanitize 적용)
setInnerHTML(html) HTML 콘텐츠 변경 (sanitize 적용)
setRequired(bool) 필수 표시 토글
setLabelAlign(align) 정렬 변경
setLabelPosition(pos) 위치 변경

내부 컴포넌트 접근

접근설명

component.infoButtonComponent info 버튼(Va.Button) 인스턴스
component.textElement 텍스트 span 요소
component.innerElement 내부 div (텍스트 + info 감싸는 컨테이너)

7. 내부 구조

<label elname="element" class="va-label [required] [disabled]
                                [top|left|right|bottom]
                                [align-left|center|right] [seperator]"
       tag-name="label">
  <div elname="inner" class="label-inner">
    <span elname="text" class="text">이름</span>
    <div cpname="infoButton" class="va-button" style="display:block">ⓘ</div>
  </div>
</label>

핵심:

  • <label> 태그 — HTML 표준 시맨틱 유지
  • **inner div**로 텍스트+info를 감싸 정렬
  • required CSS 클래스로 CSS에서 별표(::after 등) 삽입
  • seperator CSS 클래스로 콜론(":") 등 구분자 삽입

labelPosition이 left/right면 seperator 자동 부여됨 — 좌측/우측 라벨은 콜론이 자연스러워서.


8. Field 계열에서의 역할

Va.Label은 다른 Field 컴포넌트가 내부에서 자동으로 사용하는 컴포넌트입니다. 개발자가 직접 tagName: 'label'로 배치할 일은 상대적으로 적고, 대개 Field의 label 옵션이 Label을 생성합니다.

// InputField 내부에서
this.labelComponent = new Va.Label({
    label: this.label,
    required: this.required,
    labelPosition: this.labelPosition,
    labelAlign: this.labelAlign,
    size: this.size,
    infoButton: this.infoButton,
    seperator: this.seperator
});

즉, 폼 필드에서 label, required, infoButton 옵션을 지정하면 이 Label이 만들어져 붙는 구조.


9. 언제 직접 쓰나

Va.Label을 직접 쓸 때

  • Field 없이 커스텀 폼 레이아웃을 만들 때
  • 여러 요소의 공통 라벨 (예: 라디오 그룹 위의 그룹 라벨)
  • 화면 안 작은 안내 텍스트 (Va.Div나 Va.Span보다 시맨틱)
  • info 툴팁이 필요한 텍스트 라벨

다른 걸 쓸 때

  • 폼 필드용 라벨 → Va.InputField / Va.ComboboxField 등의 label 옵션 활용
  • 화면 제목·본문 → Va.H1~Va.H6, Va.Span, Va.Div
  • 클릭 가능 텍스트 → Va.Link
  • 라벨만 있는 필드 (구조상) → Va.LabelField

10. 흔한 조합 예시

// 표준
{
    tagName: 'label',
    label: '이름',
    required: true
}

// info 툴팁 포함
{
    tagName: 'label',
    label: '비밀번호',
    infoButton: {
        tooltip: '8자 이상 입력'
    }
}

// 커스텀 폼 레이아웃 (라벨 + 여러 컴포넌트)
{
    tagName: 'div',
    layout: 'ds-flex fd-row ai-center gap-m',
    tags: [
        { tagName: 'label', label: '이름', labelPosition: 'left', style: { width: '80px' } },
        { tagName: 'input' },
        { tagName: 'input' }
    ]
}

// 라디오 그룹 위의 그룹 라벨
{
    tagName: 'div',
    layout: 'ds-flex fd-column gap-s',
    tags: [
        { tagName: 'label', label: '성별', required: true },
        {
            tagName: 'radioGroup',
            key: 'code',
            display: 'name',
            data: [
                { code: 'M', name: '남' },
                { code: 'F', name: '여' }
            ]
        }
    ]
}

// HTML 콘텐츠
{
    tagName: 'label',
    innerHTML: '<b>결제 정보</b> (필수)'
}

// 비활성 상태
{
    tagName: 'label',
    label: '옵션 (선택 불가)',
    disabled: true
}

11. 실전 예 — 그룹 라벨과 컴포넌트

class OrderOptions extends Va.View {
    config() {
        return {
            tagName: 'page',
            tags: [{
                tagName: 'panel',
                tags: [
                    {
                        tagName: 'div',
                        layout: 'ds-flex fd-column gap-s',
                        tags: [
                            // Field 없이 라벨을 별도로 배치
                            {
                                tagName: 'label',
                                label: '배송 방식',
                                required: true,
                                infoButton: {
                                    tooltip: '표준: 3~5일 / 익일: 다음날 도착 / 새벽: 새벽 배송'
                                }
                            },
                            // 라디오 그룹은 라벨과 시각적으로 분리
                            {
                                tagName: 'radioGroup',
                                ref: 'shipping',
                                key: 'code',
                                display: 'name',
                                direction: 'vertical',
                                data: [
                                    { code: 'STD',   name: '표준 배송 (무료)' },
                                    { code: 'FAST',  name: '익일 배송 (+3,000원)' },
                                    { code: 'DAWN',  name: '새벽 배송 (+5,000원)' }
                                ]
                            }
                        ]
                    }
                ]
            }]
        };
    }
}

Field 계열로 감쌀 필요가 없을 때 이런 조합이 자연스럽습니다.


12. 알아두면 좋을 주의사항

  1. click에서 preventDefault 자동 — HTML <label>의 표준 focus 이동 동작 차단.
  2. infoButton 옵션은 Va.Button 옵션 그대로  icon, size, appearance, tooltip, onClick 등 자유롭게.
  3. infoButtonComponent로 직접 접근 가능 — 나중에 setIcon(), setDisabled() 등 제어.
  4. required/disabled는 CSS 클래스 — 실제 별표·회색 처리는 테마 CSS에서.
  5. seperator: true가 콜론 삽입  labelPosition이 left/right면 자동. 별도 지정도 가능.
  6. labelWidth 기본 '100%' — 부모 컨테이너 폭 채움. 좌측 라벨이면 명시 지정 권장.
  7. text/innerHTML 세팅 시 _sanitize 자동 — XSS 방지.
  8. Field에 내장된 Label은 자동 생성 — 개별 옵션은 Field 옵션으로 전달.
  9. label vs text 우선순위  label이 우선. Field 계열이 label 필드로 넘겨서.
  10. <label> for 속성 자동 연결 없음 — 별도 시맨틱 연결 필요 시 개발자가 처리.
  11. 키보드 접근성  <label> 자체는 tabindex 없음. 관련 필드가 대신.
  12. infoButton에 tabindex: -1 자동 — 폼 탭 순회에서 제외.

13. label vs labelField vs div 선택

상황추천

폼 필드의 라벨 Field 옵션 label (내부 자동 생성)
커스텀 레이아웃 라벨 Va.Label 직접
info 툴팁이 필요한 텍스트 Va.Label + infoButton
라벨만 있는 폼 필드 구조 Va.LabelField
화면 안 일반 텍스트 Va.Div / Va.Span
제목 Va.H1~Va.H6
클릭 가능 텍스트 Va.Link

참고