컴포넌트/패널 외 영역 (Div, Span)
GridDiv (그리드 디비전)
VanillaFront
2026. 9. 18. 22:25
Va.GridDiv — CSS Grid 기반 격자 레이아웃 컨테이너
CSS Grid를 이용해 셀 단위 격자 레이아웃을 만드는 컨테이너입니다. Va.Component를 직접 상속받으며 display: grid가 자동 적용되어, 실제 데이터 그리드(Va.Grid)와는 다른 목적의 정적 격자 레이아웃(카드 나열, 폼 격자 배치, 스프레드시트 스타일 표 등)에 사용됩니다.
클래스 정보
Va.GridDiv extends Va.Component
tagName: 'gridDiv' (실제 렌더링은 <div>)
isContainer: true
isEnableRoot: true
파일: va_griddiv.js (별도 모듈)
짝을 이루는 3형제
va_griddiv.js 하나에 세 컴포넌트가 함께 정의되어 있으며, 함께 사용하는 것이 표준 패턴입니다:
컴포넌트CSS 클래스역할
| Va.GridDiv | va-grid-div | 격자 컨테이너 (루트) |
| Va.GridDivH | va-grid-div-header | 헤더 셀 (배경색 강조) |
| Va.GridDivB | va-grid-div-body | 바디 셀 (일반 콘텐츠) |
기본 사용법
{
tagName: 'gridDiv',
style: {
gridTemplateColumns: '100px 200px 1fr',
gridTemplateRows: 'auto auto'
},
tags: [
{ tagName: 'gridDivH', text: '코드' },
{ tagName: 'gridDivH', text: '이름' },
{ tagName: 'gridDivH', text: '설명' },
{ tagName: 'gridDivB', text: '001' },
{ tagName: 'gridDivB', text: '홍길동' },
{ tagName: 'gridDivB', text: '개발팀장' }
]
}
Va.Grid와의 차이 — 핵심 구분
항목Va.GridVa.GridDiv
| 목적 | 데이터 그리드 (행/열, 정렬, 스크롤, DataManager 연동) | 정적 격자 레이아웃 (CSS Grid) |
| 사용 | 서버 데이터 조회 결과 표시 | 카드 나열, 폼 격자, 정적 표 |
| 이벤트 | onRowClick, onCellClick, onSort 등 풍부 | click, contextmenu만 |
| 파일 | va_grid.js (대형) | va_griddiv.js (소형) |
| 동적 데이터 | ○ (setData) | × (JSON tag 트리) |
요약: 데이터 조회/편집 UI라면 Va.Grid, 시각적 격자 배치라면 Va.GridDiv.
속성
속성타입설명
| text | String | 순수 텍스트 |
| innerHTML | String | HTML 문자열 |
| appearance | String | CSS 클래스로 부여됨 ('primary', 'outline' 등) |
| layout, style, class, hidden | — | 공통 속성 |
격자 정의는 style로: gridTemplateColumns, gridTemplateRows, gap 등 CSS Grid 속성을 style로 지정합니다.
이벤트
이벤트발생 시점콜백 인자
| click | 클릭 시 | (sender, element, evt) |
| contextmenu | 우클릭 시 | (sender, element, evt) |
세 컴포넌트 모두 동일한 이벤트만 지원합니다.
메서드
- setText(text) — 텍스트 변경 후 업데이트
- setInnerHTML(html) — HTML 변경 후 업데이트
- Va.Component 공통 메서드
자동 적용되는 CSS
.va-grid-div {
display: grid;
background: var(--colorBackground);
border-top: 0.5px solid var(--colorNeutralStroke);
border-left: 0.5px solid var(--colorNeutralStroke);
}
.va-grid-div-header {
background: var(--colorBackground3);
display: flex; align-items: center; justify-content: center;
padding: 0.2rem 0.4rem;
border-right/bottom: 0.1rem solid var(--colorNeutralStroke);
}
.va-grid-div-body {
display: flex; align-items: center; justify-content: start;
padding: 0.4rem;
border-right/bottom: 0.1rem solid var(--colorNeutralStroke);
}
appearance 변형:
- appearance: 'primary' → 헤더가 primary 색 배경
- appearance: 'outline' → 헤더 배경 투명
사용 시점 — 언제 쓰나
- 정적 표 형태 정보 표시 — 스펙 시트, 속성 목록, 규격 정보
- 폼 격자 배치 — 라벨과 필드가 규칙적으로 배열되는 폼
- 카드 그리드 — 동일 크기 카드들의 격자 나열
- 비교 표 — 요금제 비교, 사양 비교 등
- 캘린더 셀 격자 — 월 캘린더의 날짜 셀
사용하지 말아야 할 때
- 서버 데이터 조회 결과 그리드 → Va.Grid
- 정렬/필터/편집 기능이 필요한 표 → Va.Grid
- 자유 flex 레이아웃 → Va.Div + layout
- 단순 텍스트 그루핑 → Va.Div
자주 쓰는 조합 예시
스펙 시트 (2열 라벨-값)
{
tagName: 'gridDiv',
style: { gridTemplateColumns: '120px 1fr' },
tags: [
{ tagName: 'gridDivH', text: '이름' },
{ tagName: 'gridDivB', text: '홍길동' },
{ tagName: 'gridDivH', text: '부서' },
{ tagName: 'gridDivB', text: '개발팀' },
{ tagName: 'gridDivH', text: '이메일' },
{ tagName: 'gridDivB', text: 'hong@example.com' }
]
}
3열 헤더 + 여러 행 바디
{
tagName: 'gridDiv',
style: { gridTemplateColumns: '80px 150px 1fr' },
tags: [
// 헤더 행
{ tagName: 'gridDivH', text: '코드' },
{ tagName: 'gridDivH', text: '이름' },
{ tagName: 'gridDivH', text: '설명' },
// 데이터 행 1
{ tagName: 'gridDivB', text: '001' },
{ tagName: 'gridDivB', text: '홍길동' },
{ tagName: 'gridDivB', text: '개발팀장' },
// 데이터 행 2
{ tagName: 'gridDivB', text: '002' },
{ tagName: 'gridDivB', text: '김철수' },
{ tagName: 'gridDivB', text: '팀원' }
]
}
appearance 사용 (primary 헤더)
{
tagName: 'gridDiv',
appearance: 'primary',
style: { gridTemplateColumns: 'repeat(4, 1fr)' },
tags: [
{ tagName: 'gridDivH', text: '항목' },
{ tagName: 'gridDivH', text: '기본' },
{ tagName: 'gridDivH', text: '프로' },
{ tagName: 'gridDivH', text: '엔터프라이즈' },
{ tagName: 'gridDivB', text: '가격' },
{ tagName: 'gridDivB', text: '₩10,000' },
{ tagName: 'gridDivB', text: '₩50,000' },
{ tagName: 'gridDivB', text: '문의' }
]
}
폼 격자 배치 (라벨-필드 정렬)
{
tagName: 'gridDiv',
style: { gridTemplateColumns: '100px 1fr 100px 1fr', gap: 0 },
tags: [
{ tagName: 'gridDivH', text: '이름' },
{ tagName: 'gridDivB', tags: [{ tagName: 'input', ref: 'refName' }] },
{ tagName: 'gridDivH', text: '부서' },
{ tagName: 'gridDivB', tags: [{ tagName: 'input', ref: 'refDept' }] },
{ tagName: 'gridDivH', text: '이메일' },
{ tagName: 'gridDivB', tags: [{ tagName: 'input', ref: 'refEmail' }], style: { gridColumn: 'span 3' } }
]
}
실전 예시 — 사용자 상세 정보 표시
config(){
return {
tagName: 'panel',
tags: [{
tagName: 'title',
innerHTML: '사용자 상세 정보'
},{
tagName: 'gridDiv',
appearance: 'primary',
style: {
gridTemplateColumns: '150px 1fr',
width: '100%'
},
tags: [
{ tagName: 'gridDivH', text: '사용자 ID' },
{ tagName: 'gridDivB', text: 'user001' },
{ tagName: 'gridDivH', text: '이름' },
{ tagName: 'gridDivB', text: '홍길동' },
{ tagName: 'gridDivH', text: '부서' },
{ tagName: 'gridDivB', text: '개발팀' },
{ tagName: 'gridDivH', text: '가입일' },
{ tagName: 'gridDivB', text: '2026-01-15' },
{ tagName: 'gridDivH', text: '메모' },
{
tagName: 'gridDivB',
innerHTML: '<strong>VIP 고객</strong> - 우선 응대 대상'
}
]
}]
};
}
주의사항
- Va.Grid와 혼동 금지 — 이름이 비슷하지만 완전히 다른 컴포넌트. GridDiv는 정적 CSS Grid 레이아웃, Grid는 데이터 그리드
- 격자 정의는 style로 — gridTemplateColumns/gridTemplateRows 등은 style 속성으로 지정
- 셀 순서대로 배치 — 자식 배열 순서가 격자에 좌→우, 위→아래 순으로 채워짐
- 셀 병합 — 개별 셀에 style: { gridColumn: 'span 2' } 또는 gridRow: 'span N' 지정
- 자동 border — 컨테이너에 top/left, 셀에 right/bottom을 그려 전체가 표처럼 보임. gap을 주면 자연스러운 표가 아니게 되니 주의
- Va.GridDivH.update()의 버그 — 소스를 보면 innerHTML을 textContent로 넣는 부분이 먼저 실행된 후 다시 innerHTML로 덮어써지는 이중 처리 패턴이 있음. 결과적으론 innerHTML이 최종 반영되지만 첫 렌더링 시 잠깐 escape된 텍스트가 보일 수 있음
대안 비교
상황추천
| 정적 격자 레이아웃 (표/스펙) | Va.GridDiv + H + B |
| 서버 데이터 그리드 | Va.Grid |
| 트리 형태 그리드 | Va.TreeGrid |
| 동적 컬럼 그리드 | Va.DynamicGrid |
| 피벗 테이블 | Va.PivotGrid |
| 자유 flex 레이아웃 | Va.Div + layout |
| 카드 나열 (자동 줄바꿈) | Va.Div + display: grid + grid-template-columns: repeat(auto-fill, ...) |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apigriddiv
- 연관: Va.GridDivH(헤더 셀), Va.GridDivB(바디 셀)