-
floating-ui — MUI, Radix, Base UI까지 쓰이는 포지셔닝 엔진React 2026. 7. 10. 23:40
툴팁, 드롭다운, 팝오버를 직접 구현해본 적 있다면 한 번쯤 이런 생각을 해봤을 것이다.
"왜 이게 이렇게 귀찮지?" "스크롤하면 위치 틀어지고" "뷰포트 밖으로 튀어나가고…"
그래서 대부분은 MUI, Radix, Base UI 같은 라이브러리를 쓰게 된다.
근데 여기서 한 단계 더 들어가 보면, 이 라이브러리들이 공통으로 의존하는 핵심 엔진이 하나 있다. 바로 floating-ui다.
floating-ui가 뭔가요?
floating-ui는 툴팁, 팝오버, 드롭다운처럼 기준 요소(reference)에 붙어서 "떠 있는" UI(floating element)의
- 위치 계산
- 충돌 감지
- 뷰포트 보정
- 스크롤 / 리사이즈 대응
을 담당하는 저수준 포지셔닝 라이브러리다.
👉 UI 컴포넌트를 만들어주는 게 아니라
👉 UI를 "어디에 배치할지" 계산해주는 엔진에 가깝다.
Popper.js랑 무슨 관계인가요?
floating-ui는 Popper.js를 만든 동일한 팀(atomiks, Federico Zivolo)이 Popper를 재설계·리브랜딩한 프로젝트다.
별개 팀이 새로 만든 게 아니다.
저장소와 조직명도 변경됐는데, Popper에서 Floating UI로의 전환은 composability, 크로스플랫폼 호환성, 번들 사이즈, 더 현대적인 API에 집중한 결과였으며, 변경 폭이 메이저 릴리스를 넘어설 만큼 커서 리브랜딩까지 결정됐다. (참조 GitHub )
Popper.js와의 차이점을 요약하면?
- 더 작은 번들 사이즈 (tree-shakeable 설계)
- 더 함수형·미들웨어 기반 API
- DOM 전용이 아닌 크로스플랫폼 — React DOM, React Native, Vue 등 다양한 플랫폼 지원
💡 Popper.js 저장소 자체도 현재 floating-ui 모노레포에 통합되어 있고, Popper v2는 low-maintenance 상태다.
누가 쓰고 있나요?
✅ Radix UI — floating-ui 완전 채택
Radix가 Tooltip, Popover, DropdownMenu, HoverCard 등의 컴포넌트에 floating-ui를 채택했다.
Radix는 내부적으로 @floating-ui/react-dom 패키지를 모든 오버레이 포지셔닝에 사용하고 있어서, @radix-ui/react-tooltip을 사용하면 이미 floating-ui에 의존하고 있는 셈이다. XPkgPulse
shadcn/ui도 Radix 위에 올라가 있으니, shadcn/ui를 쓰는 프로젝트라면 이미 floating-ui를 간접적으로 사용하고 있다.
⚠️ Material UI — 아직 Popper.js v2 기반
여기서 중요한 팩트가 하나 있다.
많은 글에서 "MUI가 floating-ui를 쓴다"고 설명하는데, 현재 @mui/material의 Tooltip, Popover, Menu는 여전히 Popper.js v2 기반이다.
MUI Base의 Popper 컴포넌트 공식 문서에도 "Popper.js v2에 의존하며, Popper.js는 더 이상 유지보수되지 않고 Floating UI로 대체되었다"고 명시되어 있다.
즉, floating-ui 전환은 현재 Base UI를 통해 점진적으로 진행 중인 상태다. MUI
✅ Base UI — floating-ui 기반으로 새로 설계
Base UI는 Radix, Floating UI, Material UI를 만든 팀들이 함께 개발하는 unstyled UI 컴포넌트 라이브러리로, floating-ui 위에 구축된 차세대 headless 라이브러리다.
MUI의 미래 방향이라고 볼 수 있다. GitHub
✅ 그 외
- Mantine — floating-ui를 직접 의존성으로 사용
- React Aria (Adobe)
- Headless UI (Tailwind 팀)도 floating-ui 기반 PkgPulse
어떻게 쓰나요? (현재 API 기준)
⚠️ 인터넷에 돌아다니는 오래된 예제 중엔 { x, y, reference, floating, strategy }를 직접 구조분해해서 top: y ?? 0 처럼 쓰는 방식이 많다. 이건 구버전 API다. 현재 공식 API는 아래 방식을 사용한다.
import { useFloating, offset, flip, shift, autoUpdate, } from '@floating-ui/react'; function Tooltip() { const { refs, floatingStyles } = useFloating({ middleware: [offset(8), flip(), shift()], whileElementsMounted: autoUpdate, // 스크롤/리사이즈 대응 }); return ( <> <button ref={refs.setReference}>Hover me</button> <div ref={refs.setFloating} style={floatingStyles}> Tooltip content </div> </> ); }각 요소의 역할은 다음과 같다.

floating-ui를 직접 써야 할 때
1️⃣ 사내 디자인 시스템 / 커스텀 컴포넌트를 만들 때
라이브러리 없이 직접 툴팁이나 셀렉트 박스를 만들어야 한다면 floating-ui가 위치 계산을 깔끔하게 해결해준다.
2️⃣ Radix / MUI가 제공하지 않는 동작이 필요할 때
"Popover 위치 로직만 살짝 바꾸고 싶은데" 같은 상황에서 직접 floating-ui를 붙이면 자유도가 확 올라간다.
3️⃣ headless 컴포넌트를 만들 때
디자인은 직접 하고, 위치 계산만 맡기고 싶을 때 딱 맞는 수준의 추상화를 제공한다.
반대로 굳이 직접 안 써도 되는 경우
이미 Radix나 Base UI를 쓰고 있다면 직접 쓸 필요가 거의 없다.
표준적인 접근 가능한 컴포넌트가 필요하다면 Radix에서 처리하고, floating-ui를 직접 사용하는 건 Radix 프리미티브가 커버하지 않는 커스텀 컴포넌트를 만들 때만이 일반적이다. PkgPulse
floating-ui는 저수준 도구라 "편의성"보다는 "제어권"을 주는 방향으로 설계되어 있다.

한 줄 요약 💚
"우리가 쓰는 UI 라이브러리 뒤에서 조용히 위치를 계산하고 있는 라이브러리"
참고 링크
'React' 카테고리의 다른 글
🧩 React 19의 <Activity>란? (0) 2025.11.10 중첩 래퍼(Wrapper) 컴포넌트가 많은 UI 구조에서의 이벤트 처리 전략 고민해보기 🧐 (0) 2025.11.02 리액트에서 @loadable/component로 코드 스플리팅 하기 (1) 2025.08.18 React에서 우클릭 메뉴를 커스텀하게 만들기 (onContextMenu 이벤트를 활용한 간단한 메뉴 구현) 😘 (3) 2025.07.27 Controlled 컴포넌트와 UnControlled 컴포넌트 😊 공통 컴포넌트 고민해보기 (1) 2025.07.13