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 |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apidiv
- 연관: Va.Component(부모), Va.DivView(View 임베딩 지원 확장판)
'컴포넌트 > 패널 외 영역 (Div, Span)' 카테고리의 다른 글
| Title (타이틀) (0) | 2026.09.18 |
|---|---|
| ActionBar (액션바) (0) | 2026.09.18 |
| Panel (패널) (0) | 2026.09.18 |
| Page (페이지) (0) | 2026.09.18 |
| Span (스팬) (1) | 2026.09.18 |