본문으로 건너뛰기

컴포넌트 구조 리뷰

components/index.js는 모든 컴포넌트를 불러오는 진입점입니다.

import './PortfolioCard/PortfolioCard.js';
import './BackToTop/BackToTop.js';
import './SiteHeader/SiteHeader.js';
import './HeroSection/HeroSection.js';
import './WorksSection/WorksSection.js';
import './SiteFooter/SiteFooter.js';

이 파일이 실행되면 각 컴포넌트 파일 안에서 customElements.define()이 실행됩니다.

태그:

<site-header></site-header>

역할:

  • 로고 표시
  • Design / Dev 모드 토글 버튼
  • Docs, Works, Contact 링크
  • 모바일 메뉴 모달 렌더링

중요한 부분:

<div class="mode-toggle" role="tablist" aria-label="모드 전환">
<button class="mode-btn" data-mode="design">Design</button>
<button class="mode-btn active" data-mode="dev">Dev</button>
<span class="mode-indicator" aria-hidden="true"></span>
</div>

모드 토글은 main.jsModeToggle 객체가 이벤트를 붙입니다.

HeroSection

태그:

<hero-section></hero-section>

역할:

  • 첫 화면 문구 표시
  • 현재 모드에 따라 핵심 문장 변경
<span class="line line-2" data-design="Designer who codes." data-dev="Developer who designs.">
<span class="mode-text">Developer who designs.</span>
</span>

data-design, data-devModeToggle이 읽어서 텍스트를 바꿉니다.

WorksSection

태그:

<works-section></works-section>

역할:

  • 포트폴리오 데이터 배열 관리
  • 필터 버튼 렌더링
  • 기술 태그 필터 영역 렌더링
  • portfolio-card 목록 생성
  • empty state, loader, sentinel 생성

핵심 데이터:

const portfolioItems = [
{
category: 'site',
tech: 'Web Components,JavaScript,CSS,Railway',
href: 'https://zenoblog-production.up.railway.app/',
title: 'zenoBlog'
}
];

PortfolioCard

태그:

<portfolio-card></portfolio-card>

역할:

  • 작업물 카드 하나 렌더링
  • attribute를 읽어 카드 이미지, 제목, 설명, 링크 구성
  • 필터링에 필요한 dataset 설정
this.dataset.category = category;
this.dataset.tech = tech;
this.dataset.order = order;

이 값은 main.jsFilterInfiniteScroll에서 사용합니다.

태그:

<site-footer></site-footer>

역할:

  • 하단 브랜드/사이트맵/채널/연락처 표시
  • <back-to-top> 컴포넌트 포함
<back-to-top></back-to-top>

BackToTop

태그:

<back-to-top></back-to-top>

역할:

  • 상단 이동 버튼 렌더링

스크롤 이벤트와 클릭 이벤트는 main.jsBackToTop 객체가 처리합니다.

구조적으로 좋은 점

  • 컴포넌트별 폴더가 명확함
  • JS와 CSS가 같은 폴더에 있어 찾기 쉬움
  • 카드 UI는 재사용 가능하게 분리됨
  • 데이터 배열만 수정하면 카드 목록이 바뀜

아쉬운 점

  • 모든 카드 데이터가 WorksSection.js에 길게 들어 있음
  • main.js가 여러 기능을 한 파일에서 모두 담당함
  • innerHTML로 attribute 값을 바로 넣기 때문에 외부 입력을 받을 경우 XSS 주의가 필요함

현재처럼 본인이 관리하는 정적 데이터라면 큰 문제는 아니지만, 외부 사용자 입력이 들어오면 문자열 정제가 필요합니다.