폼 컨트롤에 물리 엔진을 붙인다는 것 — Jelly UI 가 다시 부른 즐거움과 접근성의 오래된 진자
폼 컨트롤에 물리 엔진을 붙인다는 것 — Jelly UI 가 다시 부른 즐거움과 접근성의 오래된 진자
폼 컨트롤에 물리 엔진을 붙이는 것은 잃어버린 UI 의 즐거움을 되찾는 일인가, 접근성·성능·사용성을 대가로 치르는 또 하나의 유행성 기믹인가.
도입 — 301 점이 둘로 갈린 자리
2026 년 7 월 21 일 (KST), Hacker News 의 첫 페이지에 Jelly UI 라는 이름의 프로젝트가 올라왔다. 제목은 “Jelly UI: Soft-body physics for native HTML form controls” 였다. 301 점을 받고 125 개의 댓글이 달렸다. 소개 문구는 짧다. Jelly UI 는 “dependency-free Web Components library for soft, tactile product interfaces” — 의존성 없는, 부드럽고 촉각적인 인터페이스를 위한 Web Components 라이브러리다. 40 개의 커스텀 엘리먼트, 제로 의존성, 스크립트 태그 하나. 태그라인은 그 성격을 그대로 드러낸다. “It’s okay to be a little jelly.”
핵심 발상은 이렇다. 체크박스, 토글 스위치, 슬라이더 같은 실제 폼 컨트롤에 소프트바디(soft-body) 물리 시뮬레이션을 입힌다. 체크박스를 누르면 젤리처럼 출렁이고, 토글을 넘기면 관성으로 흔들리며, 슬라이더의 손잡이는 포인터를 스프링처럼 뒤늦게 따라온다. 여기에 dark mode, RTL(right-to-left) 지원, WCAG AA 색상 토큰이 기본 내장되어 있다고 소개는 말한다. 즉 이 라이브러리는 단순한 눈요기 데모가 아니라, 접근성 토큰을 명시적으로 자기 이름표에 붙인 프로덕션 지향의 컴포넌트 세트를 표방한다.
주목할 것은 프로젝트 자체가 아니라 그것이 만든 반응의 모양이다. 125 개의 댓글은 거의 정확히 둘로 갈렸다. 한쪽은 “잃어버린 즐거움” 을 되찾았다고 환영했고, 다른 쪽은 접근성·성능·사용성을 대가로 치른 기믹이라고 비판했다. 이 분열은 우연이 아니다. 그것은 프론트엔드와 UX 가 십 년 주기로 반복해 온 하나의 긴장 — 즐거움(delight) 과 스큐어모피즘(skeuomorphism) 대(對) 접근성·성능·사용성 — 의 가장 최근 발현이다. 이 글은 Jelly UI 라는 구체적 사물을 렌즈 삼아, 그 진자가 어디까지 왔고 어떤 트레이드오프가 그 아래 깔려 있는지 본다.
현상 — Jelly UI 는 무엇이고 왜 화제인가
Jelly UI 의 기술적 실체는 Web Components 다. 커스텀 엘리먼트와 Shadow DOM 으로 40 개의 컴포넌트를 캡슐화하고, API 레퍼런스는 “모든 attribute, property, method, event, slot, shadow part, CSS custom property, 그리고 keyboard map” 을 문서화한다고 밝힌다. 이 목록이 중요한 이유는, 그것이 이 프로젝트의 야심을 드러내기 때문이다. shadow part 와 CSS custom property 를 노출한다는 것은 스타일 커스터마이징을 지원한다는 뜻이고, keyboard map 과 standard events 를 명시한다는 것은 키보드 접근성과 네이티브 이벤트 계약을 지키려 한다는 뜻이다. 소개 문구가 “native forms, keyboard access, standard events” 를 앞세우는 것은 이 라이브러리가 네이티브 폼 컨트롤을 대체하는 것이 아니라 감싸는 것을 지향한다는 신호다.
그러나 화제의 중심은 그 위에 얹힌 물리다. 소프트바디 시뮬레이션은 프레임마다 각 요소의 정점(vertex) 위치를 스프링-질량 모델로 재계산해야 한다. 정적인 CSS transition 으로는 젤리의 출렁임을 낼 수 없기 때문이다. 이 지점이 스레드의 첫 번째 전선(戰線)이었다. 사용자 jlukic 은 성능 문제를 정면으로 지적했다. “이 라이브러리는 8ms 마다 RAF(requestAnimationFrame) 애니메이션 루프를 돌리고, 페이지 위의 활성 컴포넌트마다 매 프레임 재계산한다.” 8ms 라는 숫자는 초당 약 120 프레임을 겨냥한다는 뜻이고, 그것은 메인 스레드를 상시 점유한다는 뜻이다.
이에 대한 반론도 즉시 나왔다. 사용자 Rohansi 는 측정으로 맞섰다. 위젯 몇 개를 렌더링하는 것 자체는 큰 자원을 쓰지 않으며, 실제 CPU 를 잡아먹는 것은 페이지 상단의 애니메이션 SVG 헤더라는 것이다. 그의 계측으로는 헤더가 있을 때 약 35ms, 없을 때 약 6.6ms 였다. 그는 위젯이 상태 변화나 애니메이션 중에만 리페인트되어야지 상시로 리페인트되어서는 안 된다고 덧붙였다. 즉 성능 문제의 상당 부분은 라이브러리의 구조적 결함이라기보다 데모 페이지의 연출 과잉일 수 있다는 반론이다. 이 공방 자체가 Jelly UI 를 흥미로운 사례로 만든다. 문제는 물리 그 자체가 아니라, 물리를 어디에 얼마나 상시로 켜 두느냐다.
옹호의 목소리도 분명했다. 사용자 memjay 는 이렇게 썼다. “가지고 놀아 보니 놀랍도록 즐겁다(surprisingly delightful). 우리는 UI 에 재미를 좀 넣어야 한다.” 제작자 baldvinmar 본인의 변(辯)은 더 직접적이다. “때때로 우리는 순수하게 만드는 기쁨을 위해 만든다. 실용성은 보너스다(Practicality is a bonus).” 이 두 발언은 이 프로젝트의 정당화 논리를 압축한다. 모든 인터페이스가 전환율 지표로 정당화될 필요는 없으며, 장인적 즐거움과 놀이 그 자체에 가치가 있다는 것이다. 이 논리는 진지하게 다뤄질 자격이 있다. 문제는 그 즐거움의 비용을 누가, 어디에서 치르는가다.
심층 — 진자, 그리고 세 갈래의 트레이드오프
Jelly UI 를 이해하려면 그것이 놓인 진자 운동을 먼저 봐야 한다. 2013 년 iOS 7 이 스큐어모피즘을 걷어내고 플랫 디자인으로 전환한 이후, 그리고 Microsoft 의 Metro 와 Google 의 Material Design 이 그 흐름을 굳힌 이후, UI 는 오랫동안 “덜어내는” 방향으로 움직였다. 그 진자가 반대로 튄 첫 신호가 2019 ~ 2020 년의 뉴모피즘(neumorphism, soft UI) 이었다. 부드러운 이중 그림자로 요소를 배경에서 살짝 밀어 올리는 이 스타일은 Dribbble 을 휩쓸었지만, 빠르게 식었다. 이유는 접근성이었다. 뉴모피즘의 미학은 요소와 배경을 같은 색으로 두는 데서 나오는데, 그 결과 텍스트 대비가 WCAG AA 의 최소 기준인 4.5:1 아래로 떨어지고, 요소의 경계 그림자는 약 1.4:1 에 그쳐 WCAG 2.2 의 비텍스트 대비 기준(1.4.11, 3:1) 을 통과하지 못했다. 즐거움을 접근성의 비용으로 산 것이다. 그리고 그 계산서가 도착하자 2021 년에 유행은 사그라들었다.
Jelly UI 는 이 진자의 가장 최근 상승 국면 — 촉각성과 물리성으로의 회귀 — 위에 서 있다. 그리고 흥미롭게도, 뉴모피즘의 교훈을 색상 축에서는 학습했다. WCAG AA 색상 토큰을 기본 내장한다고 명시한 것이 그 증거다. 그러나 같은 긴장을 다른 축 — 모션 — 에서 다시 연다. 세 갈래의 트레이드오프가 그 아래에 있다.
첫째, 접근성과 모션 감수성. 물리 애니메이션은 전정계(vestibular) 장애를 가진 사용자에게 실질적 위해가 될 수 있다. WCAG 2.3.3(Animation from Interactions, AAA) 은 상호작용으로 촉발되는 모션 애니메이션을, 그것이 기능에 필수적이지 않은 한 비활성화할 수 있어야 한다고 요구한다. 전정계 장애 반응은 산만함, 어지럼증, 두통, 메스꺼움을 포함한다. 이 요구를 구현하는 표준 도구가 CSS 미디어 쿼리 prefers-reduced-motion 이고, 그것은 macOS 의 시스템 설정 > 손쉬운 사용 > 동작 줄이기 같은 OS 설정에 연동된다. 스레드에서 이 문제는 곧바로 드러났다. 사용자 bigbuppo 는 단호하게 썼다. “그 데모는 나를 메스껍게 한다(makes me nauseous). 버튼이 저래서는 안 된다.” 사용자 altairprime 은 토글 스위치에서 “본능적인 언캐니 밸리 반응(visceral uncanny valley reaction)” 을 느꼈다고 보고했다.
여기서 미묘하지만 결정적인 함정이 있다. 다른 사용자들(momojo, TurkTurkleton)은 OS 의 “동작 줄이기” 를 켠 상태에서 데모를 열면 애니메이션이 사라져 이 데모가 대체 무엇을 하는 것인지 알 수 없게 된다고 지적했다. 즉 Jelly UI 의 물리는 단순한 장식이 아니라 어포던스(affordance) 그 자체이기도 하다. 출렁임이 “눌렸다” 는 피드백을 겸하는 순간, prefers-reduced-motion 을 존중해 모션을 끄는 것은 곧 상태 신호를 끄는 것이 된다. 접근성을 제대로 지원한다는 것은 “모션을 끈다” 로 끝나지 않고, “모션이 없어도 같은 정보를 전달하는 대체 표현” 을 함께 설계한다는 것을 의미한다. 제작자는 이 피드백을 받아 재생 오버라이드 옵션을 추가했다고 밝혔다. 이는 올바른 방향이지만, 애초에 즐거움이 어포던스와 결합되었을 때 접근성 비용이 얼마나 미묘해지는지를 보여 준다.
둘째, 성능과 입력 지연. 폼 컨트롤의 본질적 임무는 입력 상태를 지연 없이 충실하게 반영하는 것이다. 그런데 소프트바디 물리는 그 충실성을 의도적으로 훼손한다. 슬라이더 손잡이가 포인터를 스프링처럼 뒤늦게 따라오는 것이 그 예다. 사용자 socalgal2 는 물었다. “슬라이더가 포인터보다 뒤처지는 것이 대체 왜 좋은 설계인가?” 사용자 JoshTriplett 은 슬라이더를 드래그할 때 컨트롤이 커서 위치보다 상당히 뒤처져 반응 시간이 나빠진다고 보고했다. 이것은 취향의 문제가 아니라 정보 충실도의 문제다. 값을 정밀하게 맞춰야 하는 컨트롤에서 손잡이의 물리적 지연은 곧 조작 오차다. 여기에 상시 RAF 루프의 비용이 겹친다. 메인 스레드가 매 프레임 물리를 계산하면 스크롤과 다른 입력의 응답성이 떨어진다. 사용자 weego 는 Chrome/MacBook Pro 에서 효과가 미묘함에도 페이지 스크롤이 나빠지고 애니메이션 FPS 가 낮아졌다고 보고했다. 값싼 애니메이션(compositor 에서 처리되는 transform/opacity) 과 비싼 애니메이션(레이아웃을 유발하는 것) 의 구분이 여기서 실무적으로 갈린다. 젤리의 출렁임은 값싼 쪽에 머물기 어렵다.
셋째, 네이티브 대(對) 커스텀 컨트롤. ARIA 의 첫 번째 규칙은 “네이티브 요소로 할 수 있으면 커스텀으로 만들지 말라” 다. 이유는 역사적으로 명백하다. div 로 체크박스를 다시 만들면 키보드 내비게이션, 포커스 관리, 스크린 리더 시맨틱, 폼 제출 참여 같은 네이티브의 “보이지 않는 올바름” 을 전부 다시 구현해야 하고, 대개 그 과정에서 무언가를 놓친다. Jelly UI 의 진지한 답은 form-associated custom elements 와 ElementInternals 를 활용해 커스텀 엘리먼트가 실제 form 에 참여하고 키보드 접근을 유지하도록 하는 것이다. 이것이 “native-preserving” 을 표방하는 근거다. 그러나 표방과 실제는 갈라졌다. 사용자 chrismorgan 은 상세한 리뷰에서, 컴포넌트들이 여전히 JavaScript 를 요구하며(진정한 네이티브가 아니며) 활성화 동작이 부정확하다고 지적했고, checkbox, OTP, range, switch, textarea, alert, pagination, tabs, dialog, menu 전반에 걸친 문제를 열거했다. 특히 OTP 입력에 대해서는 강하게 반대했다. “어떤 경우에도 OTP 에 단일 문자 입력의 연속을 쓰지 말라. 그 동작은 정말 고약하다.” 그는 monospace 로 스타일링한 하나의 통합 입력을 권했다. 사용자 itishappy 는 이 컴포넌트들이 표준 UI 요소를 방대한 반복 끝에 재구현하던 Flash 시절 개발자의 고투를 떠올리게 한다고 썼다. 네이티브를 가깝게 재감쌀수록, 네이티브가 공짜로 주던 올바름을 더 많이 다시 벌어야 한다는 긴장이 여기에 있다.
전망·실무 시사점 — 즐거움은 언제 값을 하는가
이 세 트레이드오프를 종합하면, 판단의 축은 “물리냐 접근성이냐” 라는 이분법이 아니라 빈도(frequency) 와 중대성(criticality) 이다. 마케팅 랜딩 페이지나 게임 메뉴처럼 상호작용이 드물고 실패의 대가가 낮은 자리에서, 젤리의 출렁임은 순수한 이득이다. 반면 은행 앱의 OTP 입력이나 매일 쓰는 업무 폼처럼 상호작용이 잦고 정밀성이 요구되는 자리에서, 같은 물리는 부채가 된다. Jelly UI 가 자기 이름표에 접근성 토큰을 붙인 것은 후자의 시장을 겨냥한다는 신호이지만, 스레드의 비판 대부분은 정확히 그 후자의 맥락에서 나왔다.
실무의 해법은 진자를 한쪽 끝에 고정하는 것이 아니라 점진적 향상(progressive enhancement) 으로 배치하는 것이다. 물리는 컨트롤 위에 옵트인으로 얹히는 층이어야 하고, 그 층이 없어도 컨트롤은 올바르고 빠르게 동작해야 한다. prefers-reduced-motion 을 예외가 아니라 기준선으로 두는 설계 — 즉 모션 없는 상태가 완전한 기본이고 물리는 그 위의 선택적 사치인 설계 — 가 그것이다. 모션 예산(motion budget) 이라는 개념이 여기서 유용하다. 페이지가 감당할 수 있는 상시 애니메이션의 총량을 예산처럼 관리하고, 물리를 상호작용의 순간에만 짧게 지출하는 것이다. 8ms 상시 루프가 아니라 상태 변화 시의 짧은 스프링 감쇠로.
제작자의 대응은 이 점에서 건강한 패턴을 보여 준다. 스레드에서 스크롤 재킹(scroll-jacking) 에 대한 비판 — 사용자 wpm 은 “스크롤 재킹은 트랙패드에 대해, 스크루드라이버 손잡이를 번지 코드로 비틀어 돌리는 것이 스크루드라이버를 쓰는 것에 대한 관계와 같다. 직접적이고 즉각적인 피드백을 끊어 버린다” 고 썼다 — 이 나오자, 제작자는 “지적 인정한다. 스크롤 재킹은 제거했다(scroll-jacking has been removed)” 고 답했다. 출시하고, 적대적 리뷰를 받고, 이득보다 비용이 큰 부분에서 후퇴하는 것. 이것이 진자의 상승 국면에서 개별 프로젝트가 취할 수 있는 최선의 자세다.
한 가지 더 짚을 것은 신기함의 감쇠다. 사용자 ch_sm 은 이 프로젝트를 “React 를 위한 Compiz” 라고 불렀다. 2000 년대 중반 리눅스 데스크톱을 출렁이는 창(wobbly windows) 으로 매혹했던 그 Compiz 다. 그 비유는 정확하고 또 예언적이다. Compiz 의 출렁이는 창은 처음엔 모두를 즐겁게 했지만, 결국 거의 모두가 그것을 껐다. 사용자 xutopia 가 모션 과잉 UI 에 대해, 게임에서조차 신기함이 사라진 뒤에는 거슬린다고 말한 것과 같은 궤적이다. 즐거움이 어포던스와 분리 가능한 순수 장식일 때, 그것의 수명은 신기함의 수명과 같다. 매일 쓰는 도구에서 신기함은 며칠을 넘기지 못한다.
결론 — 우아하게 사라질 수 있는가
리드 질문으로 돌아가자. 폼 컨트롤에 물리 엔진을 붙이는 것은 즐거움을 되찾는 일인가, 기믹인가. 답은 이분법이 거짓이라는 것이다. 그러나 그 아래의 트레이드오프는 실재하며, 무엇보다 비대칭적이다. 즐거움은 실재하고 정당하다. 순수하게 만드는 기쁨을 위해 만든다는 제작자의 변은 진지하게 옹호될 수 있고, 모든 인터페이스가 전환율로 환원될 필요는 없다. 그러나 그 즐거움의 비용은 가장 취약한 사용자와 가장 약한 기기 위로 떨어진다. 전정계 장애를 가진 사용자, 저사양 기기의 사용자, 슬라이더로 정밀한 값을 맞춰야 하는 사용자가 그 계산서를 받는다. 이 비대칭이 301 점을 둘로 가른 진짜 이유다.
따라서 옳은 프레이밍은 “물리 대 접근성” 이 아니라 “향상으로서의 물리, 기준선으로서의 올바름” 이다. Jelly UI 의 가치는 라이브러리 그 자체보다, 그것이 들어 올린 거울에 있다. 301 점의 분열은 산업이 십 년마다 흔드는 같은 진자 — 스큐어모피즘에서 플랫으로, 플랫에서 뉴모피즘으로, 그리고 다시 물리성으로 — 를 재심(再審)하는 자리다. 뉴모피즘이 색상 대비에서 배운 교훈을 Jelly UI 는 색상에서 학습했지만, 같은 교훈을 모션에서 다시 시험받고 있다. 진짜 질문은 재미를 넣을 것인가 말 것인가가 아니다. 그 재미가 없어졌을 때 아무 문제 없이 우아하게 사라질 수 있는가 — 그것이 즐거움과 접근성을 화해시키는 유일한 조건이다.
출처: