UX/UI 설계 감사 — 셀러 콘솔
- 작성자: PRODUCT_DESIGN (L1, 외부 설계 감사 레인)
- 날짜: 2026-11-02 · 대상: https://staging.yetdapay.com · 로컬 ref:
8e2f0a6(main) - 방법: Playwright chromium, 라우트당 desktop 1440×900 + mobile 375×812 전체 페이지 스크린샷; DOM 지오메트리/계산 스타일 측정(overflow, 탭 타겟, 폰트/컬러/래디어스 인벤토리); 8개 화면 다크 모드 패스; 상호작용 프로브(드로어, 사이드바 접기, ⌘K 팔레트, 환불/발급/삭제 모달, 빈 폼 검증); 온보딩을 신규 계정 두 개에서 종단간 실행. 라이브 스테이징 데이터;
fe/assets/css/main.css토큰과Ui*컴포넌트 대비 소스 검사. - 픽스처:
seller_7b6b0bef65da(qa3-seller-…@e2e.invalid) — 프로젝트 1, 상품 1, 주문 2(paid/refunded), 라이선스 2(active/revoked), 구독 0, 빈 피드백/위젯/정산. 온보딩용 신규ux-audit-{desktop,mobile}-…@e2e.invalid계정. - 증거:
/tmp/ux-audit/seller/shots/*.png(80장),metrics-{desktop,mobile}.json,sweep-results.json,text/*.txt본문 텍스트 캡처,probe-*.mjs스크립트. - 범위 노트: 설계 리뷰 전용 — 제품 코드 변경 없음. 기능 결함은 INDEPENDENT_QA 레인; UX 발견이 기능적 원인이면 *(cross-lane: ④/⑤)*로 표시. 심각도: critical = 머니/라이선스 경로에서 셀러를 차단/오도 · major = 실제 마찰, 죽은 UI, 불일치 · polish = 외관/밀도.
- 부작용: 온보딩 캡처용 신규 스테이징 계정 2개 생성; 감사 대상 셀러에 쓰기 없음(모달 열고 취소만).
화면 인벤토리
| # | 라우트 | 파일 | Desktop | Mobile | Dark | 라이브 상태 |
|---|---|---|---|---|---|---|
| S1 | /onboarding | pages/onboarding.vue | step0/1/done + 오류 샷 | 동일 | — | 신규 계정: 패스스루(F4) |
| S2 | /dashboard | pages/dashboard.vue | ok + 접기 + ⌘K | ok + 드로어 | ok | 전체 KPI/차트/테이블 |
| S3 | /projects | projects/index.vue | ok | ok | — | 프로젝트 카드 1 |
| S4 | /projects/new | projects/new.vue | ok | ok | — | 폼 |
| S5 | /projects/[id] + /items + /fulfillments | projects/[id]/*.vue | ok | ok | ok | 탭 + 아이템 카드 + 빈 이행 |
| S6 | /products | products/index.vue | ok + 행 메뉴 + 삭제 확인 | ok | — | 1행 |
| S7 | /products/new · /products/[id] | products/new.vue, [id].vue | ok + 검증 토스트 | ok + 검증 | ok(상세) | 공유 ProductsForm |
| S8 | /orders | orders/index.vue | ok | ok | ok | 2행 |
| S9 | /orders/[id] ×2 | orders/[id].vue | ok + 환불 모달 | ok + 환불 모달 | ok | paid + refunded |
| S10 | /licenses | licenses/index.vue | ok + 발급 모달 | ok | ok | 2행 |
| S11 | /licenses/[id] | licenses/[id].vue | ok | ok | — | 활성 라이선스 |
| S12 | /subscriptions | subscriptions/index.vue | ok | ok | — | 비어 있음 |
| S13 | /settlements | settlements/index.vue | ok | ok | — | KPI + 미정산 1 |
| S14 | /settings | settings/index.vue | ok + apikey 표시 | ok | ok | 8개 섹션, 스크롤 스파이 nav |
| S15 | /settings/settlement | settings/settlement.vue | ok | ok | — | 미등록 + 신청 폼 |
| S16 | /feedback | feedback/index.vue | ok | ok | — | 빈 수신함 |
| S17 | /feedback/widgets | feedback/widgets.vue | ok | ok | ok | 비어 있음 + 생성 폼 |
| S18 | /donations/widgets(+/mcp) | donations/widgets/*.vue | ok | ok(제목 절단) | ok | 라이브 생성기 + MCP 플레이스홀더 |
| S19 | /integrations/ai | integrations/ai.vue | ok | ok | ok | 실제 코드+프롬프트 출력 |
검증된 OK (유지)
- 토큰 규율이 우수: 셀러 페이지에 비토큰 Tailwind 팔레트 클래스 0개, 하드코딩 hex 사실상 0개(정당한 프리뷰 캔버스
#f7f7f7/#161618하나); 측정된 모든 텍스트 컬러가--ng-ink/ink-2/muted/faint/accent/bad/warn에 매핑; 타이포 스케일 일관(본문 11–15.5px, h1 22px, KPI 26px); 래디어스 일관(카드 16px / 컨트롤 8–12px / pill). - 컴포넌트 재사용이 명목이 아닌 실제:
UiCard/UiField/UiInput/UiSelect/UiSegmented/UiTable/UiBadge/UiEmpty/UiKpi/UiModal/UiDropdown/UiSwitch/UiAvatar전반 사용; 거의 모든 페이지에CommonPageHeader+ 브레드크럼. - 모바일 탭 타겟 ≥44px 모든 측정 인터랙티브 요소(nav 44px, input min-h-44, 아이콘 버튼 w-11 h-11, 브레드크럼/링크의
min-h-11 md:min-h-0관례). 발견된 누락만: C6/F12 참조. - 다크 모드가 종단간 올바름 — 계산 스타일 프로브가 오프테마 밝은 배경이나 어두운 텍스트를 찾지 못함; 반전된 기본 버튼, 스위치 썸, 소프트 다크 필 모두 토큰 파생.
- 머니 경로의 파괴적 확인: 주문 환불은
ConfirmModal사용(취소/환불 처리, destructive 변형, 설명에 결과 포함); 상품 삭제는 확인 모달 사용. - 샌드박스 정직성:
SANDBOX헤더 배지,Sandbox · Mock 환경사이드바 푸터, 정산의 mock 고지("실제 계좌이체 없이… 수수료는 예시 값"), 기부 MCP("현재 실제 서버에 연결되지 않습니다"), 주문 상세("이 라이선스는 Mock 환경에서 발급"), 설정 프로바이더 카드(준비 중). - 콘솔 오류, 페이지 오류, 실패한 요청 없음 23개 라우트 × 2 뷰포트 전체. 375px에서 페이지 수준 가로 오버플로 0(모든 테이블 오버플로는
.ng-table-scroll에 포함). - 상태 가독성:
useLabels.ts톤 맵이 합리적(paid=good, refunded=bad, suspended=warn…); 구독 기간 종료는 ≤3일이면N일 후warn 표시; 상태별 필터 칩이 카운트를 가짐. - 연동 표면이 진짜 기능적:
/integrations/ai가 셀러 프로젝트/아이템에 바인딩된 실제 임베드 코드 + AI 프롬프트 발급;/donations/widgets는 완전한 동작 생성기(스타일/크기/아이콘/컬러 프리셋, PC-모바일/라이트-다크 프리뷰, 4개 출력 형식). - 로딩 실패 설계가 fail-closed:
serverBlocked오버레이가 낡은 데이터를 차단하고 재시도 + 로그인 탈출 제공 — 좋은 본능(그러나 비용은 F1 참조).
교차 발견
| ID | 심각도 | 발견 | 권고 | 파일 |
|---|---|---|---|---|
| F1 | critical | 모든 전체 페이지 로드가 스테이징에서 ~4.0–5.5초 동안 전체 콘솔을 전체 화면 "서버에 연결 중…" 오버레이 뒤에 가둠(측정 TTR 4.0–5.5s × 46 로드). pullAll이 ~15개의 직렬 요청 발사(/me → 10개 엔티티 배치 → 프로젝트별 items/players/fulfillments + settlements/settings); 커밋까지 모든 콘텐츠가 v-show 숨김 — 셸 없음, 스켈레톤 없음, 점진 렌더 없음. 느린 Worker/D1 응답이 모든 직접 방문/새로고침을 5초 빈 로더로 만듦; 오버레이는 신규 셀러가 signup→dashboard 후 보는 첫 화면이기도 함. 가중: 로드당 GET /api/v1/me 4회(api-sync role 검사, dashboard onMounted, CommandMenu onMounted, +1) — 중복 왕복. | (a) 레이아웃 크롬(사이드바/헤더) + UiSkeleton 콘텐츠를 즉시 렌더; 첫 pull에서 데이터 영역만 게이트. (b) /me 호출 중복 제거(스토어를 통해 하나의 role fetch 공유). (c) 스테이징 지연이 원인이면 pullAll을 배치하거나 축소(settings/settlements는 지연 로드 가능). | fe/layouts/dashboard.vue:204-226; fe/plugins/api-sync.client.ts:60-114; fe/lib/api/sync.ts:54-78; fe/components/common/CommandMenu.vue:29-40 (cross-lane: ④ perf) |
| F2 | major | 주문 상세의 결제 이벤트 타임라인 카드가 API 모드에서 영구적으로 비어 있음 — paymentEvents가 절대 채워지지 않음(client.ts에 이벤트 엔드포인트 없음, pullAll에도 없음), 따라서 모든 유료 주문이 실제 원장 같은 제목 카드 아래 "기록된 이벤트가 없습니다" 표시. 콘솔에서 가장 신뢰 민감한 화면에서 깨져 보임. | GET /orders/:id에서 이벤트를 노출하거나(BE가 기록함 — events_impl.rs가 audit/outbox 기록) apiMode && !events.length일 때 카드 숨김. | fe/pages/orders/[id].vue:86-105; fe/stores/db.ts:98-99; fe/lib/api/sync.ts:54-66 (cross-lane: ④ 읽기 경로 없음) |
| F3 | major | 어디에나 죽은 "키" 컬럼: licenses 목록 첫 컬럼 "라이선스 키"가 모든 행에 — 렌더(목록 API는 설계상 키 생략, SEL-05); products/[id] 발급된 라이선스 테이블의 동일 죽은 컬럼; subscriptions 라이선스 셀이 빈 텍스트 액센트 링크 렌더(.key가 undefined). 최고의 테이블 자리가 영구 em-dash 표시 — 버그처럼 읽히고, subscriptions 셀은 보이는 라벨 없는 클릭 타겟. | 키 컬럼을 주문번호나 lic_… id(mono, 링크)로 교체; 보안 노트 유지. subscriptions에서는 key 없을 때 id로 링크. | fe/pages/licenses/index.vue:115-116; fe/pages/products/[id].vue(licenses 테이블); fe/pages/subscriptions/index.vue:90-97 |
| F4 | major | 온보딩 검증이 apiMode에서 우회 + 흐름이 흔적화. finish()가 name/brand를 절대 검증 안 함 — 빈 제출이 즉시 POST /seller/onboarding 발사(step-1의 next() 검증은 제출 버튼에서 도달 불가). 별개로, /signup이 이미 role=seller를 프로비전(검증됨: 신규 계정 → seller_f46c0009f712), 따라서 POST가 409 ALREADY_SELLER 반환 → 흐름이 등록이 일어났다고 주장하는 "가입 완료" 화면으로 단락. 관찰: POST 1회만 필요; 이런 식으로 우회하면 step-1 오류가 필수 * 표시로만 렌더. | finish() 안에서 POST 전 동일 필드 검증 실행; ALREADY_SELLER에서는 step 0–1 건너뛰고 완료 카드 직접 표시(또는 가입 시 이미 프로비전된 계정은 /onboarding 건너뛰기). | fe/pages/onboarding.vue:33-61 (cross-lane: ⑤ 기능) |
| F5 | major | /orders의 결제수단 컬럼이 항상 — — 목록 API가 method 생략, pullAll이 결제를 절대 fetch 안 함, 따라서 컬럼이 목록 뷰에서 죽어 있고 주문 상세는 올바르게 card · mock 표시. F3과 같은 컬럼 클래스: 누락 데이터처럼 보이는 영구 플레이스홀더 셀. | orders 목록 페이로드에 method/provider 포함, 또는 컬럼을 상세 전용 배지로 축소. | fe/pages/orders/index.vue:76; fe/lib/api/sync.ts (cross-lane: ④ 페이로드) |
| F6 | major | 파괴적/비가역 액션에 확인 부재, 불일치: 구독 취소(라이선스 폐기, 드롭다운에 재활성화 경로 없음)가 단일 메뉴 탭으로 실행; 행 드롭다운의 라이선스 회수가 즉시 실행(동일 데이터 모델의 환불은 ConfirmModal 필요). 커맨드 팔레트 시연 데이터 초기화가 db.reset()을 확인 없이 오도 토스트와 함께 실행 — apiMode에서는 다음 pull까지 라이브 서버 데이터를 mock 시드로 교체하고 "초기화 완료"로 표시. | 구독 취소 확인; 라이선스 상태 플립에 확인 또는 undo 토스트. 시연 데이터 초기화를 !apiMode로 게이트하거나 "화면 데이터만 초기화(서버는 그대로)" + 확인으로 리라벨. | fe/pages/subscriptions/index.vue:46-49,100-108; fe/pages/licenses/index.vue:131-136; fe/components/common/CommandMenu.vue:63-66; fe/stores/db.ts:1056-1059 |
| F7 | major | 폼 검증 UX 불일치: products/new가 누락된 상품명을 일시적 우하단 토스트("입력 확인")로만 보고 — 인라인 오류 없음, aria-invalid 없음, 포커스 이동 없음, 실패 필드가 토스트 위 전체 뷰포트일 수 있음. onboarding, settings/settlement, donations/widgets(Base URL :invalid + 인라인 :error)가 올바른 인라인 패턴 표시. | 상품명 필드에 UiField/UiInput :error/:invalid 렌더 + 첫 무효 input 포커스; 서버 단계 실패는 토스트 유지(이미 phase==='validation' 구분). | fe/pages/products/new.vue:52-71; fe/components/products/Form.vue:88-100 |
| F8 | polish | --ng-faint가 WCAG AA 실패 — 라이트 --ng-surface에서 2.52:1, 다크에서 2.34:1. 실제 콘텐츠(행 날짜, buyer 이메일 두 번째 줄, 힌트, "전월 데이터 없음")에 11.5–12.5px로 사용되며 장식 플레이스홀더만이 아님. | faint를 ≈#8f8f8f(라이트) / ≈#777(다크)로 올리거나 — text-faint를 아이콘/플레이스홀더 전용으로 예약하고 메타데이터를 text-muted로 승격. | fe/assets/css/main.css:20,74 |
| F9 | polish | 375px 테이블 UX가 전적으로 가로 스크롤에 의존(orders 920px / licenses 960px / products 860px min-width, 349px 안에 — 가장자리 페이드/그림자 같은 스크롤 암시 없이 ~62% 컬럼 숨김). 수용 가능한 포함이지만 셀러가 주문번호+금액+상태를 한눈에 못 봄. 함께 고려: segmented 필터 트랙도 스크롤(~300–341px에서 365–445px) — 동작하나 살짝 묻힘. | 단기: 스크롤 가장자리 페이드 또는 "컬럼 N개 더 →" 힌트. 중기: sm 아래에서 주요 컬럼의 행 카드 레이아웃. | fe/components/ui/UiTable.vue; pages/{orders,licenses,products,subscriptions}/index.vue |
| F10 | polish | /settings/settlement이 지급 필드를 수집 안 함 — "정산 정보 신청" 폼이 개발자 유형 + 브랜드명만 묻고, 정산 은행/계좌번호는 /settings → 판매자 정보에 살고 상호 참조 없음. 셀러가 파일에 계좌 없이 APPROVED에 도달 가능. 또한: 수제 헤더(CommonPageHeader/브레드크럼 없음), UiToaster 대신 비스포크 고정 토스트; 심사 신청 버튼에 :loading 없음. | 신청서에 은행 필드 추가(또는 "은행 정보는 설정에서 관리" 링크 + 비어 있을 때 불완전 경고); PageHeader + useToast 채택; loading 추가. | fe/pages/settings/settlement.vue:36-82; cf. settings/index.vue:154-155 |
| F11 | polish | 커맨드 팔레트 갭: 피드백, 피드백 위젯, 정산 등록, 구독 취소/발급 액션 부재 — 존재하는 최상위 nav 항목(후원 버튼, AI 연동 센터)이 생략을 우연처럼 보이게 함. 오버레이에 UiModal이 구현하는 role=dialog/aria-modal 및 listbox/option 의미도 없음. | 누락된 nav 항목 추가(저렴, 동일 목록 형태); role="dialog" aria-modal + role=listbox/option + aria-activedescendant 추가. | fe/components/common/CommandMenu.vue:42-58,118-152 |
| F12 | polish | 데스크톱 밀도 니트: 브레드크럼 링크가 19–20px 높이 측정(min-h-11 md:min-h-0이 붕괴); API 키 보기 눈 버튼이 15×15px; donations-widgets UiCard 헤더가 헤더 슬롯의 두 segmented 컨트롤이 감싸지 않아 375px에서 제목 절단("실시간…")(헤더에 flex-wrap 없음). | 전체 밀도 수용 가능 — 눈 버튼을 ≥24px로; UiCard 헤더에 flex-wrap(또는 헤더 슬롯에 min-[0px]) 추가. | fe/components/ui/UiCard.vue:7-17; pages/settings/index.vue:189; donations/widgets/index.vue:173-177 |
| F13 | polish | 상태 라벨이 언어 혼합: orders/feedback은 한국어(결제 완료·환불됨·대기)지만 licenses/subscriptions은 영어 caps(ACTIVE/REVOKED/SUSPENDED/PAST_DUE) 렌더 — 같은 배지 컴포넌트, 인접 화면의 두 관례. | 하나의 관례 선택(한국어 라벨, 영어 기술 레지스터가 의도적이면 license/serial 컨텍스트는 mono 스타일). | fe/composables/useLabels.ts:11-22 |
| F14 | polish | 빈 상태 CTA 불균등: products 빈 → "상품 등록" CTA(좋음); subscriptions 빈 → 제목만, 설명/CTA 없음(구독 유형 프리셀렉트와 products/new 딥링크 가능); feedback 빈 → 카피가 "위젯 미리보기에서 테스트 제출"이라 하지만 /feedback/widgets 링크 안 함 — 실제 차단 해제 액션이 헤더에만 있음. | 존재하는 곳의 모든 빈 상태에 기본 액션 부여. | pages/subscriptions/index.vue:58; pages/feedback/index.vue:91 |
| F15 | polish | 크롬 지속성: 사이드바 접기 상태가 로드마다 리셋(localStorage 없음); 대시보드의 5타일 "AI로 쉽게 만들기" 히어로가 매출 있는 셀러에게도 영구 — 첫 폴드를 먹음. /dashboard→/dashboard/ 308 리다이렉트가 직접 로드에 홉 추가. | collapsed 지속; products.length || orders.length이면 히어로 접기/해제; 외관. | fe/layouts/dashboard.vue:14; fe/pages/dashboard.vue:107-117 |
화면별 노트
| 화면 | VP | 발견(증거) | 심각도 | 권고 / 파일 |
|---|---|---|---|---|
S1 /onboarding | 양쪽 | 스텝 진행(3점) + 유형 선택 카드 + UiField 오류가 잘 읽힘; 그러나 빈 "가입 완료"가 미검증 POST → 서버가 결정(F4); 계정이 이미 seller → 패스스루 완료 화면이 일어나지 않은 등록을 축하; 완료 CTA(정산 등록하기 / 첫 프로젝트 등록)가 좋은 출구. 중앙 560px 컬럼이 375px까지 잘 스케일. | major | F4. pages/onboarding.vue |
S2 /dashboard | d | 빠른 액션 히어로 + KPI 8 + 연동상태 테이블 + 차트 + 최근 테이블 2 — 밀도 높지만 스캔 가능; 나란한 두 .ng-table-scroll 테이블이 반 컬럼을 오버플로(sw 648 > cw 562) 1440px에서 — 최근 orders/licenses가 데스크톱에서도 카드 내 스크롤 필요; 전월 데이터 없음 칩이 text-faint 사용(F8). | major | 테이블 컬럼 축소 또는 xl 아래에서 두 최근을 수직 스택; dashboard.vue:230-256 |
S2 /dashboard | m | 깔끔히 스택(KPI 2열, 히어로 2열→1, 테이블 스크롤 — F9); 활성 상태 있는 완전한 드로어 nav. | ok | — |
S3 /projects | 양쪽 | 단일 카드 목록 스케일; 상태 배지 + 아이템/플레이어/매출 메타 줄이 좋은 요약 행; "프로젝트 등록" 기본 CTA 명확. | ok | — |
S4 /projects/new | 양쪽 | 유형 칩 + 컬러 스와치 + 아이콘 입력 — 깨끗한 폼; 푸터에 취소 ghost + 등록 primary. | ok | — |
S5 /projects/[id]* | d | 탭 행(개요/상품·아이템/지급 내역/AI 연동/데모 게임) — AI 연동과 데모 게임이 페이지 내 탭처럼 스타일된 외부 링크(프로젝트 컨텍스트 이탈); KPI 행 + 수익화 연동 상태 체크리스트(연동됨/미설정 배지)가 콘솔 최고의 상태 요약 패턴; 최근 거래 빈 ok. | polish | 외부 탭을 아이콘/target 암시로 스타일하거나 체크리스트 카드로 이동. projects/[id]/index.vue:19-25,57-61 |
S5 …/items | 양쪽 | 아이템 카드(이름, 유형 배지, 가격, 지급 spec, 수정/비활성화/구매 테스트) — 좋은 카드 목록; 뒤로 링크 ← QA3 Space Game이 데스크톱에서 20px 높이 타겟(F12). | polish | — |
S5 …/fulfillments | 양쪽 | 필터 칩 전체/완료/실패/취소가 orders/subscriptions 칩과 달리 카운트 없음(마이너 불일치); 빈 상태 카피가 흐름을 잘 설명. | polish | orders/subscriptions 칩과 맞추려면 카운트 추가. projects/[id]/fulfillments.vue |
S6 /products | d | 테이블 + 유형 segmented + 검색 + 행별 ⋯ 메뉴(수정/미리보기/삭제) + 삭제 ConfirmModal — 완전한 패턴; 모바일 테이블 스크롤(F9). | ok | — |
S7 /products/new,/[id] | 양쪽 | lg:[1fr_320px] 폼+스티키 프리뷰 레이아웃이 우수; 유형/플랜/entitlement 에디터가 콘솔에서 가장 깊은 UI이고 함께 유지; 검증이 토스트 전용(F7); 같은 폼이 new+edit을 일관되게 서빙. | major | F7 |
S8 /orders | d | 카운트 있는 상태 칩 + 검색 + 8열 테이블; 결제수단 컬럼 죽음(F5), 지급 컬럼이 모든 상품 유형 주문에 —(반정당하지만 노이즈). | major | F5; 비게임 셀러는 지급 컬럼 숨김 고려 |
S9 /orders/[id] | d | 3열→2열 상세(주문 정보 dl + 이벤트 + 연결 리소스); 환불 ConfirmModal 적절; 결제 이벤트 카드가 항상 비어 있음(F2); 멱등성 키가 mono로 표시 — 좋음. 브레드크럼 + 배지 + 파괴 버튼 헤더가 올바르게 감김. | major | F2 |
S10 /licenses | d | 카운트 있는 상태 칩 + 검증 도구 + 수동 발급 모달(필수 필드, 취소/발급) — 좋음; 키 컬럼 죽음(F3); 행 클릭 nav 동작; ⋯ 메뉴에 회수 확인 없음(F6). | major | F3, F6 |
S11 /licenses/[id] | d | 상태 요약 그리드(상태/발급일/만료일/기기) + 만료 인라인 편집 + 활성화 목록 + entitlements + 연결 정보 — 잘 구성; key가 절대 채워지지 않으므로 제목이 일반 "라이선스"로 폴백(F3 부작용); 보안 노트 카피가 모범적. | polish | 제목에 lic_… id나 buyer 이메일 사용 가능; licenses/[id].vue:55 |
S12 /subscriptions | d | 카운트 있는 필터 칩 + 헤더 설명의 MRR; 테이블 설계(avatar buyer, plan+interval, warn 날짜 갱신, 라이선스 링크, 상태, 시뮬레이션 메뉴)가 강함 — 그러나 빈 상태에 CTA 없음(F14), 라이선스 셀이 빈 링크 렌더(F3), 구독 취소 미확인(F6). | major | F3/F6/F14 |
S13 /settlements | d | KPI 4개(미정산/수수료×2/예상 정산액) + 지급 예정 배지 + 대기 주문 테이블 + 이력 빈 — 앱에서 가장 명확한 mock 고지 카피; 정산 실행 (시뮬레이션) 비어 있을 때 비활성이 올바름. | ok | — |
S14 /settings | d | 스크롤 스파이 사이드 nav + 8개 섹션이 이 밀도에 올바른 패턴; 카드별 저장 괜찮음; 프로바이더 카드(Mock available + 준비 중 3개) 정직; "시연 데이터 — Mock 데이터 초기화"가 여기서 올바르게 라벨(⌘K 트윈과 달리, F6). | polish | F12 눈 버튼 크기; 정산 필드 ↔ S15 링크 고려(F10) |
S14 /settings | m | 8개 섹션 모두 스택; nav 숨김(수용 가능 — 페이지가 충분히 짧음); input이 올바르게 1열 스택. | ok | — |
S15 /settings/settlement | 양쪽 | 상태 카드(미등록 배지 + 설명 + 운영자 메모 슬롯)가 잘 읽힘; 폼 얇음 — 지급 필드 없음(F10); 브레드크럼 없음; 비스포크 토스트; 버튼 로딩 없음. | major | F10 |
S16 /feedback | d | 5개 필터 행이 빈 수신함 위에도 렌더(무해); 헤더 CTA(AI 연동 센터/위젯 관리)가 누락된 빈 상태 CTA 보완(F14); 아이템 설계(유형+상태+기부 배지, 답글 스레드, 아이템별 상태 선택, URL 상태 상세 모달)가 잘 구축 — 그러나 상세 모달이 개발자 카피 "이 화면은 URL 상태로 표현됩니다…" 노출. | polish | 메타 문장 제거 또는 툴팁으로 이동; feedback/index.vue:124 |
S17 /feedback/widgets | d | 빈 "위젯이 없습니다" + 새 위젯 CTA — 올바름; 생성 폼(이름/유형/프로젝트/도메인) 표준. | ok | — |
S18 /donations/widgets | 양쪽 | 전체 기능 생성기(프리셋 그리드, 라이브 PC/모바일 + 라이트/다크 프리뷰, 4개 코드 형식, 설치 단계, 연동 방법 설명) — 콘솔에서 가장 다듬어진 표면; 모바일: 카드 헤더 제목 절단(F12), 프리뷰 크롬의 input 34×44/PC 37×44 40px 미만 타겟(마이너 — 프리뷰 소품). | polish | F12; 모바일에서 PC/모바일 토글을 ≥40px로 확장 |
S18 …/mcp | d | 전체 페이지가 "준비 중" API 문서 — 정직하고 잘 구조화되며 명확한 미연결 고지; 플레이스홀더 페이지가 최상위 nav 슬롯을 가질 가치가 있는지는 설계 결함이 아닌 제품 결정. | polish | live까지 기부 페이지 아래 탭으로 접기 고려. |
S19 /integrations/ai | d | 설정 폼 → 구매 URL → 코드 탭 → AI 프롬프트 → 관련 링크; 프로젝트/유형/아이템/프레임워크/모드 선택; 실제 엔티티에 바인딩된 출력 — 진짜 유용; 준비 중 배지가 MCP 링크 카드에만. | ok | — |
상위 5개 우선순위 목록
- F1 — 5초 하얀 벽 제거. 모든 콘솔 로드의 첫 콘텐츠풀 상호작용이 스테이징에서 4–5.5초 전체 화면 "서버에 연결 중…"; 크롬 + 스켈레톤 즉시 렌더, 데이터 영역만 게이트, 4×
/me호출 중복 제거. 콘솔에서 가장 영향 큰 UX 수정. (요청 배치에 ④ 필요) - F2 + F3 + F5 — 영구적으로 죽은 데이터 표면 제거. 결제 이벤트 타임라인(항상 빈), 라이선스 키 컬럼(항상
—), subscriptions 라이선스 링크(빈 텍스트), orders 결제수단 컬럼(항상—)이 모두 셀러에게 깨짐으로 표시. 실제 데이터를 연결하거나(BE에 이벤트/감사 레코드 있음) 컬럼 제거/교체 — 이것이 머니 화면에서 가장 큰 "폴리시 대 신뢰" 갭. (페이로드에 ④ 필요; 검증에 ⑤) - F4 + F7 — 사용자가 입력하는 곳에서 검증을 실제로.
products/new(콘솔의 주요 쓰기 경로)가 인라인 상태나 포커스 없이 토스트 전용 오류 표시; 온보딩 제출이 자체 클라이언트 검증을 완전히 우회하고ALREADY_SELLERno-op을 축하.UiField :error+ 첫 무효 포커스로 통일. - F6 — 균일한 파괴적 암시. 환불/상품 삭제는 확인; 구독 취소, 라이선스 회수, ⌘K
시연 데이터 초기화는 미확인 — 마지막은 라이브 데이터를 mock 시드로 조용히 교체. ConfirmModal 패턴(또는 undo)을 일관되게 적용하고 apiMode에서 데모 리셋을 게이트/리라벨. - F8 —
--ng-faint대비 수정. 모든 테이블과 KPI 힌트의 실제 메타데이터 텍스트에서 2.52:1/2.34:1로 AA 실패. 원 토큰 변경; 올린 값이 여전히 "보조"로 읽히는지 검증.
부록 — 측정 데이터
- TTR(time-to-ready,
main가시): 데스크톱 평균 ≈4.27s, 최대 5.56s(상품 상세); 모바일 평균 ≈4.52s, 최대 5.52s — 모두 동일한pullAll배리어로 게이트(F1). - 오버플로: 46개 로드 모두 페이지 수준 가로 오버플로 = 0px. 포함된 스크롤러:
ng-table-scroll×7(orders 928px, licenses 968px, products 868px, settlements 448px, product-detail 488px ×2, dashboard recents 모바일 648px ×3 / 데스크톱 ×2),ng-seg__track×5(365–445px), 기타 38-in-32px 및 108-in-62px 절단(F12). - 탭 타겟 <40px @375px: donations-widgets 프리뷰 크롬 내부만(
input34×44,PC37×44, 프리뷰 앵커 120×37) — F12. <24px @1440px: 브레드크럼 링크 19–20px,API 키 보기15×15 — F12. - 네트워크/콘솔: 스윕 전체 0 오류, 0 실패 요청; 전체 API 200. 관찰된 중복 호출: 로드당
GET /api/v1/me4회(F1). - 다크 모드: 계산 스타일 감사가 오프테마 표면/텍스트 0개 발견; 모든 예외가 의도적임 검증(스위치 썸 흰색, 프리뷰 캔버스
#f7f7f7,#121213라벨의 반전된 기본 버튼). - 스크린샷 인덱스:
desktop-*.png×23,mobile-*.png×23,dark-*.png×8,onb-{desktop,mobile}-*.png×12,ix-*.png×12(드로어, 접기, ⌘K, 환불/발급/삭제 모달, 검증 토스트, apikey 표시),probe-*.png×2 →/tmp/ux-audit/seller/shots/(80개 파일).