컴포넌트/시멘틱태그

Article (아티클)

VanillaFront 2026. 9. 14. 18:34

Va.Article — HTML <article> 시맨틱 컨테이너

HTML5의 <article> 태그를 감싸는 시맨틱 컨테이너. 독립적으로 배포·재사용 가능한 콘텐츠를 나타내는 랜드마크 요소입니다. 블로그 글·뉴스 기사·상품 카드처럼 그 자체로 완결된 콘텐츠 단위에 어울립니다. VanillaFront에서 가장 자주 쓰는 semantic 태그 중 하나 — 데모 코드에서도 최상위 컨테이너로 자주 등장.

  • 클래스: Va.Article  va_component.js:21824
  • short name: article
  • 상속: Va.Semantic (Main·Section과 같은 부모)
  • DOM 태그: <article>
  • isContainer: true
  • 베이스 CSS: va-article

1. 기본 사용

{
    tagName: 'article',
    layout: 'ds-flex fd-column gap-m',
    tags: [
        { tagName: 'h1', innerHTML: '기사 제목' },
        { tagName: 'p',  innerHTML: '본문 내용...' }
    ]
}
  • HTML <article> 태그로 렌더링
  • 자식을 자유롭게 담음
  • 스크린리더가 "독립 콘텐츠"로 인식

2. Va.Article의 성격

Va.Semantic을 상속한 얇은 확장. 코드 자체는 매우 단순(30줄)하지만, VanillaFront 데모·문서 페이지의 최상위 컨테이너로 관행처럼 사용되고 있습니다.

항목Va.DivVa.Article

HTML 태그 <div> <article>
시맨틱 의미 없음 독립 콘텐츠 단위
접근성 기본 랜드마크 (제목 있으면)
SEO 기본 크롤러가 독립 콘텐츠로 인식
한 페이지 여러 개 자유 자유 (Main과 다름)
재사용 시맨틱 없음 자체 완결 콘텐츠 (RSS·공유 등)

한 줄 요약: "독립 콘텐츠 단위를 표현하는 시맨틱 컨테이너 — 데모·문서 최상위로 자주 사용."


3. <article> HTML 표준의 의미

HTML5 표준상 <article>은 **"독립적으로 배포하거나 재사용할 수 있는 완결된 콘텐츠"**를 나타냅니다. 판단 기준:

  • RSS 피드에 넣을 수 있는가? — 블로그 글, 뉴스 기사 O
  • 다른 사이트로 그대로 옮겨도 의미가 통하는가? — 상품 카드, 리뷰 O
  • 댓글·평점처럼 각각 독립적인 단위인가? — 개별 댓글 O

한 페이지에 여러 개 있을 수 있고 (Main과 다름), 중첩도 가능 (기사 안 관련 기사 등).


4. Semantic 계열에서의 위치

Va.Article은 시맨틱 형제들 중 하나:

컴포넌트시맨틱 의미

Va.Main 페이지 주요 콘텐츠 (한 페이지 하나)
Va.Article 독립 배포 가능 콘텐츠
Va.Section 주제별 콘텐츠 섹션
Va.Aside 부수적 콘텐츠
Va.Nav 네비게이션
Va.Header / Va.Footer 헤더/푸터

Article과 Section 헷갈리기 쉬움:

  • Article — 독립적, 그 자체로 완결 (블로그 글)
  • Section — 문서 안 하나의 섹션, 주제별 그룹

5. 주요 속성

Semantic 상속만. 자체 추가 없음:

속성설명

innerHTML HTML 콘텐츠 (_sanitize 적용)
text 순수 텍스트
layout Flex/Grid 레이아웃
style / mobileStyle 스타일
class / addClass CSS 클래스
mediaQuery 반응형

Component의 표준 속성 그대로.


6. 이벤트 (Semantic 상속)

이벤트시그니처발생 시점

click (component, element, evt) 클릭
contextmenu (component, element, evt) 우클릭 (기본 컨텍스트 메뉴 자동 차단)
focus / blur (component, element, evt) 포커스 진입/이탈

7. 메서드

메서드설명

setText(text) 텍스트 변경 (Semantic 상속)
setInnerHTML(html) HTML 콘텐츠 변경

8. 내부 구조

<article elname="element" class="va-article [layout classes]"
         tag-name="article">
  <!-- 자식 컴포넌트들 -->
</article>

매우 단순. HTML <article> 태그 + va-article CSS 클래스.


9. VanillaFront에서의 관행

Demo·API 문서 페이지의 최상위 컨테이너로 관행처럼 사용됩니다:

// 프로젝트 내 대부분 Demo 파일이 이 구조로 시작
config() {
    return {
        tagName: 'article',
        layout: 'ds-flex fd-column gap-m',
        tags: [
            { tagName: 'h3', innerHTML: '데모 제목' },
            /* ... */
        ]
    };
}

이유:

  • 데모 하나가 그 자체로 완결된 예제 → Article이 시맨틱상 적절
  • Page/Panel보다 가벼워서 데모용으로 부담 없음
  • HTML 표준 준수

⚠️ 다만 실무 화면은 page > panel 구조가 프로젝트 표준 (CLAUDE.md 3장). Article은 데모 성격이 강함.


10. 언제 쓰나

Va.Article이 맞을 때

  • 블로그 글, 뉴스 기사 등 완결 콘텐츠
  • 상품 카드, 리뷰 아이템 등 독립 단위
  • 데모·API 문서 페이지 최상위 (VanillaFront 관행)
  • 댓글·게시글 목록의 각 아이템

다른 걸 쓸 때

  • 실무 화면 최상위 → Va.Page + Va.Panel (VanillaFront 표준)
  • 페이지 주요 콘텐츠 랜드마크 → Va.Main
  • 주제별 섹션 → Va.Section
  • 부수 콘텐츠 → Va.Aside
  • 단순 컨테이너 → Va.Div

11. 흔한 조합 예시

// 데모 페이지 표준 (VanillaFront 관행)
{
    tagName: 'article',
    layout: 'ds-flex fd-column gap-m',
    tags: [
        { tagName: 'h3', innerHTML: '컴포넌트 데모' },
        { tagName: 'button', text: '테스트' }
    ]
}

// 블로그 글 카드
{
    tagName: 'article',
    layout: 'ds-flex fd-column gap-s',
    style: { border: '1px solid gray', padding: '16px' },
    tags: [
        { tagName: 'h2', innerHTML: '제목' },
        { tagName: 'p',  innerHTML: '요약 텍스트' },
        {
            tagName: 'div',
            layout: 'ds-flex fd-row gap-s',
            tags: [
                { tagName: 'span', innerHTML: '작성자' },
                { tagName: 'span', innerHTML: '2026-09-14' }
            ]
        }
    ]
}

// 상품 카드
{
    tagName: 'article',
    layout: 'ds-flex fd-column',
    style: { border: '1px solid gray', borderRadius: '8px' },
    tags: [
        { tagName: 'img', src: '/product.jpg' },
        {
            tagName: 'div',
            style: { padding: '12px' },
            tags: [
                { tagName: 'h3', innerHTML: '상품명' },
                { tagName: 'p',  innerHTML: '10,000원' },
                { tagName: 'button', text: '장바구니' }
            ]
        }
    ]
}

// 리뷰 목록의 각 아이템
{
    tagName: 'section',
    tags: [
        { tagName: 'h2', innerHTML: '리뷰' },
        {
            tagName: 'div',
            layout: 'ds-flex fd-column gap-m',
            tags: [
                {
                    tagName: 'article',   // 리뷰 하나가 독립 콘텐츠
                    tags: [ /* 별점, 리뷰 텍스트, 작성자 */ ]
                },
                {
                    tagName: 'article',
                    tags: [ /* ... */ ]
                }
            ]
        }
    ]
}

12. 실전 예 — 블로그 목록 페이지

class BlogList extends Va.View {
    async mounted() {
        const res = await BlogService.list(this);
        if (res.result) this.renderPosts(res.data.list);
    }

    renderPosts(posts) {
        const container = this.getRef('posts');
        container.innerHTML = '';
        posts.forEach(post => {
            const article = new Va.Article({
                layout: 'ds-flex fd-column gap-s',
                style: { border: '1px solid var(--colorNeutralStroke)', padding: '16px' }
            });
            article.append(new Va.H2({ innerHTML: post.title }));
            article.append(new Va.P({ innerHTML: post.summary }));
            container.append(article);
        });
    }

    config() {
        return {
            tagName: 'main',              // 전체는 main (랜드마크)
            layout: 'ds-flex fd-column gap-l',
            style: { padding: '20px' },
            tags: [
                { tagName: 'header', tags: [{ tagName: 'h1', innerHTML: '블로그' }] },
                {
                    tagName: 'section',    // 목록 섹션
                    ref: 'posts',
                    layout: 'ds-flex fd-column gap-m'
                }
            ]
        };
    }
}

시맨틱 계층:

  • <main> — 페이지 주요 콘텐츠 (한 페이지 하나)
  • <section> — 블로그 목록 섹션
  • <article> × N — 각 블로그 글 (독립 콘텐츠, RSS로 넣을 수 있는 단위)

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

  1. Article vs Section 구분 — "독립적 재배포 가능한가?"가 판단 기준.
  2. 한 페이지 여러 개 OK — Main과 달리 개수 제한 없음.
  3. 중첩 가능 — 기사 안 관련 기사 등.
  4. VanillaFront 데모 관행  article 최상위는 데모용. 실무는 page 권장.
  5. contextmenu 자동 preventDefault — 우클릭 시 브라우저 기본 메뉴 차단.
  6. 자체 스타일 최소  va-article 클래스만. gap·padding은 layout·style로 명시.
  7. text/innerHTML은 자식 tags와 배타적 — 대개 자식으로 구조화된 콘텐츠 담음.
  8. 접근성 랜드마크 — 스크린리더가 인식하려면 aria-labelledby 등으로 제목 연결 권장.
  9. SEO 최적화 — 크롤러가 독립 콘텐츠로 인식 → 목록 페이지에서 각 글을 article로 감싸는 게 유리.
  10. Va.Semantic 상속 — Section·Header·Footer 등과 동작 방식 완전 동일.

14. article vs section vs main vs page 선택

상황추천

독립 콘텐츠 단위 (블로그 글, 상품) article
문서 안 주제 섹션 section
페이지 주요 콘텐츠 (랜드마크) main
VanillaFront 실무 화면 page + panel
데모·API 문서 페이지 article (관행)
부수 콘텐츠 aside

"블로그·상품·리뷰처럼 그 자체로 완결되면 article, 페이지 안 섹션 나누기면 section".


참고

'컴포넌트 > 시멘틱태그' 카테고리의 다른 글

Main (메인)  (0) 2026.09.14