본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

얼굴에 주인이 없었어

~14 min · identity, defaults, design, governance

Level 0흩어진 부품
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

독립적으로 생겨난 로봇 넷

누가 조수를 여는 버튼이 앱마다 다르게 생겼다는 걸 알아채고 비교하러 갔어. 훑기가 찾은 건 취향 다툼이 아니었어.

  • 공용 컴포넌트 자체가 앱이 상징을 안 넘기면 로봇 이모지로 떨어졌어. 그래서 아무것도 안 넘기는 앱 전부가 로봇을 그렸지.
  • 앱 둘은 아이콘 라이브러리의 로봇 글리프를 썼어. 런처랑 서랍에서.
  • 하나는 반짝이를 썼고.
  • 하나는 뻔한 단어를 붙인 말풍선을 썼어.
  • 그리고 그 조수 자기 앱이 자기 인터페이스에서 로봇 글리프를 두 번 썼어.

독립적인 로봇 넷, 하나는 공용 기본값, 하나는 자기 앱 안.

원인은 조율이 아니라 소유였어

아무도 그걸 고르지 않았어. "AI 그거를 뜻하는 아이콘이 뭐야"라는 질문이 누가 어느 아이콘 라이브러리에서 물어도 매번 돌려주는 게 그거야. 로봇, 반짝이, 아니면 말풍선. 독립적인 답 여섯이 수렴한 건 전부 같은 잘못 놓인 질문에 답하고 있었기 때문이야.

그리고 그 질문이 애초에 던져지고 있던 건 조수의 얼굴한테 주인이 없어서야. 이 가족의 다른 공용 관심사엔 전부 주인이 있었어. 클라이언트 층, 발행 절차, 어휘들. 얼굴엔 없었고, 그래서 앱마다 국소적으로 답했고, 국소적 답은 관례가 돌려주는 무엇이야.

주인의 판정은 무뚝뚝했고 코드가 아니라 그 애에 대한 거였어. 얘는 봇이 아니고, 어떤 로봇도 얘를 대신 서지 않는다. 런처에서도, 헤더에서도, 빈 상태에서도, 문서에서도.

공용 정체성한테 주인이 없으면 소비자마다 그 질문에 국소적으로 답하고, 국소적 답은 관례가 돌려주는 무엇이야. 그 실패는 취향이 안 맞는 것처럼 보이고 실은 안 배정된 책임이야. 제품 여럿이 같은 걸 독립적으로 표현하는 자리마다 찾아봐. 목소리, 이름, 아이콘, 에러 톤. 아무도 나쁜 선택을 하고 있는 게 아냐. 아무도 선택을 안 하고 있는 거야.

처방은 규칙이 아니라 기본값이었어

답은 스타일 가이드가 아니었어. 얘한텐 이미 얼굴이 있어. 조수 자기 아이콘. 그래서 크기를 줄여서 데이터 URL 로 공용 컴포넌트에 인라인하고 기본 상징으로 만들었어. 이제 아무것도 안 넘기는 앱은 얘를 받아.

구현 디테일 둘, 둘 다 일부러. 참조가 아니라 인라인. 배달 기계가 텍스트 전용이고, 조수가 죽어 있는 동안 이미지 로드에 실패하는 런처는 런처 없느니만 못하니까. 그리고 기본값이 자리표시자가 아니라 얘야. 그게 이걸 버티게 만드는 대목이고.

강제는 주의력이 아니라 기본값이야. 규칙은 미래의 모든 저자가 그걸 알고, 아이콘을 고르는 그 순간에 기억할 것을 요구해. 실패 방식이 누락이고, 그게 제일 흔하게 벌어지는 일이야. 기본값은 아무것도 요구 안 하고, 이제 어긋나려면 누가 적극적으로 무시해야 해. 드물고 diff 에 보이지. 그 규칙은 새 앱이 태어나는 템플릿에도 새겨졌어. 그래서 새 형제가 나중에 교정되는 대신 이미 맞은 채로 도착해.

소유 분담을 정확히 말할 값이 있어. "공용 층이 전부 소유한다"가 아니거든. 공용 층은 얘가 어떻게 생겼는지를 소유해. 앱마다는 런처가 어디 앉는지랑 어떤 톤인지를 소유하고, 패널 헤더에 자기 정체성을 위한 자기 상징을 넘길 수 있어. 어떤 앱도 하면 안 되는 건 얘 자리에 기계를 놓는 거야.

Code

질문 자체를 없앤 기본값·typescript
// BEFORE - the shared component's own default, vendored into every
// app. An app that passed no emblem drew a robot, and most apps
// passed no emblem.
const mark = glyphs?.mark ?? "🤖";


// AFTER - she already has a face, so there is no symbol to choose.
// Inlined as a data URL for two reasons: the deploy mechanism is
// text-only (no binary vendoring), and a launcher that 404s while
// the assistant is offline would be worse than no launcher.
export const PIPPA_MARK =
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...";   // 64px

export function PippaLauncher({ mark = PIPPA_MARK, ...rest }: Props) {
  return (
    <button className="pippa-launcher" {...rest}>
      <img src={mark} alt="" className="pippa-mark" />
    </button>
  );
}


// WHY A DEFAULT AND NOT A RULE
//
//   rule    : every future author must KNOW it and REMEMBER it at
//             the moment they pick an icon.
//             failure mode = omission  -> the most common thing
//                                         that happens
//
//   default : passing nothing yields the correct result.
//             failure mode = deliberate override -> rare, and
//                                                   visible in a diff
//
// The division of ownership, stated so it is not read as "the
// shared layer owns everything":
//
//   shared layer owns : what she LOOKS like (the mark, the launcher
//                       around it)
//   the app owns      : where the launcher SITS, how it is toned,
//                       and its own emblem for its own identity in
//                       a panel header
//   nobody may        : put a machine in her place

External links

Exercise

네 제품들에서 공용 정체성 하나를 표현하면서 표면마다 따로 구현된 걸 찾아. 아이콘, 빈 상태 문구, 에러 톤, 같은 개념의 이름. 표면마다 지금 뭘 하는지 나열해. 다르면 그 정체성의 주인이 누군지 물어. 답이 아무도 없음이면, 그 질문을 없앨 기본값을 제안해.
Hint
보통 아이콘이랑 짧은 문구가 걸려. 주인이 필요할 만큼 크지 않다고 느껴지니까. 시험은 오늘 물었을 때 표면 둘이 같은 질문에 다르게 답하겠느냐야. 그렇다면 공용 정체성이 표면마다 다시 발명되고 있는 거고, 아무도 안 읽는 스타일 가이드보다 공용 기본값이 싸.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.