TIL - 20260723

juni·2026년 7월 23일

TIL

목록 보기
412/468

0723 프론트엔드 실무 심화 (6/N): 컴포넌트 설계, 재사용 구조와 디자인 시스템 기초


✅ 1. 컴포넌트 설계란 무엇인가?

  • 컴포넌트 설계(Component Design)는 화면을 어떤 단위로 나누고, 각 단위가 어떤 역할과 책임을 가지게 할지 정하는 작업입니다.
  • React에서는 화면을 작은 컴포넌트로 나누어 조립합니다.
  • 좋은 컴포넌트 설계는 코드 재사용성, 유지보수성, UI 일관성, 작업 속도에 직접 영향을 줍니다.
페이지
  ↓
섹션
  ↓
컴포넌트
  ↓
작은 UI 요소

➕ 1-1. 컴포넌트 설계가 중요한 이유

  • 같은 버튼, 모달, 테이블, 폼 UI를 반복해서 만들지 않아도 됩니다.
  • 디자인이 화면마다 들쭉날쭉해지는 것을 줄일 수 있습니다.
  • 수정이 필요한 위치가 명확해집니다.
  • 관리자 페이지와 고객 화면을 더 빠르게 확장할 수 있습니다.
  • AI에게 코드를 맡길 때도 일관된 결과를 얻기 쉬워집니다.
나쁜 구조:
화면마다 버튼 스타일이 다름
모달마다 닫기 방식이 다름
폼 에러 메시지 위치가 다름
테이블 로딩 UI가 화면마다 다름

결과:
사용자는 불편하고, 개발자는 계속 같은 코드를 다시 짬

✅ 2. 좋은 컴포넌트의 기준

  • 좋은 컴포넌트는 단순히 재사용 가능한 컴포넌트가 아닙니다.
  • 역할이 명확하고, props가 예측 가능하며, 특정 화면에 과하게 묶여 있지 않아야 합니다.

➕ 2-1. 좋은 컴포넌트 조건

역할이 명확함
이름만 보고 용도를 알 수 있음
props가 과하게 많지 않음
불필요한 비즈니스 로직을 포함하지 않음
스타일이 일관적임
접근성 기본값을 챙김
상태를 필요한 곳에만 가짐

➕ 2-2. 나쁜 컴포넌트 예시

function Button(props: any) {
  return (
    <button
      style={{
        backgroundColor: props.red ? 'red' : props.blue ? 'blue' : 'gray',
        padding: props.big ? 20 : 10,
        borderRadius: props.round ? 999 : 4,
      }}
      onClick={props.onClick}
    >
      {props.text}
    </button>
  );
}

문제점:

props가 any
스타일 기준이 모호함
variant 체계가 없음
text prop만 받아 children 사용 불가
disabled/loading/accessibility 고려 없음

✅ 3. 컴포넌트 분리 기준

  • 컴포넌트를 나눌 때는 “작게 나누기” 자체가 목표가 아닙니다.
  • 의미 있는 책임 단위로 나누는 것이 중요합니다.

➕ 3-1. 분리하면 좋은 경우

같은 UI가 여러 곳에서 반복됨
한 파일이 너무 길어짐
한 컴포넌트가 여러 역할을 함
폼 섹션이 명확히 나뉨
테이블 row/action이 복잡함
로딩/에러/빈 상태가 반복됨

➕ 3-2. 분리하지 않아도 되는 경우

해당 화면에서 한 번만 쓰임
분리하면 props가 더 복잡해짐
아직 구조가 자주 바뀜
단순한 마크업 몇 줄
  • 너무 빨리 공통화하면 오히려 수정이 어려워집니다.
  • 반복이 2~3번 생기고 패턴이 보일 때 공통화하는 것이 안전합니다.

✅ 4. 페이지 컴포넌트와 UI 컴포넌트 분리

  • 실무에서는 페이지 컴포넌트와 UI 컴포넌트를 구분하면 구조가 깔끔해집니다.
구분역할예시
Page Component데이터 조회, URL 상태, 페이지 흐름AdminConsultPage
Feature Component특정 기능 UIConsultSearchForm, ConsultTable
UI Component재사용 가능한 순수 UIButton, Modal, Input
Layout Component공통 레이아웃AdminLayout, PageHeader

➕ 4-1. 나쁜 구조

function AdminConsultPage() {
  // URL 파싱
  // API 조회
  // 검색 폼
  // 테이블
  // 모달
  // 상태 변경
  // 페이지네이션
  // 전부 한 파일에 있음
}
  • 처음엔 빠르지만 나중에 수정하기 어렵습니다.
  • AI가 수정할 때도 의도치 않은 부분까지 건드릴 가능성이 커집니다.

➕ 4-2. 좋은 구조

AdminConsultPage
  ├─ ConsultSearchForm
  ├─ ActiveFilterChips
  ├─ ConsultTableToolbar
  ├─ ConsultTable
  ├─ Pagination
  ├─ ConsultDetailModal
  └─ UpdateConsultStatusModal
  • 페이지는 전체 흐름을 관리하고, 세부 UI는 컴포넌트로 분리합니다.
  • 각 컴포넌트 역할이 명확하면 유지보수가 쉬워집니다.

✅ 5. Presentational Component와 Container Component

  • 컴포넌트를 나누는 고전적인 기준 중 하나가 Presentational Component와 Container Component입니다.
  • 요즘은 엄격하게 나누지 않아도 되지만, 개념을 알면 구조를 잡는 데 도움이 됩니다.
구분역할
PresentationalUI 표시 중심
Container데이터 조회, 상태 관리, 이벤트 처리

➕ 5-1. Presentational 예시

type EmptyStateProps = {
  title: string;
  description?: string;
  action?: React.ReactNode;
};

function EmptyState({ title, description, action }: EmptyStateProps) {
  return (
    <div className="empty-state">
      <strong>{title}</strong>
      {description && <p>{description}</p>}
      {action && <div>{action}</div>}
    </div>
  );
}
  • 이 컴포넌트는 API를 호출하지 않습니다.
  • props로 받은 값을 화면에 표시합니다.

➕ 5-2. Container 예시

function AdminConsultPage() {
  const { page, status, keyword } = useConsultSearchParams();

  const consultsQuery = useQuery({
    queryKey: ['admin', 'consults', { page, status, keyword }],
    queryFn: () =>
      adminConsultApi.getConsults({
        page,
        status,
        keyword,
      }),
  });

  return (
    <ConsultTableSection
      query={consultsQuery}
    />
  );
}
  • 데이터 조회와 화면 조립은 Container 쪽에서 담당합니다.
  • UI 컴포넌트는 가능한 한 재사용 가능하게 유지합니다.

✅ 6. 공통 UI 컴포넌트

  • 공통 UI 컴포넌트는 프로젝트 전체에서 반복 사용되는 기본 UI입니다.
  • 처음부터 엄청 큰 디자인 시스템을 만들 필요는 없지만, 자주 쓰는 요소는 통일하는 것이 좋습니다.

➕ 6-1. 공통화하면 좋은 컴포넌트

Button
Input
Select
Checkbox
Radio
Textarea
Modal
ConfirmDialog
Toast
Badge
Tabs
Table
Pagination
EmptyState
ErrorState
Skeleton
PageHeader
Card

➕ 6-2. 공통화 우선순위

1순위:
Button, Input, Modal, Toast, Badge

2순위:
Table, Pagination, EmptyState, ErrorState

3순위:
Tabs, Card, Skeleton, FormField

4순위:
고급 테이블, 파일 업로드, 날짜 선택기
  • 버튼, 입력창, 모달만 통일해도 화면 품질이 많이 올라갑니다.
  • 공통 UI는 고객 화면과 관리자 화면의 톤을 나눌 수도 있습니다.

✅ 7. Button 컴포넌트 설계

  • 버튼은 가장 자주 쓰이는 컴포넌트입니다.
  • variant, size, loading, disabled 상태를 기본으로 지원하면 좋습니다.

➕ 7-1. Button props 예시

type ButtonProps = {
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  isLoading?: boolean;
  disabled?: boolean;
  children: React.ReactNode;
} & React.ButtonHTMLAttributes<HTMLButtonElement>;

➕ 7-2. 사용 예시

<Button variant="primary" size="md">
  저장
</Button>

<Button variant="danger" isLoading={deleteMutation.isPending}>
  삭제
</Button>

<Button variant="secondary" disabled>
  권한 없음
</Button>

➕ 7-3. 기준

primary:
주요 행동

secondary:
보조 행동

danger:
삭제, 취소, 위험 작업

ghost:
덜 중요한 액션
  • 버튼 스타일 기준이 명확해야 사용자가 어떤 액션이 중요한지 알 수 있습니다.
  • 위험 작업은 색상뿐 아니라 confirm도 함께 필요합니다.

✅ 8. FormField 컴포넌트

  • 폼에서는 label, input, error message, help text가 반복됩니다.
  • 이를 FormField로 정리하면 폼 UI가 일관됩니다.

➕ 8-1. 구조 예시

type FormFieldProps = {
  label: string;
  required?: boolean;
  error?: string;
  description?: string;
  children: React.ReactNode;
};

function FormField({
  label,
  required,
  error,
  description,
  children,
}: FormFieldProps) {
  return (
    <div className="form-field">
      <label>
        {label}
        {required && <span aria-hidden="true">*</span>}
      </label>

      {children}

      {description && <p className="field-description">{description}</p>}

      {error && (
        <p role="alert" className="field-error">
          {error}
        </p>
      )}
    </div>
  );
}

➕ 8-2. 사용 예시

<FormField
  label="전화번호"
  required
  error={form.formState.errors.phone?.message}
  description="하이픈 없이 입력해 주세요."
>
  <Input
    type="tel"
    inputMode="numeric"
    {...form.register('phone')}
  />
</FormField>
  • 폼 에러 위치와 라벨 표시가 화면마다 달라지는 것을 막을 수 있습니다.
  • 접근성도 공통 컴포넌트에서 챙기기 쉬워집니다.

✅ 9. Modal 컴포넌트 설계

  • 모달은 상담 신청, 상태 변경, 삭제 확인, 상세 보기에서 자주 사용됩니다.
  • 모달의 열림/닫힘, title, footer, 닫기 버튼, ESC 처리, backdrop 클릭 기준을 통일하는 것이 좋습니다.

➕ 9-1. Modal props 예시

type ModalProps = {
  open: boolean;
  title: string;
  onClose: () => void;
  children: React.ReactNode;
  footer?: React.ReactNode;
  closeOnBackdrop?: boolean;
};

➕ 9-2. 사용 예시

<Modal
  open={isOpen}
  title="상담 상세"
  onClose={closeModal}
  footer={
    <Button variant="secondary" onClick={closeModal}>
      닫기
    </Button>
  }
>
  <ConsultDetail consult={consult} />
</Modal>

➕ 9-3. 모달 기준

상세 확인:
닫기 쉬워야 함

중요 작업:
실수로 닫히지 않게 주의

폼 입력:
저장하지 않은 변경사항이 있으면 이탈 확인

삭제/상태 변경:
ConfirmDialog 사용
  • 모달은 편하지만 너무 많이 중첩되면 UX가 나빠집니다.
  • 모달 안에서 또 모달을 띄우는 구조는 최대한 피하는 것이 좋습니다.

✅ 10. Badge 컴포넌트

  • 상태값은 Badge로 표시하면 테이블 가독성이 좋아집니다.
  • 상담 상태, 주문 상태, ExportJob 상태, Webhook 상태 등에 사용할 수 있습니다.

➕ 10-1. 상태 Badge 예시

type BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info';

type BadgeProps = {
  variant?: BadgeVariant;
  children: React.ReactNode;
};

function Badge({ variant = 'default', children }: BadgeProps) {
  return (
    <span className={`badge badge-${variant}`}>
      {children}
    </span>
  );
}

➕ 10-2. 상담 상태 매핑

const CONSULT_STATUS_LABEL = {
  PENDING: '대기',
  CALLING: '상담중',
  DONE: '완료',
  CANCELLED: '취소',
} as const;

const CONSULT_STATUS_VARIANT = {
  PENDING: 'warning',
  CALLING: 'info',
  DONE: 'success',
  CANCELLED: 'default',
} as const;

function ConsultStatusBadge({ status }: { status: ConsultStatus }) {
  return (
    <Badge variant={CONSULT_STATUS_VARIANT[status]}>
      {CONSULT_STATUS_LABEL[status]}
    </Badge>
  );
}
  • 상태 라벨과 색상 기준을 한 곳에 모으면 유지보수가 쉽습니다.
  • 백엔드 enum이 바뀌면 이 매핑도 함께 확인해야 합니다.

✅ 11. EmptyState / ErrorState / LoadingState

  • 로딩, 에러, 빈 상태는 여러 화면에서 반복됩니다.
  • 공통 컴포넌트로 만들면 화면 품질이 안정됩니다.

➕ 11-1. EmptyState

type EmptyStateProps = {
  title: string;
  description?: string;
  action?: React.ReactNode;
};

function EmptyState({ title, description, action }: EmptyStateProps) {
  return (
    <div className="empty-state">
      <strong>{title}</strong>
      {description && <p>{description}</p>}
      {action && <div>{action}</div>}
    </div>
  );
}

➕ 11-2. ErrorState

type ErrorStateProps = {
  title?: string;
  message: string;
  onRetry?: () => void;
};

function ErrorState({
  title = '문제가 발생했습니다',
  message,
  onRetry,
}: ErrorStateProps) {
  return (
    <div role="alert" className="error-state">
      <strong>{title}</strong>
      <p>{message}</p>
      {onRetry && (
        <Button variant="secondary" onClick={onRetry}>
          다시 시도
        </Button>
      )}
    </div>
  );
}
  • Empty와 Error를 구분해서 컴포넌트화하면 목록 화면을 만들 때 빠릅니다.
  • 메시지만 잘 바꿔도 화면이 자연스럽습니다.

✅ 12. Table 컴포넌트 설계

  • 테이블은 너무 빨리 완전 공통화하면 복잡해질 수 있습니다.
  • 처음에는 AdminTable, TableHeader, TableRow, Pagination 정도로 나눠도 충분합니다.

➕ 12-1. 단순 Table 구조

function AdminTable({
  columns,
  children,
}: {
  columns: string[];
  children: React.ReactNode;
}) {
  return (
    <table className="admin-table">
      <thead>
        <tr>
          {columns.map((column) => (
            <th key={column}>{column}</th>
          ))}
        </tr>
      </thead>
      <tbody>{children}</tbody>
    </table>
  );
}

➕ 12-2. 사용 예시

<AdminTable
  columns={['신청일', '고객명', '전화번호', '상품명', '상태', '액션']}
>
  {consults.map((consult) => (
    <ConsultTableRow key={consult.id} consult={consult} />
  ))}
</AdminTable>
  • 컬럼 정의, 정렬, 선택, 고정 컬럼이 복잡해지면 TanStack Table 도입을 검토하면 됩니다.
  • 처음부터 모든 기능을 직접 만들려고 하면 시간이 많이 듭니다.

✅ 13. 컴포넌트 props 설계

  • props는 컴포넌트의 사용성을 결정합니다.
  • props가 너무 많거나 의미가 모호하면 재사용이 어려워집니다.

➕ 13-1. 나쁜 props

<Button
  red
  big
  round
  text="삭제"
  loading={false}
  customType="delete"
/>

➕ 13-2. 좋은 props

<Button
  variant="danger"
  size="md"
  isLoading={deleteMutation.isPending}
>
  삭제
</Button>

➕ 13-3. props 설계 기준

boolean props를 너무 많이 만들지 않기
variant/size 같은 명확한 체계 사용
children을 활용하기
이벤트 핸들러 이름은 onClick, onClose, onSubmit처럼 통일
컴포넌트 내부에서 너무 많은 비즈니스 판단을 하지 않기
  • props는 사용하는 사람이 헷갈리지 않게 설계해야 합니다.
  • “이 prop을 넣으면 어떤 UI가 되는지” 예측 가능해야 합니다.

✅ 14. Compound Component 패턴

  • 컴포넌트가 복잡해질 때는 Compound Component 패턴을 사용할 수 있습니다.
  • 예를 들어 Modal 안에 Header, Body, Footer를 조합하는 방식입니다.

➕ 14-1. 예시

<Modal open={open} onClose={onClose}>
  <Modal.Header>상담 상세</Modal.Header>
  <Modal.Body>
    <ConsultDetail consult={consult} />
  </Modal.Body>
  <Modal.Footer>
    <Button variant="secondary" onClick={onClose}>
      닫기
    </Button>
  </Modal.Footer>
</Modal>

➕ 14-2. 장점

구조가 명확함
footer/header 커스터마이징 쉬움
children 조합이 자연스러움
복잡한 props를 줄일 수 있음

➕ 14-3. 주의점

  • 너무 이른 시점에 도입하면 오히려 복잡해질 수 있습니다.
  • 기본 Modal props 방식으로 충분하다면 굳이 도입하지 않아도 됩니다.

✅ 15. 디자인 시스템이란 무엇인가?

  • 디자인 시스템(Design System)은 서비스의 UI 규칙과 재사용 가능한 컴포넌트 체계입니다.
  • 색상, 폰트, 간격, 버튼, 폼, 모달, 테이블, 상태 표시 같은 기준을 모아둔 것입니다.
  • 큰 회사처럼 거창하게 만들 필요는 없고, 작은 프로젝트에서는 “UI 규칙 문서 + 공통 컴포넌트” 정도로 시작하면 됩니다.
디자인 토큰
  ↓
공통 컴포넌트
  ↓
UI 패턴
  ↓
사용 가이드

➕ 15-1. 디자인 시스템이 필요한 이유

  • 화면마다 버튼/간격/색상이 달라지는 것을 줄입니다.
  • 새 화면을 만들 때 속도가 빨라집니다.
  • 고객 화면과 관리자 화면의 품질이 일정해집니다.
  • AI에게 UI 작업을 맡길 때 기준을 줄 수 있습니다.
  • 유지보수와 리디자인이 쉬워집니다.

✅ 16. 디자인 토큰

  • 디자인 토큰(Design Token)은 색상, 폰트 크기, 간격, radius, shadow 같은 기본 디자인 값을 변수화한 것입니다.

➕ 16-1. 토큰 예시

export const tokens = {
  color: {
    primary: '#2563eb',
    danger: '#dc2626',
    success: '#16a34a',
    warning: '#f59e0b',
    text: '#111827',
    muted: '#6b7280',
    border: '#e5e7eb',
    background: '#ffffff',
  },
  radius: {
    sm: '4px',
    md: '8px',
    lg: '12px',
  },
  spacing: {
    xs: '4px',
    sm: '8px',
    md: '16px',
    lg: '24px',
    xl: '32px',
  },
};

➕ 16-2. 토큰이 없을 때 문제

파란색이 화면마다 조금씩 다름
버튼 radius가 제각각
카드 padding이 제각각
텍스트 크기가 화면마다 다름
  • 처음부터 복잡하게 만들 필요는 없습니다.
  • 색상, spacing, radius부터 정리해도 효과가 큽니다.

✅ 17. UI Variant 체계

  • 컴포넌트는 variant 체계를 가져야 일관성이 생깁니다.
  • 특히 Button, Badge, Alert, Toast, Modal action에서 중요합니다.

➕ 17-1. Button Variant

primary:
주요 액션

secondary:
보조 액션

danger:
삭제/취소/위험 액션

ghost:
가벼운 액션

➕ 17-2. Alert Variant

info:
일반 안내

success:
성공 안내

warning:
주의 필요

error:
실패/오류

➕ 17-3. Badge Variant

default:
기본 상태

success:
완료/성공

warning:
대기/주의

danger:
실패/취소

info:
진행 중/정보
  • variant 이름은 기능보다 의미 중심으로 정하는 것이 좋습니다.
  • red, blue보다 danger, primary가 유지보수에 좋습니다.

✅ 18. 고객 화면과 관리자 화면의 UI 기준 차이

  • 고객 화면과 관리자 화면은 목적이 다릅니다.
  • 같은 컴포넌트를 쓰더라도 톤과 정보 밀도가 달라야 합니다.
구분고객 화면관리자 화면
목적구매/상담 전환업무 처리
톤쉽고 친절함명확하고 효율적
정보량핵심만필요한 정보 충분히
버튼전환 중심작업 중심
에러 메시지안심/재시도 안내원인/다음 행동 안내
테이블거의 없음핵심 UI

➕ 18-1. 고객용 버튼

상담 신청하기
혜택 확인하기
가입 조건 확인하기

➕ 18-2. 관리자용 버튼

저장
상태 변경
엑셀 다운로드
재처리
삭제
  • 고객 화면은 망설임을 줄이는 것이 중요합니다.
  • 관리자 화면은 실수 없이 빠르게 처리하는 것이 중요합니다.

✅ 19. 폴더 구조

  • 컴포넌트가 많아지면 폴더 구조가 중요해집니다.
  • 공통 컴포넌트, 기능별 컴포넌트, 페이지 컴포넌트를 나누면 좋습니다.

➕ 19-1. 예시 구조

src/
  components/
    ui/
      Button/
      Input/
      Modal/
      Badge/
      EmptyState/
      ErrorState/
    layout/
      AdminLayout/
      PageHeader/
  features/
    consults/
      components/
        ConsultSearchForm.tsx
        ConsultTable.tsx
        ConsultDetailModal.tsx
      hooks/
        useConsultSearchParams.ts
      api/
        consultApi.ts
    products/
      components/
      hooks/
      api/
  pages/
    admin/
      consults/
      products/
  lib/
    queryClient.ts
    apiClient.ts
  styles/
    tokens.ts

➕ 19-2. 기준

components/ui:
프로젝트 전체에서 쓰는 순수 UI

features:
도메인별 기능 컴포넌트

pages:
라우팅 단위 페이지

lib:
공통 API client, queryClient, 유틸

styles:
토큰, 공통 스타일
  • 기능별 폴더를 만들면 관련 코드가 모여 있어 수정하기 편합니다.
  • 공통 UI와 도메인 기능 컴포넌트를 섞지 않는 것이 중요합니다.

✅ 20. 컴포넌트 네이밍 기준

  • 이름만 봐도 역할을 알 수 있어야 합니다.

➕ 20-1. 좋은 이름

ConsultSearchForm
ConsultTable
ConsultDetailModal
UpdateConsultStatusModal
ProductImageUploader
AdminPageHeader
ExportJobStatusBadge

➕ 20-2. 나쁜 이름

Box
CustomModal
CommonComponent
DataList
TempTable
NewButton

➕ 20-3. 기준

도메인 + 역할:
ConsultTable
ProductForm

상태 + UI:
ErrorState
EmptyState

행동 + 대상:
UpdateConsultStatusModal
CreateProductButton
  • 이름이 명확하면 코드 탐색이 쉬워집니다.
  • AI에게 수정을 맡길 때도 어떤 컴포넌트를 건드려야 하는지 분명해집니다.

✅ 21. 컴포넌트 테스트 관점

  • 모든 컴포넌트를 테스트할 필요는 없지만, 중요한 UI 로직은 테스트할 가치가 있습니다.

➕ 21-1. 테스트하면 좋은 컴포넌트

권한 기반 버튼 노출
상태 Badge 라벨
검색 폼 URL 업데이트
폼 유효성 검증
Empty/Error 상태 렌더링
대량 작업 Confirm

➕ 21-2. 테스트 관점 예시

VIEWER 권한:
상태 변경 버튼이 보이지 않아야 함

ADMIN 권한:
상태 변경 버튼이 보여야 함

CONSULT_STATUS DONE:
완료 Badge가 표시되어야 함
  • UI 테스트는 모든 스타일을 확인하는 것이 아니라, 중요한 조건부 렌더링을 확인하는 데 집중하면 됩니다.

✅ 22. Storybook 개념

  • Storybook은 컴포넌트를 독립적으로 확인하고 문서화할 수 있는 도구입니다.
  • 작은 프로젝트에서 필수는 아니지만, 공통 UI가 많아지면 도움이 됩니다.

➕ 22-1. Storybook이 유용한 경우

공통 Button/Modal/Input이 많음
디자인 상태를 한눈에 보고 싶음
로딩/에러/빈 상태를 독립적으로 확인하고 싶음
디자이너/기획자와 UI를 공유하고 싶음

➕ 22-2. Story 예시

Button / Primary
Button / Danger
Modal / Basic
EmptyState / No Search Result
ErrorState / With Retry
Badge / Consult Status
  • 지금 당장 도입하지 않아도 됩니다.
  • 다만 공통 컴포넌트가 많아질수록 Storybook이 문서 역할을 할 수 있습니다.

✅ 23. AI를 활용한 컴포넌트 생성 기준

  • AI에게 컴포넌트를 만들게 할 때는 디자인 기준, props 체계, 접근성, 상태 처리를 명확히 줘야 합니다.
  • “버튼 컴포넌트 만들어줘”라고 하면 프로젝트와 안 맞는 코드가 나올 수 있습니다.

➕ 23-1. 좋은 요청 예시

React + TypeScript로 공통 Button 컴포넌트를 만들어줘.

조건:
1. variant는 primary, secondary, danger, ghost
2. size는 sm, md, lg
3. isLoading 상태 지원
4. disabled 상태 지원
5. children 사용
6. button 기본 속성을 받을 수 있게 설계
7. 접근성 고려
8. className 확장 가능
9. 과하게 복잡한 스타일 라이브러리는 쓰지 않기
10. 사용 예시 포함

➕ 23-2. AI 결과 검증 기준

props가 명확한가?
any를 쓰지 않았는가?
기존 디자인 기준과 맞는가?
접근성을 해치지 않는가?
불필요한 라이브러리를 추가하지 않았는가?
프로젝트 스타일 방식과 맞는가?
재사용 가능한 구조인가?
  • AI가 만든 컴포넌트도 실제 프로젝트 기준에 맞춰 검수해야 합니다.

✅ 24. 실무 체크리스트

➕ 24-1. 컴포넌트 설계 체크리스트

  1. 컴포넌트 역할이 이름만 봐도 명확한가?
  2. 한 컴포넌트가 너무 많은 책임을 갖고 있지 않은가?
  3. 재사용 가능한 UI와 도메인 기능 컴포넌트가 분리되어 있는가?
  4. props가 과하게 많거나 모호하지 않은가?
  5. 반복되는 UI를 적절히 공통화했는가?
  6. 너무 이른 공통화로 오히려 복잡해지지 않았는가?
  7. 로딩/에러/빈 상태 컴포넌트가 통일되어 있는가?
  8. 접근성 기본값을 고려했는가?

➕ 24-2. 디자인 시스템 체크리스트

  1. Button variant 기준이 있는가?
  2. Badge 상태 기준이 있는가?
  3. Alert/Toast 메시지 기준이 있는가?
  4. 색상, 간격, radius 같은 토큰이 정리되어 있는가?
  5. 고객 화면과 관리자 화면의 UI 톤이 구분되는가?
  6. 공통 FormField가 있는가?
  7. Modal/ConfirmDialog 사용 기준이 있는가?
  8. 새 화면을 만들 때 참고할 UI 규칙이 있는가?

➕ 24-3. 폴더 구조 체크리스트

  1. 공통 UI 컴포넌트가 components/ui에 모여 있는가?
  2. 도메인 기능 컴포넌트가 features 단위로 나뉘어 있는가?
  3. API 호출 코드가 화면 컴포넌트에 과하게 섞이지 않았는가?
  4. hook, api, component 역할이 구분되어 있는가?
  5. 컴포넌트 이름이 도메인과 역할을 드러내는가?
  6. 공통 컴포넌트와 페이지 전용 컴포넌트가 섞이지 않았는가?
  7. AI가 수정하기 쉬운 구조인가?
  8. 새 기능 추가 시 어디에 파일을 둘지 기준이 있는가?

✅ 25. AI를 활용해 컴포넌트/디자인 시스템을 설계할 때 질문법

  • AI에게 컴포넌트 구조를 요청할 때는 현재 화면 종류, 자주 반복되는 UI, 사용하는 라이브러리, 스타일 방식, 고객/관리자 화면 구분을 알려줘야 합니다.

➕ 25-1. 좋은 질문 예시

React + TypeScript 기반 온라인 휴대폰 판매몰 프론트엔드에서 공통 컴포넌트와 디자인 시스템 기초를 정리하고 싶어.

상황:
1. 고객 화면에는 상품 목록, 상품 상세, 상담 신청 모달이 있음
2. 관리자 화면에는 상담 목록, 주문 목록, 상품 관리, 배너 관리, 엑셀 다운로드가 있음
3. 공통으로 Button, Input, Modal, Badge, EmptyState, ErrorState, Pagination이 반복됨
4. 관리자 화면에서는 테이블, 상태 배지, ConfirmDialog가 자주 사용됨
5. 고객 화면은 친절하고 전환 중심이어야 하고, 관리자 화면은 명확하고 업무 처리 중심이어야 함
6. TypeScript를 사용하고 props 타입을 명확히 하고 싶음
7. 너무 큰 디자인 시스템보다는 실무에서 바로 쓸 수 있는 작은 구조부터 원함

요청:
- 컴포넌트 분리 기준
- 공통 UI 컴포넌트 우선순위
- Button/Input/Modal/Badge props 설계
- FormField 구조
- EmptyState/ErrorState 구조
- 폴더 구조
- 디자인 토큰 기초
- 고객/관리자 UI 기준 차이
- AI에게 컴포넌트 생성을 맡길 때 프롬프트
를 실무 기준으로 정리해줘.

➕ 25-2. AI 답변 검증 기준

  1. 모든 것을 과하게 공통화하라고 하지 않는가?
  2. 공통 UI와 도메인 컴포넌트를 구분하는가?
  3. Button variant, size, loading, disabled 기준을 제안하는가?
  4. Modal, FormField, Badge처럼 반복되는 UI를 우선 정리하는가?
  5. 고객 화면과 관리자 화면의 목적 차이를 반영하는가?
  6. props 타입을 명확히 잡는가?
  7. 접근성과 로딩/에러/빈 상태를 고려하는가?
  8. 현재 프로젝트 규모에 맞게 현실적인 구조인가?

📌 요약

  • 컴포넌트 설계는 화면을 어떤 단위로 나누고 각 단위가 어떤 책임을 갖게 할지 정하는 작업입니다.
  • 좋은 컴포넌트는 역할이 명확하고, props가 예측 가능하며, 특정 화면에 과하게 묶여 있지 않습니다.
  • 페이지 컴포넌트는 데이터 조회와 화면 흐름을 담당하고, 공통 UI 컴포넌트는 Button, Input, Modal, Badge처럼 반복되는 UI를 담당하게 나누면 좋습니다.
  • 컴포넌트는 너무 빨리 공통화하면 오히려 복잡해질 수 있으므로, 반복 패턴이 보일 때 공통화하는 것이 안전합니다.
  • Button은 variant, size, loading, disabled 기준을 갖추고, Modal은 title, open, onClose, footer 같은 기준을 통일하면 좋습니다.
  • FormField, EmptyState, ErrorState, Badge 같은 컴포넌트는 화면 품질과 유지보수성을 크게 올려줍니다.
  • 디자인 시스템은 거창한 것이 아니라 색상, 간격, radius, 버튼 종류, 상태 배지, 모달 기준 같은 UI 규칙을 정리하는 것부터 시작하면 됩니다.
  • 고객 화면은 전환과 안심이 중요하고, 관리자 화면은 업무 속도와 정확성이 중요하므로 UI 톤과 정보 밀도를 다르게 봐야 합니다.
  • 폴더 구조는 components/ui, features, pages, lib, styles처럼 역할별로 나누면 기능이 커져도 관리하기 쉽습니다.
  • AI에게 컴포넌트를 만들게 할 때는 props 체계, variant, 접근성, 기존 스타일 기준을 명확히 제공해야 프로젝트에 맞는 결과물을 얻을 수 있습니다.

0개의 댓글