Design System

ipvelo AI 디자인 시스템

assets/const.less 토큰과 상표 검토, OA 대응, IP 자산 관리 화면에서 반복 사용하는 UI 패턴을 한 화면에서 확인합니다.
54 컬러 토큰24 컴포넌트 패턴

01

컬러 팔레트

assets/const.less 에 실제 선언된 컬러 토큰입니다. 기본 포인트 컬러는 항상 #3182F6을 유지합니다.

Primary 컬러

핵심 CTA, 활성 상태, 주요 강조 영역에 사용합니다. 브랜드 포인트는 이 계열만 씁니다.

텍스트 컬러

본문 위계, 보조 설명, 비활성 텍스트, placeholder에 사용합니다.

배경 컬러

페이지 배경, 카드 내부, hover, disabled 상태에 사용합니다.

테두리 컬러

입력 필드, 카드, 포커스 상태, 섹션 구분선에 사용합니다.

상태 컬러

성공, 오류, 경고, 정보 피드백에 사용합니다.

상태 Alias 컬러

const.less의 insure-* alias는 과거 명칭이지만 현재 화면에서는 정보, 완료, 주의 상태 alias로만 해석합니다.

레거시 Alias 컬러

기존 화면 호환 토큰입니다. 새 화면은 primary, text, background, border 토큰을 우선합니다.

구독 플랜 그라데이션

const.less에 선언된 결제/구독 플랜용 그라데이션입니다. 기본 화면 배경이나 새 브랜드 색으로 확장하지 않습니다.

02

토큰 조합 예시

상표 검토, OA 대응, 모니터링 화면에서 토큰 조합이 쓰이는 방식입니다.
Primary CTA 상표 검토 시작

주요 업무 흐름의 다음 액션은 primary + white 조합으로 즉시 인지되게 합니다.

@primary-color + @background-primary
Info Panel AI 분석 진행

OA PDF 분석, 후보 매칭처럼 진행 중인 상태에는 밝은 정보 배경을 씁니다.

@info-bg + @info-color + @text-primary
Error 검토 실패 / 거절 위험

입력 오류, 분석 실패, 높은 거절 위험에는 error 계열을 사용합니다.

@error-bg + @error-color + @error-lighter
Success 등록 / 저장 완료

등록, 저장 완료, 검토 확정처럼 긍정 상태에는 success 계열을 씁니다.

@success-bg + @success-color
Warning 추가 검토 필요

유사 후보가 있거나 자동 판단이 애매할 때 warning 계열로 재확인을 유도합니다.

@warning-bg + @warning-color + @warning-border
Surface 증거 / 결과 카드

판단 근거, 후보 목록, 테이블 배경은 white + border-primary를 기본으로 둡니다.

@background-primary + @border-primary + @text-secondary

03

기반 토큰

컬러 외 레이아웃, 간격, 타이포그래피, 입력, 버튼, 카드 기준값입니다.

그림자

표면의 높이와 포커스 정도를 표현합니다.
@shadow-xs 0 1px 2px rgba(0, 0, 0, 0.04) 작은 표면
@shadow-sm 0 2px 8px rgba(0, 0, 0, 0.08) 기본 카드
@shadow-md 0 4px 16px rgba(49, 130, 246, 0.12) Primary 강조
@shadow-lg 0 8px 24px rgba(0, 0, 0, 0.12) 오버레이
@shadow-xl 0 12px 32px rgba(0, 0, 0, 0.16) 모달
@shadow-2xl 0 16px 40px rgba(0, 0, 0, 0.20) 최상위 레이어

모서리

버튼, 입력, 카드, pill UI의 모서리 기준입니다.
@radius-xs 4px 작은 요소
@radius-sm 6px 배지
@radius-md 8px 기본 카드/버튼
@radius-lg 12px 입력 필드
@radius-xl 16px 큰 카드
@radius-2xl 20px 대형 패널
@radius-3xl 24px 히어로 카드
@radius-round 9999px pill

간격

컴포넌트 내부 여백과 섹션 간격입니다.
@spacing-xs 4px 아이콘과 텍스트
@spacing-sm 8px 작은 gap
@spacing-md 12px 폼 내부
@spacing-lg 16px 컴포넌트 gap
@spacing-xl 20px 카드 내부
@spacing-2xl 24px 섹션 내부
@spacing-3xl 28px 큰 gap
@spacing-4xl 32px 섹션 간격
@spacing-5xl 40px 페이지 블록
@spacing-6xl 48px 대형 블록
@spacing-7xl 56px 상하 여백
@spacing-8xl 64px 최대 여백

타이포그래피

Pretendard 기반 크기, 굵기, 행간 기준입니다.
@font-family-base Pretendard stack 전역 한글 UI 서체
@font-family-mono ui-monospace stack 코드, 토큰, 개발자용 값
@font-xs 12px 보조 메타
@font-sm 13px 라벨
@font-md 14px 테이블
@font-base 15px 본문
@font-lg 16px 버튼
@font-xl 17px 강조 본문
@font-2xl 20px 작은 제목
@font-3xl 22px 패널 제목
@font-4xl 24px 섹션 제목
@font-5xl 26px 페이지 제목
@font-6xl 28px 큰 제목
@font-7xl 32px 히어로 제목
@font-regular 400 일반
@font-medium 500 중간
@font-semibold 600 강조
@font-bold 700 제목/버튼
@line-tight 1.2 짧은 제목
@line-normal 1.5 본문
@line-relaxed 1.6 긴 설명

레이아웃과 레이어

컨테이너, 헤더, z-index 기준입니다.
@header-height 70px 헤더 높이
@container-sm 600px 폼 컨테이너
@container-md 900px 중간 컨테이너
@container-lg 1200px 리스트
@container-xl 1440px 최대 컨테이너
@z-dropdown 1000 드롭다운
@z-sticky 1020 sticky
@z-fixed 1030 고정
@z-modal-backdrop 1040 모달 배경
@z-modal 1050 모달
@z-popover 1060 팝오버
@z-tooltip 1070 툴팁

입력, 버튼, 카드

상호작용 컴포넌트의 기본 치수입니다.
@input-height 52px 입력 높이
@input-padding-x 16px 입력 좌우
@input-padding-y 14px 입력 상하
@input-border-radius @radius-lg 입력 반경
@input-border-color @border-primary 입력 테두리
@input-focus-border @primary-color 입력 포커스
@btn-height-sm 36px 작은 버튼
@btn-height-md 44px 중간 버튼
@btn-height-lg 52px 큰 버튼
@btn-padding-x 20px 버튼 좌우
@btn-padding-y 16px 버튼 상하
@btn-border-radius @radius-lg 버튼 반경
@btn-disabled-bg @background-disabled 비활성 배경
@btn-disabled-color @text-tertiary 비활성 텍스트
@btn-disabled-border @background-disabled 비활성 테두리
@card-padding 24px 카드 내부 여백
@card-border-radius @radius-xl 카드 반경
@card-border-color @border-primary 카드 테두리
@card-bg @background-primary 카드 배경

Empty State

데이터 없음, 초기 설정, 권한 없음처럼 다음 행동이 필요한 상태 화면 기준입니다.
@background-primary #FFFFFF 빈 상태 배경
@border-secondary #D1D6DB 점선 테두리
@radius-xl 16px 패널 반경
@spacing-4xl 32px 상하 여백
@spacing-2xl 24px 좌우 여백
@primary-lighter #F0F7FF 상태 아이콘 배경
@primary-color #3182F6 상태 아이콘 컬러

전환

호버, 입력, 오버레이 전환 속도입니다.
@transition-fast 0.1s ease 짧은 피드백
@transition-base 0.2s ease 기본 전환
@transition-slow 0.3s ease 오버레이

04

서체와 타이포그래피

Pretendard를 기본 서체로 사용하고, 사용처별 크기와 굵기는 제한된 단계로 운영합니다.

Primary Typeface

Pretendard

"Pretendard", "Noto Sans KR", "Apple SD Gothic Neo", "Malgun Gothic", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif 가나다라마바사 ABC 123
Typography Principles
  • 크기보다 정보 위계가 먼저 보이도록 제목, 본문, 보조문을 명확히 나눕니다.
  • 업무 화면은 과장된 장식보다 읽기 속도와 숫자 판독성을 우선합니다.
  • 새 스타일을 만들기보다 정의된 단계 중 가장 가까운 역할을 재사용합니다.

Usage Guide

화면에서 쓰이는 역할별 스타일입니다. 새 UI는 아래 단계 중 가장 가까운 역할을 선택합니다.
상표 검토가 더 빠르고 선명해집니다
Hero / Page Title 랜딩 첫 제목, 주요 페이지 타이틀, 비어 있는 화면의 핵심 메시지
@font-7xl / 700 / 1.2
유사 후보 분석
Section Title 대시보드 섹션, 모달 큰 제목, 설정 그룹 제목
@font-4xl / 700 / 1.25
상표 검토 입력
Panel Title 카드 헤더, 사이드 패널 제목, 표 상단 요약 제목
@font-2xl / 700 / 1.35
상표명과 지정상품을 기준으로 유사 후보를 확인합니다.
Body / Form Value 본문, 입력값, 설명 문장, 드롭다운 선택값
@font-base / 500 / 1.5
IPVELO · 40-2024-0101201 · 검토중
Table / Compact Body 테이블 셀, 리스트 행, 밀도 높은 업무 데이터
@font-md / 500 / 1.5
상표 검토 시작
Label / Button 폼 라벨, 버튼, 탭, 상태 배지
@font-sm / 700 / 1.4
마지막 업데이트 2026.07.01
Caption / Meta 도움말, 보조 메타, 테이블 헤더, 칩 내부 설명
@font-xs / 600 / 1.4

05

프로젝트 컴포넌트 인벤토리

components/ds/DsClayBarChart.vue 와 현재 프로젝트에서 반복되는 업무 화면 패턴, 등록 플러그인을 함께 정리했습니다.
Component Usage Source
v-app Nuxt 레이아웃 루트 layouts/default.vue, layouts/form.vue, layouts/admin.vue
v-icon 액션, 상태, 네비게이션 아이콘 pages/main/*.vue
v-progress-circular 로딩/상태 확인 layouts/default.vue, pages/main.vue
v-dialog + v-card 전역 로딩, 확인 모달 layouts/default.vue, layouts/error.vue
nuxt-link 랜딩, 로그인, 클라이언트 로그인 이동 pages/index.vue, pages/login.vue, pages/clientlogin.vue
nuxt-child 워크스페이스 하위 라우트 렌더링 pages/main.vue, pages/admin.vue
client-only 차트처럼 브라우저 렌더링이 필요한 컴포넌트 components/ds/DsClayBarChart.vue, components/ds/DsLibraryPreview.vue
highcharts 대시보드 차트 위젯 plugins/chart.js, pages/main/dashboard/index.vue
DsClayBarChart 기간별 검토/출원 지표 components/ds/DsClayBarChart.vue
draggable 관리자 카테고리 순서 변경 pages/admin/category/main.vue
swiper / swiper-slide 슬라이더 플러그인 plugins/swiper.js
quill-editor 리치 텍스트 에디터 플러그인 plugins/main.js
vue-toastification 전역 토스트 피드백 plugins/toast.js
Form controls 로그인, 상표 검토, OA 제출, 고객 설정 pages/login.vue, pages/main/trademark/review.vue, pages/main/oa/trademark/report/submit.vue
DsTextNameBox 입력한 상표 명칭을 검토 요청 패널의 정사각형 박스에 표시 components/ds/DsTextNameBox.vue, pages/designsystem.vue
DsScoreRing 상품류/지정상품 추천도 점수를 success, warning, neutral 상태 색상으로 표시 components/ds/DsScoreRing.vue, components/CategoryList.vue, pages/designsystem.vue
DsNumericSpinner 후보 수, 표시 개수, 반복 횟수처럼 정수 값을 빠르게 증감 components/ds/DsNumericSpinner.vue, pages/designsystem.vue
DsSegmentedControl 단일 선택 필터, 검토 범위, 모드 전환 components/ds/DsSegmentedControl.vue, components/ds/DsFormPreview.vue, pages/designsystem.vue
Admin list 검색, 일괄 액션, 상태 칩, 활성 토글이 있는 업무 목록 pages/main/document/notification.vue, components/ds/DsListPreview.vue
DsSwitch 자동화 옵션, 알림 설정, 공개 여부 같은 즉시 반영 토글 components/ds/DsSwitch.vue, pages/designsystem.vue
Dashboard widget KPI, 데이터 테이블, 차트 슬롯 pages/main/dashboard/index.vue
Skeleton system 초기 로딩, 리스트/카드/커스텀 로딩 자리표시자 pages/designsystem.vue
Upload dropzone OA PDF, 특허 자료, IP 자산 파일 첨부 pages/main/oa/trademark/report/submit.vue, pages/main/patent/write.vue
Empty state 데이터 없음/초기 화면 pages/main/dashboard/index.vue, pages/main/team.vue

06

컴포넌트 예시

아래 예시는 실제 ipvelo 업무 화면에서 반복되는 컴포넌트 패턴을 기준으로 구성했습니다.

액션

버튼

.toss-btn, .ghost-action, .commit-button
<button class="toss-btn primary-btn" type="button">상표 검토 시작</button>
<button class="toss-btn secondary-btn" type="button">취소</button>
<button class="toss-btn text-btn" type="button">근거 보기</button>
<button type="button" aria-label="수정"><v-icon small>mdi-pencil-outline</v-icon></button>

입력

폼 컨트롤

input, textarea, checkbox, switch, segmented
<label>
  검토 대상
  <select v-model="trademarkId">
    <option value="ipvelo">IPVELO</option>
  </select>
</label>
<label>
  검토 메모
  <textarea v-model.trim="memo" rows="4" />
</label>
<DsSwitch
  v-model="autoEvidence"
  label="근거 자동 표시"
  description="분석 완료 후 핵심 근거 패널을 자동으로 엽니다."
/>
<DsSegmentedControl
  v-model="duplicateMode"
  size="large"
  aria-label="검토 방식"
  :options="duplicateOptions"
/>

입력 미리보기

명칭 박스

<DsTextNameBox :value="trademarkName" />
<input v-model.trim="trademarkName" type="text" placeholder="상표 명칭" />
<DsTextNameBox
  :value="trademarkName"
  label="상표 명칭"
  :box-size="150"
/>

상태 지표

추천도 링

<DsScoreRing :score="96" />
초록 · 강력 추천 90점 이상 추천도가 높은 상품류
주황 · 추천 검토 70점 이상 90점 미만의 검토 후보
회색 · 낮은 추천도 낮은 추천도나 보조 후보
<DsScoreRing :score="96" label="추천도" />
<DsScoreRing :score="82" label="추천도" />
<DsScoreRing :score="55" label="추천도" />

선택

Numeric Spinner, Segmented Control

<DsNumericSpinner />, <DsSegmentedControl />
Segmented Control 검토 범위
Numeric Spinner 검토 후보 수
유사 후보 표시
5
1
2
3
4
잠긴 설정
0
<DsNumericSpinner
  v-model="candidateLimit"
  size="large"
  :min-number="1"
  :max-number="12"
  decrease-aria-label="유사 후보 수 줄이기"
  increase-aria-label="유사 후보 수 늘리기"
/>
<DsSegmentedControl
  v-model="reviewScope"
  size="large"
  alignment="fixed"
  aria-label="검토 범위"
  :options="reviewScopeOptions"
/>

상태

메시지, 배지, 칩

.error-message, .notice-message, .file-chip
<p class="notice-message">거절이유통지서 PDF를 분석 중입니다.</p>
<p class="error-message" role="alert">이메일 또는 비밀번호를 확인해주세요.</p>
<span class="file-chip"><v-icon small>mdi-file-pdf-box</v-icon> 의견제출통지서.pdf</span>

데이터

카드, 테이블, KPI

.dashboard-slot, .data-grid, .manager-kpi
REVIEW_QUEUE 42 이번 달 완료 28건
상표명 출원번호 상태
IPVELO 40-2024-0101201 신규 감지
NOWOD 40-2025-0221708 의견서 작성중
CURSTI 40-2024-0203592 추가 검토
<article class="dashboard-slot dashboard-slot--filled">
  <header class="widget-header">...</header>
  <div class="manager-kpi">42<span>건</span></div>
</article>
<div class="data-grid" role="table">...</div>

목록

관리 목록

.admin-list-panel, .admin-list-table, .status-chip
출원번호 상표명 상품류 출원인 등록자 현재상태 확인일시 활성 메모
40-2025-0120254 어드헤어 휴대폰메일anon 선행 상표 제44류 최임진 김태훈 출원 2026.07.02 16:46
40-2026-0069737 이보카 (evoka) 휴대폰메일이의신청 제03류 성예슬 김태훈 공고 2026.07.02 10:56
40-2025-0226402 한양비책 휴대폰 제-류 - 김태훈 등록 2026.07.02 10:56
40-2025-0217827 헤이스트 휴대폰 제-류 - 김태훈 출원 2026.07.02 10:55
페이지당 표시 1-4 of 4
<section class="admin-list-panel">
  <div class="admin-list-toolbar">
    <label class="admin-list-search">
      <v-icon small>mdi-magnify</v-icon>
      <input type="search" placeholder="출원번호, 상표명, 출원인 또는 등록자 검색" />
    </label>
    <button class="admin-list-action" type="button">알림 추가</button>
  </div>
  <div class="admin-list-scroll">
    <div class="admin-list-table" role="table">
      <div class="admin-list-row admin-list-row--head" role="row">...</div>
      <div class="admin-list-row" role="row">
        <strong>40-2025-0120254</strong>
        <span class="class-chip">제44류</span>
        <em class="status-chip status-chip--info">출원</em>
        <DsSwitch compact aria-label="어드헤어 활성" />
      </div>
    </div>
  </div>
</section>

차트

Highcharts 막대 차트

<DsClayBarChart :data="monthlyBarChartData" />
<DsClayBarChart
  :data="[
    { label: '1월', value: 6 },
    { label: '2월', value: 5 },
    { label: '3월', value: 4 },
    { label: '4월', value: 3 },
    { label: '5월', value: 2 },
    { label: '6월', value: 1 },
  ]"
  :height="160"
/>

로딩

스켈레톤 시스템

.skeleton, .skeleton-row, .skeleton-card
아이콘 포함 상단 리스트 topListWithIcon
리스트 전용 listOnly
카드 전용 cardOnly
Custom Pattern ['title', 'subtitle', 'spacer(20)', 'card']
Usage Rules
  • 실제 콘텐츠의 위치와 크기를 먼저 보여주고, 로딩 텍스트는 별도로 쓰지 않습니다.
  • 리스트는 마지막 row를 반복하는 방식으로 길이를 맞춥니다.
  • 흰 배경, 회색 배경, 진한 회색 배경에서 모두 대비가 유지되게 합니다.
<section class="skeleton-pattern skeleton-pattern--white">
  <div class="skeleton-top">
    <span class="skeleton-icon"></span>
    <div>
      <i class="skeleton skeleton-title"></i>
      <i class="skeleton skeleton-subtitle"></i>
    </div>
  </div>
  <div class="skeleton-list">
    <div v-for="index in 4" :key="index" class="skeleton-row">
      <span class="skeleton-icon skeleton-icon--sm"></span>
      <div>
        <i class="skeleton skeleton-line"></i>
        <i class="skeleton skeleton-line skeleton-line--short"></i>
      </div>
    </div>
  </div>
</section>

파일

업로드, 드롭존, 진행 상태

.upload-panel, .upload-dropzone, .upload-file-card
의견제출통지서.pdf
<section class="upload-panel" @dragover.prevent @drop.prevent="dropFiles">
  <input id="dataInputFiles" class="upload-file-input" type="file" multiple @change="selectFiles" />
  <label v-if="!uploadedFileCards.length" class="upload-dropzone" for="dataInputFiles">
    <v-icon>mdi-cloud-upload-outline</v-icon>
    <strong>클릭하거나 파일을 여기로 드래그하세요</strong>
    <span>PDF, HWP, DOCX, JPG, PNG 파일 지원</span>
  </label>
  <div v-else class="upload-file-grid">
    <article v-for="file in uploadedFileCards" :key="file.id" class="upload-file-card">
      <DsButton type="button" class="upload-file-remove" @click="removeFile(file.id)">
        <v-icon x-small>mdi-close</v-icon>
      </DsButton>
      <v-icon>mdi-file-document-outline</v-icon>
      <strong>{{ file.name }}</strong>
    </article>
    <label class="upload-add-card" for="dataInputFiles"><v-icon>mdi-plus</v-icon><span>자료 추가</span></label>
  </div>
</section>

오버레이

모달, 다이얼로그, 토스트

v-dialog, vue-toastification, builder-modal
의견서 구성
<v-dialog v-model="isDialogOpen" width="420">
  <v-card class="pa-5">...</v-card>
</v-dialog>
this.$toast.success("저장되었습니다.")

라이브러리

Vuetify, Draggable, Highcharts, Swiper, Quill

v-icon, draggable, highcharts, swiper, quill-editor
Vuetify primitives
상표 검토
OA 대응
IP 자산
<swiper><swiper-slide /></swiper> <quill-editor v-model="content" />
<client-only>
  <highcharts :options="chartOptions" />
</client-only>
<draggable v-model="items" handle=".drag-handle" :animation="140">...</draggable>
<swiper><swiper-slide>...</swiper-slide></swiper>
<quill-editor v-model="content" />

상태 화면

빈 상태, 로딩, 오류

.empty-state, v-progress-circular
아직 검토한 상표가 없습니다.

상표명을 입력하면 유사 후보, 지정상품, 등록 가능성을 이 화면에서 확인할 수 있습니다.

온보딩 상태 확인 중
<section class="empty-state">
  <v-icon>mdi-database-off-outline</v-icon>
  <div><strong>아직 검토한 상표가 없습니다.</strong></div>
</section>
<v-progress-circular indeterminate size="32" color="primary" />