내가 Cartlify를 만든 이유 — React용 실전 전자상거래 UI 키트
출처: Dev.to
10년 넘게 같은 컴포넌트를 다시 만들다 보니, 드디어 하나로 묶었습니다.
제가 참여한 모든 이커머스 프로젝트—Fidelity Investments, OCBC Bank, Mondi Group—는 같은 방식으로 시작했습니다.
Day 1: ProductCard를 만든다.
그리고 다음 프로젝트에서도 똑같이 반복한다.
이 과정을 여러 번 겪으면서 깨달은 점은, 시간 낭비라는 것입니다.
프로젝트마다 컴포넌트는 크게 변하지 않으며, 로직도, 접근성 요구사항도, 엣지 케이스도 모두 동일합니다.
그래서 저는 Cartlify를 만들었습니다 — React + TypeScript + Tailwind CSS 기반의 이커머스 UI 전용 컴포넌트 라이브러리입니다.
모든 이커머스 앱이 첫날부터 필요로 하는 컴포넌트입니다.
- 3가지 레이아웃 변형 — 기본(세로), 가로, 콤팩트
- 썸네일 네비게이션이 있는 이미지 갤러리
- 위시리스트 토글(채워진/윤곽선 하트)
- 세일 / 신규 / 품절 배지
- 별점 표시
animate-pulse가 적용된 스켈레톤 로딩 상태
원가(originalPrice)에서 자동으로 할인 %를 계산
addToCart(p)}
onWishlistToggle={(p) => toggleWishlist(p)}
/>
모든 기능을 바로 사용할 수 있는 슬라이드‑인 카트 드로어.
- 오른쪽(또는 왼쪽)에서 부드럽게 슬라이드 인
- 포커스 트랩 — 열려 있을 때 키보드 포커스가 드로어 안에 머무름
- ESC 키로 드로어 닫기
- 최소/최대 제어가 가능한 수량 스테퍼
- 커스텀 아이콘을 지원하는 빈 카트 상태
- 자동 계산된 소계
- 고정 헤더 + 스크롤 가능한 아이템 리스트 + 고정 푸터
const { isOpen, onOpen, onClose } = useDisclosure();
체크아웃 흐름을 위한 다단계 진행 표시기.
- 가로 및 세로 방향 지원
- 단계 사이에 애니메이션 연결선
- 세 가지 단계 상태: 완료, 현재, 대기
- 완료된 단계 클릭 시 뒤로 이동
- 단계별 커스텀 아이콘
- 키보드 네비게이션(화살표 키)
setStep(index)}
/>
4가지 애니메이션 스타일(스핀, 펄스, 바운스, 도트)과 3가지 위치 모드(인라인, 오버레이, 풀스크린).
Cartlify에 포함된 4가지 컴포넌트를 넘어선 추가 요소
- 3개의 유틸리티 훅 —
useCart,useDisclosure,useMediaQuery - 11개의 트리‑쉐이킹 가능한 아이콘 — 카트, 하트, 별, 휴지통, 체브론 등
- 40개 이상의 CSS 디자인 토큰 — 스페이싱, 색상, 라디우스, 그림자 등
- 기본 제공 다크 모드 지원
- 내부에서 재사용되는 프리미티브 —
Button,Badge,IconButton
이 라이브러리를 데모용이 아니라 프로덕션용으로 만들었습니다. 모든 결정은 실제 서비스 배포를 염두에 두고 이루어졌습니다.
- 141개의 Jest + React Testing Library 테스트가 인터랙션, 접근성, 엣지 케이스, 키보드 동작을 모두 커버
PASS src/components/CartDrawer/CartDrawer.test.tsx
PASS src/components/ProductCard/ProductCard.test.tsx
PASS src/components/CheckoutStepper/CheckoutStepper.test.tsx
Test Suites: 12 passed
Tests: 141 passed
모든 컴포넌트는 WCAG 2.1 AA를 준수합니다.
CartDrawer에aria-modal,role="dialog"- 현재 단계에
aria-current="step" ProductCard에role="article"- 모든 아이콘 버튼에
aria-label
전체 키보드 네비게이션 지원
Strict mode, zero any. 모든 prop과 이벤트 핸들러에 타입이 지정됩니다.
interface ProductCardProps {
product: Product;
variant?: 'default' | 'horizontal' | 'compact';
showRating?: boolean;
isWishlisted?: boolean;
onAddToCart: (product: Product) => void;
onWishlistToggle?: (product: Product) => void;
}
Vite, Next.js, Remix 등 현대적인 번들러와 호환됩니다. ESM + CJS 형태로 배포되며, tsup을 통해 .d.ts 타입 정의 파일도 함께 제공합니다.
| Layer | Choice |
|---|---|
| Framework | React 18 |
| Language | TypeScript (strict) |
| Styling | Tailwind CSS v3 |
| Documentation | Storybook v7 |
| Testing | Jest + React Testing Library |
| Build | tsup |
| Linting | ESLint + Prettier |
src/
├── components/
│ ├── ProductCard/
│ ├── CartDrawer/
│ ├── CheckoutStepper/
│ └── PageLoader/
├── primitives/
│ ├── Button/
│ ├── Badge/
│ └── IconButton/
├── hooks/
│ ├── useCart.ts
│ ├── useDisclosure.ts
│ └── useMediaQuery.ts
├── icons/
├── tokens/
└── types/
경로 별칭을 사용해 ../../ 같은 상대 경로를 없앴습니다.
import { Button } from '@primitives/Button';
import { useCart } from '@hooks/useCart';
import type { Product } from '@types';
각 컴포넌트는 모든 변형, 상태, 엣지 케이스를 다루는 인터랙티브 Storybook 스토리를 제공합니다. 구매 전 라이브 Storybook을 직접 체험해 보세요.
Live demo → https://cartlify.vercel.app/
Cartlify는 Gumroad에서 $29에 판매됩니다 — 일회성 결제, 단일 사이트 라이선스.
🛒 Gumroad → https://karthiksoftengg.gumroad.com/l/cartlify-react-ui-kit
앞으로 추가 예정인 기능
- 필터 사이드바가 있는
ProductGrid - 제안 기능이 있는
SearchBar ReviewCard+RatingInputWishlistDrawer- 더 많은 디자인 토큰 테마
보고 싶은 컴포넌트가 있다면 댓글로 알려 주세요. 수요에 따라 우선순위를 정하겠습니다.
제작자: Karthik G S — React, TypeScript, React Native 분야에서 10년 이상의 경력을 가진 시니어 프론트엔드 엔지니어.
태그: react, typescript, tailwindcss, storybook, webdev, javascript, frontend, ecommerce, opensource