본문으로 건너뛰기

데이터 렌더링

zenoPortfolio의 작업물 카드는 HTML에 하나씩 직접 적지 않습니다.
portfolioItems 배열에 객체를 추가하면 자동으로 카드가 만들어집니다.

portfolioItems 배열

위치:

components/WorksSection/WorksSection.js

예시:

{
category: 'site',
tech: 'Web Components,JavaScript,CSS,Railway',
order: -1,
href: 'https://zenoblog-production.up.railway.app/',
image: 'images/openGraph.png',
alt: 'zenoBlog',
tag: 'Site',
date: '2026',
stack: 'Web Components · JS · CSS',
title: 'zenoBlog',
desc: 'Web Component 학습 흐름을 바탕으로 정리한 개인 개발 블로그입니다.'
}

각 필드 의미

필드역할
category대분류 필터용 값
tech기술 태그 필터용 값
order카드 정렬 순서
href클릭 시 이동할 링크
image썸네일 이미지
alt이미지 대체 텍스트
tag카드 위 작은 라벨
date제작 연도
stack카드에 보이는 기술 스택
title카드 제목
desc카드 설명

map으로 카드 생성

${portfolioItems.map(item => `
<portfolio-card
category="${item.category}"
tech="${item.tech}"
order="${item.order}"
href="${item.href}"
image="${item.image}"
alt="${item.alt}"
tag="${item.tag}"
date="${item.date}"
stack="${item.stack}"
title="${item.title}"
desc="${item.desc}"
></portfolio-card>
`).join('')}

map()은 배열의 각 객체를 HTML 문자열로 바꿉니다.
join('')은 만들어진 문자열 배열을 하나의 문자열로 합칩니다.

PortfolioCard에서 attribute 읽기

PortfolioCard는 attribute를 읽어서 화면을 만듭니다.

const title = this.getAttribute('title') || '';
const desc = this.getAttribute('desc') || '';

HTML attribute는 문자열입니다.
그래서 order도 처음에는 문자열로 들어옵니다.

dataset 설정

카드 렌더링 중에 필터링용 dataset을 설정합니다.

this.dataset.category = category;
this.dataset.tech = tech;
this.dataset.order = order;

이렇게 하면 실제 DOM에는 아래처럼 들어갑니다.

<portfolio-card
class="card"
data-category="site"
data-tech="Web Components,JavaScript,CSS,Railway"
data-order="-1">
</portfolio-card>

main.js의 필터 로직은 이 dataset을 읽습니다.

새 작업물 추가 방법

새 카드를 추가하려면 portfolioItems에 객체 하나를 추가하면 됩니다.

{
category: 'toy',
tech: 'JavaScript,CSS',
order: 300,
href: 'portfolio/page/example/index.html',
image: 'images/example.png',
alt: '예제 프로젝트',
tag: 'Toy',
date: '2026',
stack: 'JavaScript · CSS',
title: '예제 프로젝트',
desc: '새로 추가한 토이 프로젝트입니다.'
}

HTML을 직접 복사해서 붙일 필요가 없다는 점이 데이터 기반 렌더링의 장점입니다.

개선 아이디어

작업물이 더 많아지면 portfolioItems를 별도 파일로 분리할 수 있습니다.

예:

data/portfolioItems.js

그 후 WorksSection.js에서 import합니다.

import { portfolioItems } from '../../data/portfolioItems.js';

이렇게 하면 컴포넌트 코드와 데이터가 분리되어 관리가 더 쉬워집니다.