프론트엔드 개발자의 package.json은 해가 갈수록 뚱뚱해집니다. 알림 하나 띄우려면 서드파티 토스트 라이브러리, 무거운 연산 하나 돌리려면 상태관리 미들웨어, 버튼 하나 재밌게 움직이려면 애니메이션 라이브러리. 그런데 정작 브라우저가 이미 갖고 있는 네이티브 API를 제대로 써본 적은 있나요? 최근 눈에 띄는 사례 세 가지를 엮어보면, '번들 사이즈 0KB'로도 UX를 유의미하게 끌어올리는 전략이 보입니다.
1. Notification API — 10줄이면 되는 브라우저 알림
Velog의 한 개발자가 포모도로 타이머를 만들며 Notification API를 적용한 사례가 흥미롭습니다(velog/@js_baek). 핵심은 단 두 함수입니다. Notification.requestPermission()으로 권한을 받고, new Notification(title, { body, icon })으로 알림을 쏘면 끝이에요. onclick 핸들러를 걸면 알림 클릭 시 window.focus()까지 자연스럽게 연결됩니다.
사용자 입장에서 생각해 볼 부분이 있습니다. 포모도로처럼 탭을 벗어난 상태에서 시간 기반 이벤트를 알려야 하는 시나리오는 실무에서도 빈번합니다 — 긴 빌드 완료 알림, 실시간 채팅의 새 메시지, 타이머 기반 퀴즈 앱 등. 이런 곳에 react-toastify 같은 인앱 토스트를 쓰면 탭 비활성 시 사용자가 놓칩니다. Notification API는 OS 레벨 알림이기 때문에 탭을 떠나 있어도 도달률이 확보되죠. 번들에 1바이트도 추가하지 않으면서요.
다만 한 가지, Notification.permission이 denied인 경우의 폴백 UX는 반드시 설계해야 합니다. 권한 거부 시 인앱 토스트로 폴백하는 식이죠. 이 부분을 빠뜨리면 "알림이 왜 안 와요?"라는 CS가 쏟아집니다. 기획자가 이걸 의도한 건지 항상 확인해야 하는 지점이에요.
2. Web Worker — 메인 스레드는 UI 전용입니다
Dev.to에 올라온 Aaron Rose의 글(dev.to/aaron_rose)은 Web Worker의 필요성을 '주방장과 보조 셰프' 비유로 설명합니다. 핵심 메시지는 명확해요: async/await는 '기다리는 작업'을 비동기로 돌리는 것이지, CPU 바운드 연산을 메인 스레드에서 빼주는 게 아닙니다. CSV 파싱, 대량 데이터 정렬, 이미지 리사이징 같은 '적극적인 연산'은 postMessage로 Worker에 넘겨야 UI가 살아남습니다.
실제로 Lighthouse 퍼포먼스 탭을 열어보면, 50ms 이상의 Long Task가 한 블록이라도 있으면 TBT(Total Blocking Time) 점수가 확 떨어지는 걸 볼 수 있습니다. 사용자 입장에서는 로딩 스피너가 '멈추는' 경험이고요. Web Worker를 도입하면 스피너는 매끄럽게 돌고, 버튼 클릭도 즉각 반응합니다. 여기서 추가 팁으로, 대용량 ArrayBuffer를 다룰 때는 Transferable Objects로 넘기면 데이터 복사 비용이 0에 수렴합니다. worker.postMessage(buffer, [buffer]) 한 줄이면 됩니다.
Figma에서 볼 때는 괜찮았는데 실제로 구현하면 스피너가 버벅이는, 그 디자인-개발 갭의 정체가 바로 메인 스레드 블로킹이에요. 이 라이브러리 도입하면 bundle size가... 하는 고민을 하기 전에, 브라우저가 이미 제공하는 new Worker()부터 꺼내 드세요.
3. CSS 네이티브 인터랙션 — transform 하나로 감성을 만든다
LovedIn이라는 프로포즈 플랫폼 케이스 스터디(dev.to/oluchii)에서 인상적이었던 건 "No" 버튼의 마이크로 인터랙션입니다. 호버 시 transform: translate(80px, -30px)으로 버튼이 도망가는데, JavaScript 한 줄 없이 CSS transition만으로 구현했어요. transform은 레이아웃 리플로우를 트리거하지 않기 때문에 퍼포먼스 측면에서도 깔끔합니다.
더 주목할 건 반응형 대응입니다. 데스크톱에서는 80px, 모바일에서는 40px로 이동 거리를 줄여 버튼이 뷰포트 밖으로 날아가지 않게 방어했어요. 이런 디테일, 사실 1px 단위로 봐야 합니다. 모바일에서 터치 타깃이 사라지면 접근성(a11y) 위반이거든요. CSS 변수와 미디어 쿼리 조합이면 브레이크포인트별로 인터랙션 강도를 세밀하게 제어할 수 있습니다.
LovedIn의 디자인 시스템도 인상적입니다. Scarlet Blush, Wild Strawberry, Petal Frost 같은 시맨틱 컬러 토큰을 base.css에 CSS 커스텀 프로퍼티로 선언하고, 이를 모든 컴포넌트에서 참조하는 구조예요. 디자인 토큰 기반 시스템이 '라이브러리 없이'도 일관된 감성 UX를 만들 수 있다는 좋은 증거입니다.
시사점 — 브라우저를 먼저 믿어볼 것
세 사례가 공통으로 말하는 건 하나입니다: npm install 전에 MDN을 먼저 펼쳐라. Notification API는 인앱 토스트 라이브러리의 맹점(탭 비활성 시 도달 불가)을 보완하고, Web Worker는 상태관리 미들웨어 없이 Long Task를 제거하며, CSS transform + transition은 Framer Motion 없이도 감성적 마이크로 인터랙션을 만듭니다.
물론 네이티브 API에도 한계는 있습니다. Notification API는 모바일 Safari의 제약이 여전하고, Web Worker는 DOM 접근이 불가하며, CSS만으로는 복잡한 시퀀스 애니메이션에 한계가 있죠. 하지만 2026년 현재, Container Queries, :has() 셀렉터, @layer까지 CSS 스펙이 빠르게 확장되고 있고, 브라우저 API의 표현력은 해마다 넓어지고 있습니다.
번들 사이즈가 줄면 Core Web Vitals가 좋아지고, 메인 스레드가 가벼워지면 INP(Interaction to Next Paint)가 개선됩니다. 결국 이건 DX(Developer Experience) 이전에 UX 성능 지표로 직결되는 이야기예요. 다음에 라이브러리를 검색하기 전에, 브라우저 DevTools를 열고 이미 갖고 있는 것부터 확인해 보시길 권합니다. 생각보다 많은 문제가, 이미 해결되어 있으니까요.