← 글 목록

insights

Grade·ease-out·토큰 층·QR·앵커 — 겉보기 기준을 다시 맞출 때

다크에서 글자가 굵어 보이고, 모션은 시계와 달랐고, 토큰은 두 층이면 됐고, QR은 같은 폰에선 없었고, 할인은 첫 숫자가 기준이었다.

1. 다크 타이포 Grade — 같은 weight가 더 굵어 보일 때

출처: Keeping type consistent

처음에 든 생각은 "다크 모드면 글자만 밝게 바꾸면 되지"였다. Astro 셸 헤더랑 TQ 쿠폰 칩에 같은 weight(굵기 단계)를 그대로 썼다. 라이트에서는 괜찮은데, 다크로 바꾸면 칩 라벨이 한 단계 더 굵은 폰트처럼 보였다. 줄바꿈 위치도 살짝 달라져서, 같은 문장인데 한 줄이 넘치거나 비는 느낌이 났다.

원인은 할레이션(halation)이다. 밝은 글자가 어두운 배경 위에 있으면, 빛 번짐처럼 가장자리가 퍼져 보여 실제보다 두껍게 읽힌다. weight 숫자는 그대로인데 눈의 두께감만 커지는 것이다. 가변 폰트(한 파일 안에서 굵기·폭 등을 미세 조절할 수 있는 글꼴)의 GRAD(그레이드) 축을 살짝 내리면 — 예로 −92 — 겉보기 두께를 라이트 쪽에 맞출 수 있다. weight를 바꾸지 않으니 줄바꿈·정렬 규칙도 크게 흔들리지 않는다.

쿠폰 칩·태그처럼 짧은 라벨에서 효과가 분명하다. "적용됨" 네 글자가 다크에서만 뚱뚱해 보이면 칩 전체 균형이 깨진다. GRAD로 보정해 두면, 테마를 바꿔도 같은 문장이 같은 자리에 앉는다.

다크 타이포 Grade — 할레이션 vs GRAD −92 보정

2. 모션 체감 ≠ 시계 — ease-out을 과장하고 duration을 늘릴 때

출처: Wham! Bezier tool note · Bezier curve tool

토스트가 "느리다"는 피드백과 "갑자기 튀어나온다"는 피드백이 동시에 왔다. 시계로 재면 duration(전체 재생 시간)은 짧았고, 체감은 둘 다 틀렸다. 중간 프레임이 비면 Ghost(유령처럼 순간이동해 보이는 현상)가 나고, 선형으로 길게 끌면 답답하다.

해결의 힌트는 ease-out을 과장한 뒤 duration을 오히려 늘리는 쪽이었다. 예를 들어 1200ms짜리 곡선에서, 앞쪽 약 350ms 안에 이동의 90%가 끝나고 나머지는 미끄러지듯 안착한다. 사용자는 "빨리 도착했다"고 느끼면서도, 끝이 부드럽게 붙어 텔레포트 느낌이 사라진다. 시계의 길이와 체감의 속도가 다른 이유다.

toast 등장·쿠폰 적용 모션에 바로 썼다. "프레임을 더 촘촘히"만으로는 Ghost가 안 사라지고, "duration만 줄이기"만으로는 고급감이 없다. 초반에 대부분을 보내고, 끝에만 남는 시간을 설계하는 쪽이 맞았다.

ease-out 과장 + 1200ms — 앞 ~350ms에 90%

3. 토큰 층 — primitive + semantic 두 층이면 충분하다

출처: Design token architecture (Figma)

Storybook이랑 TQ Variables를 정리하다가 층이 세 개, 네 개로 불어났다. primary가 버튼에도, 뱃지에도, 포커스 링에도 쓰이는데 값이 조금씩 갈라지자 component 토큰을 미리 만들어 둔 탓이다. 이름을 고르는 비용이 커졌고, "이 파란 게 진짜 primary야?"를 매번 물게 됐다.

정리해 보니 기본은 두 층이면 된다. primitive(원시값) — blue-500, 8px처럼 팔레트와 숫자. semantic(의미층) — color.primary, space.tight처럼 제품이 고를 이름. 다운스트림(실제로 쓰는 코드·컴포넌트)에는 semantic만 publish하고, primitive는 안쪽에 숨긴다. component 층은 같은 semantic이 버튼/뱃지/포커스에서 정말로 갈라질 때만 올린다. "결정"만 밖으로 내보내고, 원재료는 감추는 구조다.

이렇게 두면 Storybook 표와 TQ Variables가 "고를 목록"으로 읽힌다. 원시 팔레트를 직접 고르게 두면 화면마다 미묘한 파랑이 생긴다. 두 층 + 필요 시 component, 이 규칙이 과한 추상화보다 유지비용이 낮았다.

토큰 층 — primitive 숨김 · semantic publish · component는 분기 시

4. 쿠폰 QR — 같은 폰 정보는 링크, QR은 타인·키오스크용

출처: QR Code Guidelines (NN/g)

쿠폰 상세에 QR을 크게 넣었더니, 자기 폰으로 자기 쿠폰을 스캔하려는 시도가 생겼다. 같은 기기에 이미 정보가 있는데 다시 카메라로 돌아가는 동선이다. QR은 "다른 화면·다른 사람·매장 키오스크"처럼 가리켜 스캔하는 상황용이고, 같은 폰이면 딥링크나 "바로 적용" 버튼이 맞다.

그다음이 인식 조건이다. 색을 반전(어두운 바탕에 밝은 모듈)하면 인식률이 떨어지니 흰 바탕 + 어두운 모듈을 유지한다. 크기는 대략 2×2cm 이상. 화면에 잠깐만 뜨는 경우(15초 미만)에는 긴 URL 대신 짧은 URL로 모듈 밀도를 낮춰, 초점이 잡히기 전에 사라지지 않게 한다.

TQ 쿠폰함에서는 "내 기기 = 버튼", "제시용 = QR"로 역할을 나눴다. QR을 없애는 게 아니라 쓰는 자리를 따로 맞추는 쪽에 가깝다.

쿠폰 QR — 같은 폰은 링크, QR은 타인·키오스크 · 반전 금지·2cm·짧은 URL

5. 할인 Anchoring — 첫 숫자가 가치의 기준이 된다

출처: Anchoring Principle (NN/g)

할인가만 크게 넣으면 "싸다"는 느낌이 바로 안 온다. 사람은 처음에 본 숫자를 정상 가치의 닻(anchor) 으로 삼고, 그다음 숫자를 그 기준으로 읽는다. 원가 ₩19,800 옆에 할인가 ₩9,900이 있으면 할인이 "이득"으로 읽히고, ₩9,900만 있으면 기준이 없어 판단이 흔들린다.

같은 원리가 기본값·소요시간에도 적용된다. 드롭다운 기본값을 이상한 옵션에 두면 그게 "정상"처럼 보이고, "3초 완료"처럼 낙관을 과대하면 한 번 기대를 깨는 순간 신뢰가 깎인다. 쿠폰 적용 안내에는 원가+할인가를 같은 시야에 두고, 소요시간은 낙관이 아니라 현실적인 구간(예: 약 10–20초)으로 적는 쪽이 맞았다.

앵커는 설득 트릭이라기보다, 비교할 첫 기준을 화면에 명시하는 일에 가깝다. 가격·기본값·시간 추정 — 세 자리가 같은 법칙을 쓴다.

할인 Anchoring — 원가 앵커 + 현실적 소요시간

겉보기와 첫 기준이 겹칠 때

다섯 꼭지는 서로 다른 도메인처럼 보이지만, 제품 화면에서는 한번에 만난다. 다크 칩의 글자 두께감(Grade)은 테마를 믿을 수 있게 하고, toast·쿠폰 모션의 ease-out은 "빠르면서도 덜 놀라는" 리듬을 만든다. 토큰 두 층은 그 색과 간격을 고를 수 있는 이름으로 고정한다. QR은 같은 폰에서의 헛수고를 줄이고, 할인 앵커는 가격·시간 기대의 첫 숫자를 바로잡는다.

공통점은 장식 디테일이 아니라 사람이 먼저 느끼는 기준을 어디에 둘지다. 겉보기 굵기, 체감 속도, 고를 이름, 스캔이 필요한 자리, 첫 가격 — 이 기준이 어긋치면 각각은 작은 위화감인데, 한 플로우에 겹치면 "뭔가 싼티이거나 믿을 수 없는" 인상으로 합쳐진다. 이번 메모는 그 기준을 다시 맞추는 쪽에 가깝다.