
최근에 과제 전형을 진행하면서 UI 컴포넌트를 직접 구현할 기회가 있었다. 이 기회를 통해 다양한 컴포넌트를 만들어 보고, 다른 사람들과 인사이트를 공유하고 싶어 UI 컴포넌트 스터디를 운영하게 되었다.
이번 스터디에서 중요하게 생각한 점은 다음과 같다:
React와 TypeScript, Storybook 사용 경험 쌓기첫 번째 주에 구현한 것은 tooltip이었다.
라이브러리를 사용할 때는 쉬워 보였으나, 직접 구현하려니 고려할 사항이 많았다.
tooltip 컴포넌트를 구현한 과정을 정리해 보고자 한다.
툴팁 컴포넌트로 감싼 요소에 마우스를 오버하면 툴팁이 나타나고, 마우스를 아웃하면 툴팁이 사라져야 한다.
Tooltip 컴포넌트를 구현하는 데 사용한 코드는 세 부분으로 나눌 수 있다:
Tooltip.tsx)Tooltip.css)Tooltip.stories.tsx)이 파일에서는 Tooltip 컴포넌트의 메인 로직을 정의한다.
// src/components/Tooltip.tsx
import React, { useState } from "react";
import "./Tooltip.css";
export type TooltipProps = {
content: string;
children: React.ReactNode;
};
const Tooltip = ({ content, children }: TooltipProps) => {
const [visible, setVisible] = useState(false);
const showTooltip = () => setVisible(true);
const hideTooltip = () => setVisible(false);
return (
<div className="tooltip-container" onMouseEnter={showTooltip} onMouseLeave={hideTooltip}>
{children}
{visible && <div className="tooltip">{content}</div>}
</div>
);
};
export default Tooltip;
useState 훅을 사용하여 visible 상태를 정의하고, 이를 통해 툴팁의 표시 여부를 제어한다.TooltipProps 타입을 정의하여 content와 children을 props로 받는다.content: 툴팁에 표시될 텍스트children: 툴팁을 감쌀 요소showTooltip과 hideTooltip 함수는 마우스 이벤트에 반응하여 visible 상태를 변경한다.div 요소에 onMouseEnter와 onMouseLeave 이벤트 핸들러를 설정하여 툴팁의 표시와 숨김을 제어한다.visible 상태에 따라 툴팁(div.tooltip)을 조건부 렌더링한다.이 파일에서는 Tooltip 컴포넌트의 스타일을 정의한다.
/* src/components/Tooltip.css */
.tooltip-container {
position: relative;
display: inline-block;
}
.tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 6px 14px;
border-radius: 10px;
white-space: nowrap;
z-index: 10;
}
.tooltip-container 클래스는 툴팁을 감싸는 요소의 스타일을 정의한다.
position: relative를 사용하여 툴팁이 이 요소를 기준으로 배치될 수 있게 한다..tooltip 클래스는 툴팁 자체의 스타일을 정의한다.
position: absolute를 사용하여 툴팁이 .tooltip-container 요소를 기준으로 절대 위치에 배치된다.bottom: 100%과 left: 50%를 통해 툴팁을 부모 요소의 아래쪽 중앙에 배치한다.transform: translateX(-50%)로 툴팁을 가로축에서 중앙 정렬한다.z-index를 설정하여 툴팁의 외형을 지정한다.이 파일에서는 Storybook을 사용하여 Tooltip 컴포넌트를 문서화하고 시각적으로 테스트할 수 있다.
// src/components/Tooltip.stories.tsx
import { Meta, StoryObj } from "@storybook/react";
import Tooltip from "./Tooltip";
const meta: Meta<typeof Tooltip> = {
title: "Tooltip",
component: Tooltip,
tags: ["autodocs"],
parameters: {
layout: "centered",
},
args: {
content: "This is a tooltip",
},
} satisfies Meta<typeof Tooltip>;
export default meta;
type TooltipStory = StoryObj<typeof meta>;
export const Default: TooltipStory = {
args: {
children: <span>Hover over me</span>,
},
};
meta 객체는 Storybook에서 Tooltip 컴포넌트의 메타데이터를 정의한다.
title: Storybook 사이드바에서 컴포넌트를 그룹화하거나 분류하는 방법component: 사용할 컴포넌트를 지정tags: 컴포넌트에 대한 문서를 자동으로 생성하는 데 사용parameters: Storybook의 설정을 정의args: 기본적으로 사용할 props를 지정Default 스토리는 기본적인 Tooltip 컴포넌트를 렌더링한다.
args는 children을 설정하여 툴팁을 테스트할 수 있게 합니다.이렇게 구현한 tooltip은 Storybook을 통해 테스트할 수 있고, 시각적으로 확인할 수 있다.

현재 구현한 툴팁은 기본적인 기능만 제공하고 있어 추가로 구현할 사항을 정리해 보았다.
tooltip 방향 지원
left, right, bottom, top, topLeft, topRight, bottomLeft, bottomRight, leftTop, leftBottom, rightTop, rightBottom으로 뜰 수 있도록 구현딜레이 설정
delay 시간을 custom 할 수 있도록 구현닫기 버튼
포커스와 키보드 접근성 지원
aria 속성 추가툴팁 크기 및 위치 자동 조절
툴팁 내용 동적 업데이트
스타일 커스터마이징
클릭 이벤트로 툴팁 표시
다양한 트리거 방식 지원
이 모든 기능을 다 구현할지는 모르겠지만, 추가로 기능을 구현하여 툴팁을 고도화할 예정이다.