[번역] Tooltip Components Should Not Exist

[번역] Tooltip Components Should Not Exist

2025-11-18

TkDodoTooltip Components Should Not Exist 를 번역한 글입니다.

1

솔직히 말하자면, 웹 앱에서 엉망인 툴팁은 내가 가장 싫어하는 것 중 하나입니다. 그리고 사실 제대로 된 툴팁을 만들기란 생각보다 꽤 어렵기도 합니다. 툴팁에는 고려해야 할 요소들이 정말 많기 때문이죠:

  • 접근성(Accessibility)
  • 키보드 상호작용(Keyboard interactivity)
  • 모든 사용자에게 ‘최소한의 놀라움’ 원칙 지키기
  • 중요한 정보를 툴팁 뒤에 가려버리지 않기

수년간 여러 디자인 시스템들이 소비자(사용자)에게 제공할 컴포넌트를 구현하려고 시도하는 걸 봐왔는데, 솔직히 말하면 하나의 공통점이 있습니다. 의도한 대로 사용되지 않는다는 것입니다.

API 설계 관점에서 보면, 이는 아마 컴포넌트라는 추상이 너무 저수준이기 때문일 것입니다. 그리고 이게 바로 오늘의 핫테이크 🌶:

Tooltip 컴포넌트는 존재해서는 안 됩니다

툴팁 자체가 없어야 한다는 이야기는 아닙니다. 툴팁은 올바르게 — 각자의 사용 사례에서 “올바르게”가 무엇이든 간에 — 적용된다면 꽤 유용한 도구입니다.

물론 충분한 교육으로 해결할 수도 있을 것입니다. 하지만 솔직히 말해볼까요? 문서를 꼼꼼히 읽는 사람은 극히 드물고, AI는 이미 본 패턴을 그대로 재생산할 뿐이라서, 우리 코드베이스에 있는 안티 패턴들을 그대로 증폭시킬 확률이 높습니다.

그래서 대안을 이야기하기 전에, 먼저 툴팁을 잘못 사용했을 때 발생하는 잠재적인 문제들을 한번 살펴봅시다.

Keyboard Interactivity

이 부분은 사실 너무 당연합니다. 우리는 모든 사람을 위한 웹앱을 만들어야 하며, 그 말은 곧 모든 사용자가 마우스를 사용하지는 않는다는 점을 항상 인지해야 한다는 뜻입니다.

그럼에도 불구하고, 저는 종종 “툴팁을 트리거하는 요소가 인터랙티브하지 않을 때 hover에서만 툴팁을 보여주는” 구현을 자주 마주칩니다.

이 문제를 확인하기 위해 멀리 갈 필요도 없습니다. 가장 인기 있는 컴포넌트 라이브러리 중 하나인 Material UI만 봐도 그렇습니다. 공식 문서에 있는 기본 tooltip 예제는 다음과 같습니다:

// MUI-basic-tooltip
<Tooltip title="Delete">
  <IconButton>
    <DeleteIcon />
  </IconButton>
</Tooltip>

이 예제는 간단하고 잘 동작합니다. 하지만 아이콘 같은 요소, 혹은 Badge처럼 인터랙티브하지 않은 다른 요소에 <Tooltip>만 둘러주면 어떻게 될까요?

// MUI-non-interactive-tooltip
<Tooltip title="Home">
  <IconHome />
</Tooltip>

<Tooltip title="Unread Mails">
  <Badge badgeContent={4} color="primary">
    <IconMail color="action" />
  </Badge>
</Tooltip>

맞습니다 — 그런 경우에도 툴팁은 hover에서는 여전히 나타납니다. 하지만 focus에서는 나타나지 않습니다. 왜냐하면 Tab으로 이동할 때 해당 요소를 아예 건너뛰기 때문이죠. 해당 요소는 키보드로 상호작용할 수 있는 요소가 아니기 때문에 포커스를 받을 일이 없고, 결과적으로 키보드로만 탐색하는 상황에서는 툴팁이 절대 나타나지 않습니다.

또 하나의 문제는, <Tooltip> 컴포넌트에 어떤 children이 전달되는지 우리가 통제할 수 없기 때문에 이 문제를 타입 안전하게(type-safe) 해결할 방법도 없다는 점입니다.

React Aria의 접근 방식은 조금 더 낫다. 인터랙티브하지 않은 요소에는 애초에 툴팁을 표시하지 않기 때문입니다. 이렇게 하면 마우스를 주로 사용하는 개발자라도 문제를 더 빨리 눈치채기 쉽습니다. 그리고 이 문제를 해결하려면 커스텀 트리거<Focusable> 컴포넌트로 감싸면 됩니다.

이 방식은 다른 라이브러리들의 접근 방식보다 훨씬 나은 편이지만, 여전히 몇 가지 문제가 남아 있습니다. 특히 다음과 같은 점들입니다:

Least Surprise For All Users

만약 <Tooltip>을 어떤 요소에든 붙일 수 있게 해두면, 누군가는 정말로 어디에든 붙이려고 할 것입니다.

저는 문장 한가운데 있는 특정 텍스트에, 추가 정보가 있다는 그 어떤 시각적 힌트도 없이, 툴팁이 달려 있는 경우를 실제로 본 적도 있습니다.

반대로 정말 불편한 경우도 있습니다. 의미를 전혀 이해할 수 없는 아이콘만 있는 버튼을 봤는데, 정작 그 버튼을 누르면 무슨 일이 일어나는지 아무런 정보도 제공되지 않는 경우입니다.

개발자와 디자이너가 어느 정도 규모로 함께 일하는 순간, 이런 불일치가 앱 곳곳에서 발생하는 건 사실상 피할 수 없습니다.

그렇다면, 독립적인 <Tooltip> 컴포넌트가 이상적이지 않다면 디자인 시스템은 툴팁의 동작을 어떻게 제공해야 할까요? 제 생각은 이렇습니다:

일관적이고 접근성 있는 툴팁 사용을 강제하는 더 상위 수준의 패턴 컴포넌트만 제공하라.

과거에 실제로 꽤 잘 작동하는 걸 봤던 방식들은 다음과 같습니다:

  • <Button>이나 <Link> 같은 인터랙티브 컴포넌트에는 선택적 title prop을 제공합니다. 이렇게 하면 필요할 때 추가 정보를 표시할 수 있습니다. 인터랙티브 요소는 UI에서 쉽게 눈에 띄고, 키보드 탭 탐색에서도 자연스럽게 발견됩니다.
  • <IconButton>에는 title prop을 필수로 지정합니다. 이렇게 하면 아이콘의 의미를 사용자에게 명확히 전달할 수 있고, 접근성 측면에서도 버튼에 올바른 레이블을 부여할 수 있습니다.
  • 정보 아이콘이나 물음표 아이콘과 함께 툴팁을 렌더링하는 <InfoIcon> 컴포넌트를 추가로 제공합니다. 이렇게 하면 사용자가 추가 정보가 어디에 있는지 쉽게 인지할 수 있고, 내부적으로는 해당 요소가 포커스를 받을 수 있도록 보장할 수 있습니다.
  • 텍스트에 더 많은 맥락을 제공할 수 있도록 <InfoText> 컴포넌트를 만듭니다. 이 컴포넌트는 점선 밑줄 같은 방식으로 일반 텍스트와 시각적으로 구분되어야 하고, 물론 키보드로도 상호작용 가능해야 합니다.

물론 내가 놓치고 있는 다른 요소들도 있을 것입니다. 하지만 그런 경우라도 모두에게 저수준 컴포넌트를 공개하는 것보다는 새로운 패턴 컴포넌트를 하나 더 만드는 편이 훨씬 낫습니다.

오해하지 맙시다. 유연성은 많은 상황—예를 들어 레이아웃 구성 같은 경우—에서 정말 중요합니다. 하지만 툴팁에 있어서만큼은 일관된 UX를 제공하고, 모든 사용자를 포용하는 것이 훨씬 더 중요합니다. 그래서 오히려 제한을 두는 것이 더 바람직합니다.

그리고 제한은 창의성을 자극하기도 합니다. 화면 공간이 부족하다는 이유만으로 정보를 툴팁 뒤에 숨길 수 없다면, 우리는 어떤 아이디어를 처음부터 다시 설계할 기회를 얻을지도 모릅니다.

그러니 조직을 위한 디자인 시스템을 만들고 있다면, 공개된 인터페이스에 컴포넌트를 넣고 싶은 유혹을 잠시 참아보길 바랍니다.