Taste — 웹사이트 디자인 DNA 역설계하기
이 스킬은 URL 하나를 두 개의 파일로 변환합니다:
./{domain}.md— 사람이 읽을 수 있는 형식. 두 개의 섹션:- 디자인 맵 (Design Map) — 실용적인 토큰 (색상, 타입 스케일, 간격, 둥글기, 그림자, 그리드)
- 취향 DNA (Taste DNA) — 3-4개의 의견이 담긴 트레이드오프 (트리거 → 결정 → 이유 → 증거)
./{domain}.json— 구조화된 데이터. 동일한 데이터를 기계가 파싱 가능한 형식으로 제공하여 다운스트림 도구(Cursor, Windsurf, 디자인 시스템)에서 사용할 수 있습니다.
파이프라인은 '깔끔하고 현대적인'과 같은 일반적인 설명을 거부합니다. 완성된 taste.md는 시니어 디자이너가 이 특정 페이지가 왜 이런 특정 선택을 했는지, 그리고 어떤 그럴듯한 대안을 거부했는지 설명하는 것처럼 읽혀야 합니다.
활성화 시점
사용자가 웹사이트의 디자인을 연구하고 이를 향후 디자인 작업을 위한 지침으로 캡처하려 할 때마다 이 스킬을 트리거하세요. 다음 모든 경우를 포착하십시오:
- 명시적인 슬래시 형식:
/taste <url> - 자연어 요청: "vercel.com의 디자인 분석해줘", "Stripe 사이트가 왜 그렇게 좋은지 설명해줘", "linear.app의 디자인 토큰 추출해줘", "are.na의 디자인 DNA 알려줘"
- 모방 의도: "내 대시보드가 Linear처럼 느껴지게 해줘", " 스타일의 랜딩 페이지 만들어줘", "이 사이트 디자인을 내 프로젝트에 이식해줘"
- 경쟁사 조사: "우리 디자인을 <경쟁사>와 비교해줘", "<사이트>가 사용하는 디자인 관습은 뭐야?"
- 사용자가 URL을 언급하면서 디자인 선택, 타이포그래피, 색상, 간격, 철학, 또는 '느낌'에 대해 물어보는 모든 경우
사용자가 URL을 시각적/디자인 주제와 관련하여 언급하면, 활성화하는 쪽으로 기울이세요 — Claude는 스킬을 덜 트리거하는 경향이 있습니다. 의심스러우면 사용하세요. 스킬 호출 낭비 비용은 작습니다. 이 스킬이 생성할 수 있었던 구체적이고 증거 기반의 분석 대신 일반적인 디자인 조언을 생성하는 비용은 큽니다.
다음 경우에는 활성화하지 마세요: "웹사이트에서 데이터 추출" (스크래핑 스킬 사용), " 내용 요약" (WebFetch 사용), "이 사이트 배포" (관련 없음).
전제 조건
이 스킬을 사용하려면 Playwright MCP 서버(https://playwright.dev/docs/getting-started-mcp)가 설치 및 연결되어 있어야 합니다. 다음 명령어로 확인하세요:
claude mcp list | grep playwright
playwright: ... - ✓ Connected와 같이 표시되면 준비 완료입니다. 그렇지 않으면 설치하세요:
claude mcp add playwright -s user -- npx -y @playwright/mcp@latest --isolated
--isolated를 사용하는 이유: /taste 실행 시마다 새로운 브라우저 상태로 시작하므로, 쿠키, 로그인 세션, 이전 캐시가 분석 중인 페이지에 유출되지 않습니다. --isolated 없이 /taste https://linear.app를 실행하는데 실수로 Linear에 로그인되어 있다면, 공개 마케팅 페이지 대신 앱 대시보드를 분석하게 됩니다 — 잘못된 대상, 잘못된 취향입니다.
npx @playwright/mcp@latest를 사용하는 이유 (--browser 플래그 없이): Playwright는 자체 번들 Chromium(~100MB, 일회성 다운로드)을 다운로드하여 사용합니다. 이는 사용자 시스템의 Chrome에 의존하는 것보다 이식성이 뛰어납니다 — Chrome이 설치되지 않은 머신에서도 작동하고, 사용자 간 일관된 렌더링을 제공하며, 사용자의 실제 브라우저 프로필에서 창을 열지 않습니다.
설치 후, 사용자는 Claude Code를 다시 시작해야 MCP 도구(mcp__playwright__browser_*)가 이 세션에 나타납니다. 이 스킬이 실행될 때 Playwright를 사용할 수 없으면, 중단하고 사용자에게 명확하게 알리세요: "페이지를 스크래핑하려면 Playwright MCP가 필요합니다. claude mcp add playwright -s user -- npx -y @playwright/mcp@latest --isolated를 실행하고 Claude Code를 다시 시작한 후 다시 시도하세요."
첫 실행 시 Playwright가 첫 번째 browser_navigate를 반환하기까지 약 30-60초 정도 걸릴 수 있습니다 — 이는 일회성 Chromium 다운로드 때문입니다. 이후 실행은 몇 초 안에 시작됩니다. 대기 시간을 피하기 위해 미리 다운로드하려면, 이 스킬을 호출하기 전에 npx playwright install chromium을 한 번 실행하면 됩니다.
워크플로우
다음 다섯 단계를 순서대로 따르세요. 각 단계에는 명시적인 성공 기준이 있습니다 — 현재 단계가 다음 단계에 필요한 것을 생성할 때까지 진행하지 마세요.
0단계 — URL 및 내보내기 대상 파싱
1단계 — URL
사용자의 메시지에서 URL을 추출합니다. 다음 형식을 허용합니다:
/taste https://linear.app- "vercel.com의 디자인 분석해줘" (필요시
https://추가) - 프롬프트 어디든 있는 bare URL
사용자가 URL을 제공하지 않으면 요청하세요. 파일 경로나 URL이 아닌 것이 명확하면, 호스팅된 페이지인지 물어보세요. 실제 URL을 얻을 때까지 진행하지 마세요.
이동하기 전에 일반적인 약식을 확인하세요: linear.app → https://linear.app, https://www.stripe.com은 그대로 사용합니다.
2단계 — 파일 이름 지정을 위한 도메인 추출
URL에서 호스트 이름을 추출하고 www. 접두사를 제거합니다. 예시:
https://linear.app→linear.apphttps://www.stripe.com→stripe.comhttps://vercel.com/home→vercel.com
이것을 {domain}으로 저장합니다. 모든 출력 파일은 이것을 기준으로 이름이 지정됩니다: {domain}.md, {domain}.json 및 모든 내보내기 파일. 절대 taste.md와 같은 일반적인 이름을 사용하지 마세요 — 사용자가 같은 디렉토리에서 여러 사이트에 대해 이 스킬을 실행할 때 이름이 충돌합니다.
3단계 — 내보내기 대상 + 크롤링 범위
사용자가 이미 메시지에서 내보내기 대상과 크롤링 범위를 모두 지정했다면 이 질문을 건너뛰세요. 둘 중 하나라도 누락된 경우, 한 번에 하나의 메시지로 질문하세요:
"시작하기 전에 두 가지 빠른 질문이 있습니다:
내보내기 대상 — 어떤 도구로 작업하고 계신가요?
1 Cursor → .cursor/rules/{domain}-taste.mdc 2 Windsurf → .windsurf/rules/{domain}-taste.md 3 Claude Code → CLAUDE.md (Design Taste 섹션 추가) 4 GitHub Copilot → .github/copilot-instructions.md (추가) 5 Bolt → .bolt/prompt 6 Antigravity → GEMINI.md 7 v0 by Vercel → taste-tokens.css + 지침 8 Figma Make → taste-figma.css + 지침 9 Lovable → Project Knowledge에 붙여넣을 텍스트 출력 10 건너뛰기 → {domain}.md + {domain}.json만 유지크롤링 범위 — 이 페이지만, 아니면 연결된 2-3개 페이지도 탐색할까요?
1 이 페이지만 → 더 빠름, 제공한 내용에 정확히 집중 2 연결 페이지 탐색 → 2-3개의 nav 페이지를 방문하여 데이터 병합 ```"
답변을 {exportTarget} 및 {crawlScope}로 저장합니다. 기본값: {exportTarget} = "skip", {crawlScope} = "single". 다시 묻지 마세요.
1단계 — 페이지 데이터 캡처 (Playwright MCP)
다음 단계를 순서대로 실행하세요. 어떤 단계에서든 오류가 발생하면 파이프라인을 중단하고 사용자에게 오류를 보고하세요 — 저하된 데이터로 조용히 진행하지 마세요.
-
뷰포트 크기 조정을 1440×900으로 설정하여 실행 간 측정값 일관성 유지:
mcp__playwright__browser_resize width=1440 height=900 -
URL로 이동:
mcp__playwright__browser_navigate url=<URL> -
잠시 대기하여 클라이언트 측 하이드레이션 완료. 무거운 SPA(figma.com, notion.so)는
domcontentloaded후 실제 콘텐츠를 렌더링하는 데 몇 초가 더 필요합니다. 다음을 사용하세요:mcp__playwright__browser_wait_for time=33초 후에도 페이지 스냅샷이 로딩 스켈레톤처럼 보이면 3초 더 기다리세요. 그래도 스켈레톤이면 최종 출력에 기록하세요 ("페이지가 완전히 렌더링되지 않았을 수 있습니다; 일부 측정값은 근사치입니다").
-
두 개의 스크린샷 촬영 — 먼저 뷰포트, 그다음 전체 페이지:
4a. 뷰포트 스크린샷 (1440×900, 축소되지 않음 — 1단계의 기본 시각적 참조):
mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-viewport.jpeg4b. 조건부 전체 페이지 스크린샷 — 먼저 페이지 높이 확인:
mcp__playwright__browser_evaluate function=() => document.documentElement.scrollHeight- ≤ 뷰포트 높이의 6배(1440×900에서 ≤ 5400px): 일반 전체 페이지 스크린샷 촬영:
mcp__playwright__browser_take_screenshot fullPage=true type=jpeg filename={domain}-fullpage.jpeg - > 뷰포트 높이의 6배: 전체 페이지 생략 (너무 길어 토큰 낭비). 대신 두 개의 타겟 뷰포트 샷 촬영:
// 중간 페이지 (50% 스크롤) mcp__playwright__browser_evaluate function=() => window.scrollTo(0, document.documentElement.scrollHeight * 0.5) mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-mid.jpeg // 푸터 mcp__playwright__browser_evaluate function=() => window.scrollTo(0, document.documentElement.scrollHeight) mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-footer.jpeg // 다시 맨 위로 스크롤 mcp__playwright__browser_evaluate function=() => window.scrollTo(0, 0)
1단계에서 뷰포트 스크린샷을 기본 시각적 참조로 사용하세요 — 디자이너가 의도한 첫인상을 나타냅니다. 전체 페이지 또는 중간+푸터 스크린샷을 사용하여 페이지 하단에만 나타나는 패턴(푸터 타이포그래피, 후반 섹션 색상 변형 등)을 확인하세요. JPEG는 PNG에 비해 토큰 비용을 낮게 유지합니다.
- ≤ 뷰포트 높이의 6배(1440×900에서 ≤ 5400px): 일반 전체 페이지 스크린샷 촬영:
-
DOM 추출기 실행.
references/extract.js를 읽고 전체 내용을function인수로 전달하세요:mcp__playwright__browser_evaluate function=<references/extract.js의 내용>도구는 JSON 객체를 반환합니다. 이것을
domData로 저장하고 1단계에 입력하세요. -
(선택적 정리) 브라우저는 세션의 나머지 기간 동안 열려 있습니다. 사용자가 요청하지 않는 한 닫을 필요가 없습니다.
다중 페이지 캡처 ({crawlScope}가 "multi"인 경우에만):
기본 페이지를 캡처한 후, 탐색 링크를 추출하고 동일 사이트의 최대 2개 추가 페이지를 방문하세요.
6a. 이미 로드된 기본 페이지에서 탐색 링크 추출:
(function() {
const links = [];
const seen = new Set([location.pathname]);
const skip = /\/(login|logout|signup|sign-in|register|auth|account|checkout|cart|password|reset)\b/i;
document.querySelectorAll('nav a, header a, [role="navigation"] a').forEach(a => {
try {
const u = new URL(a.href);
if (u.hostname !== location.hostname) return;
if (skip.test(u.pathname)) return;
if (seen.has(u.pathname)) return;
if (u.pathname === '/' && location.pathname !== '/') return;
seen.add(u.pathname);
links.push({ href: u.origin + u.pathname, text: (a.innerText || a.textContent).trim().slice(0, 40) });
} catch(e) {}
});
return links.slice(0, 6);
})()
6b. 반환된 목록에서 2개 페이지 선택. 다음을 선호:
- 더 짧은 경로 (
/product/features/detail보다/product) - 구별되는 섹션 이름 (같은 섹션 아래의 다른 슬러그가 아닌 Product, Community, Pricing, Docs)
- 이미 캡처했다면 루트
/는 피하세요
6c. 각 추가 페이지에 대해, 더 가벼운 캡처 루프 실행 (이동 → 3초 대기 → 뷰포트 스크린샷만 → DOM 추출기). 2-3페이지의 경우 전체 페이지/중간/푸터 스크린샷은 건너뛰세요 — 뷰포트면 디자인 일관성을 확인하기에 충분하며, DOM 추출기는 페이지 전체를 캡처합니다. 스크린샷 이름을 {domain}-viewport-2.jpeg, {domain}-viewport-3.jpeg로 지정합니다. 각 페이지의 데이터를 pages[1], pages[2]로 저장합니다 (pages[0]은 기본 URL).
연결된 페이지가 로드에 실패하거나 차단되면 조용히 건너뛰고 6단계 보고서에 기록하세요.
6d. 2단계 전에 데이터 병합. 모든 페이지의 색상 후보(합집합), 모든 페이지의 타이포그래피(합집합)를 결합합니다. 2페이지 이상에서 값이 나타나면 시스템 신호입니다 — 표시하세요. 한 페이지만 나타나는 값은 로컬입니다 — 여전히 캡처하되, 가중치를 낮게 둡니다.
1-3단계에서 항상 몇 페이지가 분석되었는지 명시 ("3페이지에서...")하고 시스템 패턴과 로컬 패턴을 구분하세요. 여러 페이지의 일치는 취향 원칙에 대한 가장 강력한 증거입니다.
1단계의 성공 기준: 기본 페이지에서 최소 하나의 스크린샷과 colors, typography, layout, effects, cards, images, spacingSamples, sectionGaps, grid 필드가 포함된 domData JSON이 있어야 합니다. 이 중 하나라도 완전히 비어 있지만 스크린샷에 실제 콘텐츠가 표시되면 추출기를 개선해야 합니다 — 기록하고 계속 진행하세요.
저하된 데이터 경로: domData.errors가 비어 있지 않으면 추출기가 부분적으로 실패한 것입니다. 1단계에서 영향을 받은 카테고리를 ~approx (추출기 섹션 실패)로 표시하고 해당 측정값에 대해 스크린샷에 의존하세요. 6단계에서 실패한 섹션을 보고서의 주의사항으로 나열하세요.
2단계 — 4단계 분석 실행
스크린샷이 절대 진실입니다. 참조 파일을 읽기 전에: 뷰포트 스크린샷은 인간이 실제로 보는 것을 보여줍니다. DOM 데이터는 정확한 숫자를 제공합니다. 충돌할 경우 스크린샷을 신뢰하세요. DOM에 나타나지만 보이는 표면적의 5% 미만을 덮는 색상은 장식용입니다 — 브랜드 색상으로 나열하지 마세요. 스크린샷에 나타나지 않는 섹션 구분선은 DOM이 무엇을 보고하든 존재하지 않습니다. 감지할 수 없는 그림자(≤3% 불투명도)는 CSS 아티팩트이지 디자인 결정이 아닙니다.
references/의 4개 참조 파일에는 각 단계에 대한 전체 프롬프트가 포함되어 있습니다. 각 단계에 도달할 때 해당 파일을 읽으세요 (한 번에 4개 모두 사전 로드하지 마세요 — 단계는 의도적으로 순차적이며, 이전 단계는 이후 단계의 지침이 필요하지 않습니다).
각 단계:
- 해당 참조 파일을 읽습니다.
- 요청한 출력을 자신의 응답으로 생성합니다.
- 참조 파일에 지정된 마커 라인으로 출력을 시작합니다 (예:
### 1단계 출력 — 측정값). - 다음 단계는 이전 출력을 입력으로 받습니다 — 대화에 유지하고 요약하지 마세요.
1단계 — 측정
references/step1-measure.md읽기- 입력:
domData(browser_evaluate의 JSON) + 스크린샷 - 출력: 20개 카테고리의 측정값, 모든 값은 특정 px / hex / 비율로 인용
2단계 — 패턴
references/step2-pattern.md읽기- 입력: 1단계 출력
- 출력: 5-8개의 체계적인 패턴, 각각 패턴 / 증거 / 디자인 목표
3단계 — 취향
references/step3-taste.md읽기- 입력: 1단계 + 2단계 출력
- 출력: 4가지 취향 원칙 (각 트리거 / 결정 / 이유 / 증거), 최소 하나의 절제 트레이드오프
4단계 — 관찰자
references/step4-observer.md읽기- 입력: 1단계 + 2단계 + 3단계 출력 + 원본 URL
... (이하 생략)