VanillaFront 2026. 9. 18. 19:05

Va.Page — View의 표준 최상위 컨테이너

VanillaFront View의 루트로 사용되는 표준 페이지 컨테이너입니다. 내부적으로는 <article> 태그로 렌더링되지만 va-page 클래스로 페이지 전용 레이아웃/여백/스타일이 적용되며, Va.Panel과 짝을 이뤄 Page > Panel 구조로 화면을 구성하는 것이 VanillaFront의 표준입니다.

클래스 정보

Va.Page extends Va.Semantic extends Va.Component
tagName: 'page' (실제 렌더링은 <article>)
isContainer: true

기본 사용법

{
    tagName: 'page',
    tags: [{
        tagName: 'panel',
        title: '섹션1',
        tags: [ /* 콘텐츠 */ ]
    },{
        tagName: 'panel',
        title: '섹션2',
        tags: [ /* 콘텐츠 */ ]
    }]
}

View의 config()에서:

config(){
    return {
        tagName: 'page',
        tags: [{
            tagName: 'panel',
            tags: [ /* ... */ ]
        }]
    };
}

View 루트로 사용 — VanillaFront 표준

VanillaFront에서 **화면(View)을 만들 때 표준 최상위 컨테이너는 Va.Page**입니다:

  • 자체 gap을 가짐 — 내부 Panel 사이 공백이 자동으로 잡힘
  • 자체 padding/여백을 가짐 — 화면 가장자리 여백이 통일됨
  • 테마 대응 — 모든 테마에서 일관된 페이지 룩 앤 필

따라서 div나 article로 평탄하게 View를 시작하지 말고 Page → Panel 구조부터 시작하는 것이 표준입니다. 이 구조만 따르면 각 영역이 일정한 공백으로 자연스럽게 나뉘며, 별도로 margin/padding/gap을 강제로 끼우면 오히려 룩이 어긋납니다.

 <article> 태그일까?

Va.Page는 내부적으로 <article> HTML 태그로 렌더링됩니다:

  • HTML5 시맨틱상 하나의 독립된 콘텐츠 단위를 표현
  • SPA에서 각 View는 독립된 페이지처럼 동작하므로 <article>이 적절
  • CSS는 va-page 클래스로 페이지 전용 스타일 적용

속성

속성타입설명

lineDivision String 'row' 또는 'column' — 자식 사이 구분선 방향
innerHTML String HTML 문자열 (상속)
text String 순수 텍스트 (상속)
layout, style, class, hidden 공통 속성

lineDivision 활용

{
    tagName: 'page',
    lineDivision: 'row',    // 자식들 사이에 가로 구분선
    tags: [ /* panel들 */ ]
}
  • 'row'  line-division-row 클래스 → 세로 배치된 자식 사이 가로선
  • 'column'  line-division-column 클래스 → 가로 배치된 자식 사이 세로선

이벤트

Va.Semantic으로부터 상속 (별도 이벤트 없음, 기본 DOM 이벤트만).

메서드

  • setText(text) / setInnerHTML(html) — 내용 변경
  • Va.Component / Va.Semantic 공통 메서드

내부 구조

<article class="va-page" tag-name="page">
    <!-- containerElement에 Panel 등 자식 -->
</article>

lineDivision이 지정되면 line-division-row/line-division-column 클래스가 추가됩니다.

사용 시점 — 언제 쓰나

  • 모든 View의 최상위 컨테이너 — 새 View 만들 때 기본으로 시작
  • 모달/다이얼로그 내부 페이지 — Dialog 안에도 Page > Panel 구조 가능
  • 탭 안의 각 화면 — TabItem 콘텐츠도 Page로 감싸 일관성 유지

사용하지 말아야 할 때

  • 하위 섹션 분할  Va.Panel 사용
  • 단순 텍스트 감싸기  Va.Div
  • 의미가 있는 콘텐츠 블록  Va.Article / Va.Section

표준 구조 — Page > Panel

VanillaFront 화면의 표준 스캐폴드:

config(){
    return {
        tagName: 'page',
        tags: [{
            tagName: 'panel',
            title: '검색 조건',
            tags: [ /* 검색 폼 */ ]
        },{
            tagName: 'panel',
            title: '결과',
            tags: [
                { tagName: 'grid', ref: 'refGrid', /* ... */ }
            ]
        }]
    };
}
  • Page의 자식은 대부분 Panel — 폼/그리드/차트 등을 각 Panel에 나눠 담음
  • Panel도 자체 title/header/collapse 기능 제공 → 별도 헤딩 없이도 섹션 구분됨

자주 쓰는 조합 예시

목록 + 상세 화면

{
    tagName: 'page',
    tags: [{
        tagName: 'panel',
        title: '조회',
        tags: [ /* 검색 조건 필드 + 조회 버튼 */ ]
    },{
        tagName: 'panel',
        title: '목록',
        tags: [
            { ref: 'refGrid', tagName: 'grid', /* ... */ }
        ]
    },{
        tagName: 'panel',
        title: '상세',
        tags: [ /* 편집 폼 */ ]
    }]
}

line-division으로 구분선 자동 부여

{
    tagName: 'page',
    lineDivision: 'row',
    tags: [
        { tagName: 'panel', tags: [ /* ... */ ] },
        { tagName: 'panel', tags: [ /* ... */ ] },
        { tagName: 'panel', tags: [ /* ... */ ] }
    ]
}

좌우 분할 레이아웃

{
    tagName: 'page',
    layout: 'ds-flex fd-row',
    tags: [{
        tagName: 'panel',
        title: '메뉴',
        style: { width: '250px' },
        tags: [ /* 사이드바 */ ]
    },{
        tagName: 'panel',
        style: { flex: 1 },
        tags: [ /* 메인 콘텐츠 */ ]
    }]
}

실전 예시 — 전형적인 CRUD View

export default class UserList extends Va.View{
    constructor(){
        super(arguments);
    }
    mounted(){
        this.loadUsers();
    }
    onClickSearch(){ /* ... */ }
    onRowClick(grid, key, value, data){ /* ... */ }
    config(){
        return {
            tagName: 'page',
            tags: [{
                tagName: 'panel',
                title: '조회 조건',
                tags: [{
                    tagName: 'div',
                    layout: 'ds-flex fd-row gap-s',
                    tags: [
                        { tagName: 'inputField', label: '이름', ref: 'refName' },
                        { tagName: 'button', text: '조회', onClick: 'onClickSearch' }
                    ]
                }]
            },{
                tagName: 'panel',
                title: '사용자 목록',
                tags: [{
                    ref: 'refGrid',
                    tagName: 'grid',
                    columns: [ /* ... */ ],
                    onRowClick: 'onRowClick'
                }]
            }]
        };
    }
}
Va.registerView('/view/user/UserList', UserList);

주의사항

  • Page/Panel은 자체 gap을 가짐 — 사이에 별도의 margin, padding, gap을 강제로 넣지 말 것 (룩이 어긋남)
  • div/article로 평탄하게 시작 금지 — VanillaFront 표준을 어기면 여백/구분선 스타일이 자동 적용되지 않음
  • View 안에 여러 Page 중첩은 지양 — Page는 View의 최상위 하나만. 하위 구획은 Panel로
  • <article>로 렌더링됨 — HTML 마크업 검사 시 <page>가 아니라 <article class="va-page">로 보임
  • 테마 대응 — Light/Dark/Paper/Titan 등 모든 테마에서 자동 조정. 직접 CSS 오버라이드 최소화

대안 비교

상황추천

View 최상위 Va.Page
페이지 내부 섹션 분할 Va.Panel
독립된 게시글 콘텐츠 Va.Article
논리적 섹션 Va.Section
순수 그루핑 Va.Div

참고