VanillaFront 2026. 9. 18. 19:00

Va.Div — 범용 <div> 컨테이너

VanillaFront에서 가장 기본적이고 가장 많이 쓰이는 범용 컨테이너입니다. HTML <div> 태그로 렌더링되며, 시맨틱적 의미 없이 자식 요소들을 그룹핑하거나 레이아웃을 구성하는 데 사용됩니다.

클래스 정보

Va.Div extends Va.Component
tagName: 'div'
isContainer: true
isEnableRoot: true

Va.Semantic이 아닌 Va.Component를 직접 상속하며, isEnableRoot: true로 라우터 영역의 루트가 될 수 있습니다.

기본 사용법

{
    tagName: 'div',
    tags: [
        { tagName: 'button', text: '확인' },
        { tagName: 'button', text: '취소' }
    ]
}

플렉스 레이아웃 조합:

{
    tagName: 'div',
    layout: 'ds-flex fd-row ai-center gap-m',
    style: { padding: '20px' },
    tags: [ /* 자식 */ ]
}

코드로:

let div = new Va.Div({
    innerHTML: '<p>Hello</p>'
});
parent.append(div);

HTML <div>의 의미

<div>는 의미 없는 블록 레벨 컨테이너입니다. HTML5에서 다음과 같은 위치에 사용됩니다:

  • 시맨틱 태그(<article>, <section>, <nav> 등)로 표현할 수 없는 순수한 레이아웃 그룹핑
  • CSS 스타일링만을 목적으로 하는 감싸기
  • 스크립트로 조작할 대상을 지정하기 위한 컨테이너

시맨틱적 의미가 필요하다면 <div> 대신 <article>, <section>, <header>, <footer>, <nav>, <aside> 등을 우선 검토해야 합니다.

속성

속성타입설명

text String 순수 텍스트 (자동 이스케이프)
innerHTML String HTML 문자열
gridHeader Boolean true이면 grid-header 클래스 부여
gridBody Boolean true이면 grid-body 클래스 부여
layout, style, class, hidden, attributes 공통 속성

이벤트

이벤트발생 시점콜백 인자

click 클릭 시 (sender, element, evt)
contextmenu 우클릭 시 (sender, element, evt)

<div>가 표준 DOM 이벤트를 그대로 노출하는 것은 아니지만, VanillaFront에서는 두 이벤트가 명시적으로 dispatch됩니다.

메서드

  • setText(text) — 텍스트 변경 후 업데이트
  • setInnerHTML(html) — HTML 변경 후 업데이트
  • Va.Component 공통 메서드 (append, remove, addStyleClass 등)

내부 구조

<div class="va-div" tag-name="div">
    <!-- containerElement는 element 자신 -->
    <!-- text, innerHTML 또는 자식 컴포넌트가 여기에 -->
</div>

사용 시점 — 언제 쓰나

  • 레이아웃 그룹핑 — flex/grid 컨테이너로 자식들을 배치
  • 스타일 감싸기 — 배경색, 여백, 테두리 등 CSS를 적용할 상자
  • 동적 콘텐츠 마운트 포인트 — JS로 자식을 추가/제거할 공간
  • flex spacer  style: { flex: 1 }로 남는 공간 채우기 (.flex-1)
  • 의미 없는 순수 그루핑 — 그 외 시맨틱 태그가 어울리지 않는 모든 경우

사용하지 말아야 할 때

  • 페이지 최상위 컨테이너  Va.Page (page + panel 표준 구조)
  • 머리말/꼬리말/본문  Va.Header/Va.Footer/Va.Main
  • 게시글/독립 콘텐츠  Va.Article
  • 논리적 섹션  Va.Section
  • 내비게이션  Va.Nav
  • 버튼 역할  Va.Button (스타일로만 버튼 흉내 내지 말 것)

즉, 의미가 있으면 시맨틱 태그를, 의미가 없을 때만 div를.

자주 쓰는 조합 예시

flex row + spacer 패턴

{
    tagName: 'div',
    layout: 'ds-flex fd-row ai-center gap-s',
    tags: [
        { tagName: 'label', text: '제목' },
        { tagName: 'div', style: { flex: 1 } },      // 스페이서
        { tagName: 'button', text: '저장' },
        { tagName: 'button', text: '취소' }
    ]
}

스타일 감싸기 (카드 형태)

{
    tagName: 'div',
    style: {
        padding: '20px',
        borderRadius: 'var(--sizeRadiusM)',
        background: 'var(--colorNeutralBackground)',
        boxShadow: '0 2px 6px rgba(0,0,0,0.1)'
    },
    tags: [
        { tagName: 'h3', innerHTML: '카드 제목' },
        { tagName: 'div', text: '카드 본문' }
    ]
}

grid header/body 활용

{
    tagName: 'div',
    gridHeader: true,      // .grid-header 클래스 자동 부여
    tags: [ /* 헤더 셀들 */ ]
},
{
    tagName: 'div',
    gridBody: true,        // .grid-body 클래스 자동 부여
    tags: [ /* 바디 셀들 */ ]
}

동적 마운트 포인트

config(){
    return {
        tagName: 'div',
        tags: [{
            ref: 'refContent',
            tagName: 'div'
        }]
    };
}
mounted(){
    let child = new Va.Button({ text: '동적 버튼' });
    this.getRef('refContent').append(child);
}

실전 예시 — 반복되는 아이템 리스트

config(){
    return {
        tagName: 'div',
        layout: 'ds-flex fd-column gap-s',
        tags: this.items.map(item => ({
            tagName: 'div',
            layout: 'ds-flex fd-row ai-center gap-m',
            style: {
                padding: '10px',
                border: '1px solid var(--colorNeutralStroke)',
                borderRadius: '4px'
            },
            tags: [
                { tagName: 'div', text: item.name, style: { flex: 1 } },
                { tagName: 'div', text: item.price }
            ]
        }))
    };
}

주의사항

  • 남용 주의 (div soup) — 모든 것을 div로 감싸면 시맨틱 정보가 사라져 접근성/SEO가 나빠짐. 시맨틱 태그로 표현 가능한 것부터 검토
  • isEnableRoot: true — 라우터의 영역 루트가 될 수 있어 Va.setRouterAreaAsName로 참조 가능
  • text와 innerHTML 동시 지정 시 text 우선
  • innerHTML은 Va._sanitize() 통과 — XSS 방지 이스케이프가 적용됨
  • 페이지 최상단은 Div로 시작하지 말 것 — VanillaFront 표준은 page > panel 구조 (CLAUDE.md 참조). Div로 평탄하게 시작하면 gap/padding이 자연스럽게 잡히지 않음

대안 비교

상황추천

페이지 최상위 Va.Page
섹션 분할 Va.Panel
게시글 Va.Article
논리 섹션 Va.Section
상단/하단 영역 Va.Header / Va.Footer
내비게이션 Va.Nav
사이드바 Va.Aside
그 외 순수 그루핑/레이아웃/스타일 상자 Va.Div

참고