데이터 렌더링
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';
이렇게 하면 컴포넌트 코드와 데이터가 분리되어 관리가 더 쉬워집니다.