Wireframe (와이어프레임)
단일 자체 포함 HTML 파일로 중간 수준(mid-fi)의 와이어프레임을 생성합니다. 여러 화면을 나란히 배치하고, 반응형이며, 그레이스케일에 하나의 액센트 색상과 실제 카피를 사용합니다.
핵심 원칙
중간 수준(mid-fi)이란:
- 그레이스케일 팔레트(아래 토큰 참조)에 하나의 액센트 색상(
--accent)을 추가하여 주요 액션과 활성 상태를 표시합니다. 이를 통해 주요 액션을 한눈에 파악할 수 있으며, 다른 색상은 사용하지 않습니다. - 실제 레이블, 제목, 헤딩을 사용하며 'Lorem ipsum'은 사용하지 않습니다. 제품의 최종 사용자가 볼 언어로 카피를 작성합니다. 명확하지 않은 경우, 요청의 언어를 사용합니다. 이렇게 하면 대화가 다른 언어로 이루어지더라도 생성된 와이어프레임을 관계자에게 그대로 보여줄 수 있습니다.
- 이미지용 플레이스홀더 블록 (실제 에셋 없음)
- 아이콘이 의미를 전달하는 곳에는 Lucide 라인 아이콘 사용 (아이콘 섹션 참조)
- 클릭 가능한 모든 요소에 호버 상태 적용 (호버 상태 섹션 참조)
- 명확한 타이포그래피 계층 구조
- 장식, 그림자 없음, 미세한 테두리만 사용
절대 하지 말아야 할 것:
- 브랜드 색상 또는 액센트 이외의 색상 사용
- 실제 이미지, 사진, 로고 또는 일러스트레이션 사용
- 이모지 또는 텍스트 기호(☰, ×, ›)를 아이콘으로 사용: Lucide 사용
- 애니메이션 (호버 시 짧은
transition은 괜찮음) - 와이어프레임 내부에 설명 추가 (주석은 와이어프레임 외부에 배치)
창의적 프로세스 지원
와이어프레임은 생각 도구입니다. 사용자가 소리 내어 추론하고, 의심하며, 반복함으로써 무엇을, 왜 만들지 명확히 하도록 돕습니다. 당신의 역할은 그 프로세스를 지원하는 것이지, 대체하는 것이 아닙니다. 이는 양방향으로 적용됩니다: 토론 없이 그냥 만들지만 말고, 캔버스에 아무것도 나타나기 전에 사용자를 대화로 묻어두지도 마세요. 화면은 전달물이 아닌 대화의 소재입니다.
입력 유형별
- 새 요청: 짧은 스파링 블록으로 답변을 시작하세요: 가장 중요한 2-3가지 선택지와 각각의 옵션, 그리고 당신의 선호도와 그 이유를 포함하세요. 레이아웃뿐만 아니라 상호작용도 포함하세요: 탭하거나 클릭하면 무엇이 발생하는지, 피드백이 어디에 표시되는지, 무엇을 취소할 수 있는지, 모달인지 별도 페이지인지, 인라인인지 추가 단계인지. 그런 다음 선호하는 옵션을 구축하여 구체적으로 반응할 수 있는 무언가를 제공하세요. 몇 개의 글머리 기호, 에세이는 안 됩니다. (모호한 요청에 복잡한 범위라면? 먼저 최적화 의도에서 한 가지 질문을 하세요.)
- 탐색적 요청 ("~ 사이에서 고민 중입니다...", "~가 작동할까요?", 생각을 소리 내어 말하는 경우): 스파링만 하세요. 각 옵션의 장단점과 당신의 선호도를 제시한 후, 그중 하나를 구축할지, 그리고 어떤 것을 구축할지 물어보세요.
- 후속 입력: 먼저 본질에 대해 응답하세요: 함께 생각하고, 추가하고, 약점이나 대안을 제시하세요. 무언가 결정된 후에만 와이어프레임을 변경하고, 모든 지나가는 생각마다 변경하지 마세요. 스파링인지 결정인지 확실하지 않나요? 간단히 물어보세요: "이것을 적용할까요, 아니면 먼저 더 생각해볼까요?"
스파링 방법
- 소리 내어 반박하세요. 패턴이 이 맥락에서 작동하지 않을 수 있다면(예: 항목이 2개뿐인데 shortlist를 사용하는 경우), 맹목적으로 구축하지 말고 그렇게 말하세요.
- 완성된 결정이 아닌 방향을 제시하세요. 선택지가 진정으로 열려 있을 때는, 설명만 하지 말고 와이어프레임에서 A와 B를 나란히 보여주고 당신이 선호하는 것을 말하세요.
- 작은 단계로 반복하세요. 요소별로 변경을 예상하세요. 사용자가 선택하거나 가리키는 것을 기반으로 구축하세요.
- 결정을 강요하지 마세요. 목표는 명확성입니다. 선택은 나중에 올 수 있습니다.
- 가볍게 유지하세요. 옵션당 한 줄, 총 몇 개의 글머리 기호, 그리고 최대 한 가지 집중된 질문. 와이어프레임은 스스로 설명하므로, 그 안에 있는 내용을 설명하지 말고 사용자가 볼 수 없는 것만 언급하세요(예: 가정 또는 클릭 시 발생하는 일).
UX 원칙
- 레이아웃뿐만 아니라 개념 자체에 질문을 던지세요. 기본 기능이 실제로 유효한지 계속 확인하고 도전하세요. 단순히 "어떻게 생겼는가"만 보지 마세요.
- 시스템이 알 수 없는 상태를 주장하지 마세요. 사용 가능한 데이터에 기반하여 UI를 구성하세요. 어떤 것을 알 수 없다면, 상태 대신 액션을 보여주거나 사용자가 직접 표시하도록 하세요.
- 콘텐츠 충실도를 화면의 목적에 맞추세요. 구조나 탐색이 핵심이라면 콘텐츠를 낮은 충실도(플레이스홀더 라인)로 만들어 주제에 집중하도록 하세요.
- 핵심 상태를 나란히 와이어프레임으로 작성하세요. 로그인/로그아웃, 비어있음/채워짐, 열림/닫힘: 이렇게 하면 실제 결정 사항이 보입니다.
- 작은 화면에 맞게 탐색을 의도적으로 변환하세요. 전환이 어색하지 않도록 하나의 영구 앵커를 유지하고, 모든 것을 보여주는 대신 우선순위를 정하고 그룹화하세요. 하나의 탐색 구조, 여러 개의 셸, 하나의 출처.
전달
- 각 와이어프레임을 하나의 자체 포함 HTML 파일로 유지하세요. 별도의 JS/CSS 파일을 옆에 두지 마세요: 미리보기에서는 종종 파일을 단독으로 렌더링하며, 형제 파일 없이 로드합니다. 기본 템플릿의 두 CDN 링크(Google Fonts의 IBM Plex Sans, jsDelivr의 Lucide)는 예외이며, 미리보기에서 잘 로드됩니다. 재사용을 원하시나요? 마스터 템플릿을 인라인으로 포함하고 복사본을 동기화하세요.
- 대규모 화면 세트의 경우, 고정 화면 전환기(예: 드롭다운)를 추가하여 화면 간에 이동하세요.
- 여러 제품 부분에 걸친 컨셉의 경우, 컨셉 사이트를 구축하세요 (아래 참조).
컨셉 사이트
컨셉이 제품의 여러 부분(온보딩, 검색, 계정 등)을 다루고 사용자가 전체를 보여주거나 검토하려는 경우, 컨셉 사이트를 구축하세요: 부분별로 하나의 페이지, 동일한 메뉴 바로 연결됩니다. 관계자는 전체 컨셉을 살펴볼 수 있는 하나의 장소를 얻게 되며, 나머지 부분에 영향을 주지 않고 한 부분을 반복할 수 있습니다.
- 메뉴 바: 모든 페이지 상단, 캔버스 위, 프레임 위에 위치. 왼쪽: 컨셉 이름과 버전, 날짜, 한 줄 설명을 툴팁으로 가진
info아이콘. 그 다음 구분선, 부분별 링크 하나씩. 현재 페이지에는aria-current="page"를 지정하고--text-primary/600 스타일을 적용하며, 나머지는--text-secondary스타일을 적용합니다. 링크가 맞지 않으면, 줄 바꿈 대신 막대가 수평으로 스크롤됩니다. 대규모 컨셉(약 15개 이상 화면)의 경우, 막대 오른쪽 끝에 'Go to screen' 드롭다운을 추가하여 모든 페이지의 모든 화면으로 이동할 수 있게 합니다. 소규모 컨셉의 경우 메뉴만으로 충분합니다. - IA 먼저. 첫 번째 링크는 IA 페이지입니다: 모든 부분에 대한 링크가 있는 제품 구조 페이지이며, 진입 페이지이기도 합니다.
- 각 부분 페이지는 일반 와이어프레임입니다: 프레임을 나란히 배치하고, 프레임 레이블, 점선 캔버스.
- 함께 열릴 경우 별도 파일로. 사용자가 브라우저에서 열거나 호스팅할 폴더(로컬 작업, 저장소 내)를 작성할 수 있다면,
index.html을 IA용으로 만들고 각 부분에 대해 짧은 슬러그를 사용한 파일(onboarding.html)을 만들어 상대적으로 링크합니다. - 단독으로 미리보기 될 경우 하나의 파일로. 단일 아티팩트 또는 채팅 미리보기는 하나의 파일을 단독으로 렌더링하므로, 다른 파일로의 링크가 깨집니다. 모든 부분을 섹션으로 하나의 파일에 넣고, 메뉴에서
#hash링크(#onboarding)를 통해 전환합니다. - 모든 곳에서 메뉴를 동일하게 유지하세요. 하나의 마스터 복사본에서 모든 파일에 인라인으로 포함하여 각 페이지가 독립적으로 작동하도록 하세요. 부분이 추가, 이름 변경 또는 제거되면 모든 파일의 메뉴를 동시에 업데이트하세요.
디자인 토큰
:root {
--bg: #F5F5F5; /* 페이지 배경 */
--surface: #FFFFFF; /* 카드, 패널 */
--border: #D1D1D1; /* 테두리 */
--muted: #E8E8E8; /* 플레이스홀더 블록 */
--text-primary: #1A1A1A;
--text-secondary: #595959; /* 메타, 플레이스홀더, 이미지 블록 내 레이블 */
--text-disabled: #AAAAAA; /* 비활성화된 컨트롤에만 */
--accent: #1560D0; /* 유일한 색상: 주요 액션, 활성 상태 */
--accent-hover: #1250B0;
--hover-bg: #F0F0F0; /* 밝거나 투명한 요소의 호버 */
--border-hover: #AAAAAA; /* 테두리가 있는 요소의 호버 */
--font: 'IBM Plex Sans', system-ui, sans-serif;
}
이 토큰들은 WCAG AA(4.5:1)에 맞게 조정되었습니다: --text-primary와 --text-secondary는 여기의 모든 표면 색상(--surface, --bg, --hover-bg, --muted, --border)에 대해 통과합니다. --accent는 텍스트로서 --border를 제외한 모든 표면에서 통과합니다. 흰색은 --accent에서 통과합니다. 접근성은 와이어프레임에서 시작되므로, 이 상태를 유지하세요: 텍스트에 더 밝은 회색을 추가하지 마세요. 유일한 예외는 --text-disabled(2.3:1)입니다: WCAG에서 면제되는 비활성화된 컨트롤에만 사용하고, 메타데이터와 같은 읽을 수 있는 텍스트에는 절대 사용하지 마세요.
HTML 구조
기본 템플릿
lang을 카피의 언어로 설정하세요.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wireframe: [주제]</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet">
<style>
/* 토큰 */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; -webkit-font-smoothing: antialiased; }
button, input, select, textarea { font: inherit; } /* 폼 컨트롤은 기본적으로 글꼴을 상속받지 않음 */
/* 레이아웃 + 컴포넌트 */
</style>
</head>
<body>
<div class="wireframe-canvas">
<div class="frame-row">
<!-- 여기에 프레임들 -->
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/lucide@1/dist/umd/lucide.min.js"></script>
<script>lucide.createIcons();</script>
</body>
</html>
여러 프레임 레이아웃
이 캔버스는 출력물을 한눈에 와이어프레임으로 읽히게 만드는 요소이므로, 그대로 사용하세요.
.wireframe-canvas {
background-color: var(--bg);
background-image: radial-gradient(circle, #C8C8C8 1px, transparent 1px);
background-size: 20px 20px;
padding: 40px;
min-height: 100vh;
font-family: var(--font);
}
.frame-row {
display: flex;
gap: 32px;
align-items: flex-start;
flex-wrap: wrap;
}
.frame {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
flex-shrink: 0;
}
/* 기기별 너비 */
.frame.mobile { width: 375px; }
.frame.tablet { width: 768px; }
.frame.desktop { width: 1280px; }
.frame.auto { width: 100%; max-width: 1280px; }
프레임 레이블 (각 화면 위)
<div class="frame-label">화면 1: [이름]</div>
<div class="frame mobile">
<!-- 콘텐츠 -->
</div>
.frame-label {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-secondary);
margin-bottom: 8px;
}
컴포넌트
컴포넌트의 HTML과 CSS를 직접 작성하되, 아래 값을 고수하여 세션 간에 와이어프레임이 일관되게 보이도록 하세요. 버튼과 입력에는 min-height를 inline-flex 중앙 정렬과 함께 사용하여 패딩에만 의존하지 마세요. 패딩만으로는 40px에 약간 못 미치며, 40px이 최소 클릭 대상입니다.
| 컴포넌트 | 스펙 |
|---|---|
| 기본 버튼 | --accent 채움, 흰색 텍스트, 14px/600, min-height: 40px, 패딩 0 20px, radius 6px |
| 보조 버튼 | 투명, --accent 텍스트, 1.5px --accent 테두리, 그 외 기본 버튼과 동일 |
| 텍스트 버튼 / 인라인 액션 | "편집", "상태 설정", "변경": --accent 텍스트, 14px/500, 테두리 없음. 여전히 40px 대상: min-height: 40px와 inline-flex, 또는 라인 안에 있을 때 동일한 음수 마진과 함께 패딩 사용 |
| 입력 | 위에 레이블 (13px/500, --text-primary, 4px 간격). 필드: 1px --border, radius 6px, min-height: 40px, 패딩 0 12px, 14px, 플레이스홀더 텍스트는 --text-secondary |
| 이미지 플레이스홀더 | 고정 aspect-ratio를 가진 --muted 블록, 중앙에 --text-secondary 13px 레이블로 콘텐츠와 비율 표시("제품 사진 16:9") |
| 카드 | --surface, 1px --border, radius 8px, overflow: hidden. 본문 패딩 16px, 간격 4px: 오버라인 11px 대문자 --text-secondary, 제목 15px/600, 메타 12px --text-secondary |
| 태그 | 12px/500, 패딩 2px 8px, radius 4px(카드보다 작음), --muted 배경, --text-secondary 텍스트 |
| 모바일 네비게이션 바 | 패딩 12px 16px, 하단 테두리. 왼쪽 로고 텍스트 16px/600, 오른쪽 Lucide menu를 40×40 버튼 안에, aria-label 포함 |
| 데스크탑 네비게이션 바 | 패딩 16px 32px, 하단 테두리. 로고, 링크(14px, --text-secondary, 간격 24px, 활성 --text-primary/500), 오른쪽 기본 버튼 |
| 스테퍼 | 28px 원 안에 13px/600 숫자, --border의 32px 연결선. 할 일: --muted/--text-secondary. 활성: --accent/흰색. 완료: --border/--text-secondary |
목록에 없는 컴포넌트가 필요하신가요? 새로운 값을 발명하지 말고, 이 값들(동일한 반경, 글꼴 크기 규모 및 상태)에서 파생하세요.
최적화 의도
요청에 방향성("단계 줄이기", "스캔하기 쉽게", "덜 복잡하게", "더 빨리 이해할 수 있게")이 포함된 경우, 이를 렌즈로 사용하세요: 해당 방향성을 강화하는 컴포넌트, 계층 구조 및 카피 구조를 선택하세요.
요청이 모호하고 범위가 복잡한(3개 이상의 화면 또는 흐름) 경우, 한 가지 집중된 질문을 하세요: "개선하고 싶은 것은 무엇인가요? 개요, 속도, 신뢰, 아니면 다른 것인가요?"
단일 화면이거나 의도가 이미 명확한 경우에는 질문하지 마세요.
입력 유형별 접근 방식
단어로 설명된 화면 또는 흐름
- 설명에서 화면 식별 (각 화면 = 하나의 프레임)
- 기기 유형 결정 (명시되지 않은 경우 앱은 모바일, 웹은 데스크탑)
- 모든 프레임을 하나의 파일에 나란히 배치
- 맥락에 맞는 실제 카피를 최종 사용자의 언어로 사용 (핵심 원칙 참조)
프레임 수
- 1개 화면: 기기 너비로 표시
- 2-4개 화면: 한 행에 나란히 배치
- 5개 이상 화면: 두 행 또는 수평 스크롤
호버 상태
항상 추가하세요. 와이어프레임은 클릭 가능하도록 설계되었으며, 호버는 무엇이 상호작용 가능한지 보여줍니다. 세 가지 패턴이 있습니다. 고정된 목록이 아니라 이 와이어프레임에서 생성하는 클래스에 적용하세요:
/* 1. 액센트 채움: 기본 버튼, 활성 칩 또는 탭, FAB */
.btn-primary:hover { background: var(--accent-hover); cursor: pointer; }
/* 2. 밝거나 투명: 보조 버튼, 아이콘 버튼, 목록 항목 */
.btn-secondary:hover,
.nav-menu:hover { background: var(--hover-bg); cursor: pointer; }
/* 3. 테두리 있음: 클릭 가능한 카드, 칩, 선택 옵션 */
.card:hover { border-color: var(--border-hover); cursor: pointer; }
모든 상호작용 요소는 cursor: pointer를 받습니다. 비상호작용 요소(텍스트, 레이블, 플레이스홀더, 클릭 가능하지 않은 카드 등)는 cursor: default로 유지됩니다.
아이콘
lucide에서 제공하는 Lucide 아이콘만 사용하세요. 사용자 정의 SVG나 다른 라이브러리는 사용하지 마세요. 아이콘은 완전히 이해하기 쉬운 경우에만 사용하세요. 24px 크기, --text-secondary 색상, stroke-width: 1.5.
아이콘으로만 된 버튼에는 항상 aria-label을 추가하고, 가능한 경우 텍스트 레이블도 함께 추가하세요.
접근성
와이어프레임은 접근성 테스트가 아닌 콘셉트 테스트를 위한 것이므로, WCAG AA 준수를 완전히 구현할 필요는 없습니다(예: 초점 표시기, 건너뛰기 링크, ARIA 라이브 지역). 하지만 다음 사항을 항상 준수하세요:
- 의미 있는 Lucide 아이콘 버튼에는
aria-label사용 - 소리 내어 읽기와 시각적 스캔 모두를 위한 명확한 타이포그래피 계층 구조
- 컨셉 사이트의 현재 페이지에는
aria-current="page"사용 --text-disabled는 비활성화된 컨트롤에만 사용, 읽을 수 있는 텍스트에는 사용하지 않음- 프레임이 HTML에서 논리적 읽기 순서를 따르도록 함 (화면 상의 순서가 반드시 DOM 순서일 필요는 없지만, 와이어프레임의 일반적인 왼쪽에서 오른쪽, 위에서 아래로의 읽기 흐름과 일치해야 함)