µJS vs Turbo: 같은 아이디어, 다른 철학
Source: Dev.to

Turbo (Hotwire의 일부)와 µJS는 같은 문제를 해결합니다: 프론트엔드를 JavaScript로 다시 작성하지 않고도 서버‑렌더링된 웹사이트를 더 빠르게 느끼게 만드는 것이죠. 두 라이브러리 모두 링크 클릭과 폼 제출을 가로채고, AJAX를 통해 페이지를 가져와 DOM에 삽입합니다.
차이점은 범위, 무게, 그리고 서버 요구사항에 있습니다.
크기
| Library | Size (min + gzip) |
|---|---|
| µJS | ~5 KB |
| Turbo | ~25 KB |
Turbo는 5 배 더 무겁습니다. “페이지를 가져와서 HTML을 교체하는” 것이 주된 역할인 라이브러리라면, 이는 상당히 큰 차이입니다.
빌드 단계
Turbo는 빌드 단계가 필요합니다 – 번들링을 위해 npm 패키지로 배포됩니다.
µJS는 필요하지 않습니다:
mu.init();이는 JavaScript 빌드 파이프라인을 의도적으로 피하는 프로젝트(정적 사이트, PHP/Python/Ruby 앱, 혹은 npm + 번들러를 추가하는 것이 오히려 뒤로 가는 단계가 되는 모든 프로젝트)에게 중요한 사항입니다.
서버‑측 요구 사항
µJS는 서버에 아무것도 요구하지 않습니다. 표준 HTTP 요청을 보내고 표준 HTML을 반환받기를 기대합니다. 기존 페이지는 그대로 작동합니다.
Turbo에는 다음과 같은 규칙이 있습니다:
- Turbo Drive(기본 탐색)는 µJS와 동일하게 작동합니다.
- Turbo Frames는 서버가 특정
<turbo-frame>요소를 반환해야 합니다. - Turbo Streams(µJS의 패치 모드와 동등함)는 서버가
<template>태그 안에 콘텐츠를 감싼<turbo-stream>커스텀 요소를 반환해야 합니다.
Turbo Streams를 도입하면 서버‑측 HTML 출력이 변경됩니다. Rails와 Hotwire 생태계에서는 헬퍼가 이를 처리해 주지만, 다른 백엔드에서는 직접 구현해야 합니다.
다중‑프래그먼트 업데이트: 패치 모드 vs Turbo Streams
두 라이브러리 모두 단일 응답으로 페이지의 여러 부분을 업데이트할 수 있습니다. 구문이 차이를 보여줍니다.
µJS – 패치 모드
서버는 일반 HTML을 반환합니다. 각 프래그먼트는 mu-patch-target 및 mu-patch-mode 속성을 가집니다:
<div mu-patch-target="article" mu-patch-mode="replace">
<h2>Great article!</h2>
</div>
<div mu-patch-target="comments">
<p>14 comments</p>
</div>
<form mu-patch-target="comment-form">
<button type="submit">Submit</button>
</form>Turbo Streams
각 프래그먼트는 <turbo-stream> / <template> 로 감싸야 합니다:
<turbo-stream action="replace" target="article">
<template>
<h2>Great article!</h2>
</template>
</turbo-stream>
<turbo-stream action="append" target="comments">
<template>
<p>14 comments</p>
</template>
</turbo-stream>
<turbo-stream action="replace" target="comment-form">
<template>
<form>
<button type="submit">Submit</button>
</form>
</template>
</turbo-stream>µJS에서는 프래그먼트 자체가 내용입니다. Turbo에서는 각 프래그먼트가 래퍼 구조를 필요로 합니다. µJS 방식은 보일러플레이트가 적고 HTML을 그대로 읽을 수 있습니다.
또 다른 실용적인 장점: µJS의 mu-patch-target 속성은 초기 페이지 로드 시 무시되므로, 일반 페이지 템플릿과 패치 응답에서 동일한 HTML 프래그먼트를 그대로 사용할 수 있습니다.
HTTP 메서드
| Feature | Turbo | µJS |
|---|---|---|
| 지원되는 메서드 | GET, POST | GET, POST, PUT, PATCH, DELETE |
| 추가 동사 사용 방법 | 숨겨진 _method 필드 또는 서버 측 관례 | 링크, 버튼 및 폼에 대한 mu-method 속성 |
<a href="/posts/5" mu-method="delete">Delete</a>
<form action="/api/publish/5" mu-method="patch">
<button type="submit">Publish</button>
</form>Turbo는 PUT/PATCH/DELETE에 대한 기본 지원이 없어 우회 방법을 사용해야 하지만, µJS는 이를 바로 사용할 수 있습니다.
트리거와 폴링
Turbo는 링크와 폼만 처리합니다.
µJS는 mu-trigger를 추가하여 모든 요소가 모든 이벤트에서 fetch를 시작할 수 있게 합니다:
<button mu-trigger="click" mu-url="/refresh" mu-poll="5000">
5초마다 새로 고침
</button>실시간: 서버 전송 이벤트 (SSE)
두 라이브러리 모두 SSE를 지원합니다.
- µJS는 기본 제공되며 동일한 패치 구문을 재사용합니다:
<div mu-patch-target="notifications" mu-patch-mode="append">
<!-- Server will push <div mu-patch-target="notifications">…</div> fragments -->
</div>서버는 mu-patch-target 속성을 가진 표준 HTML 조각을 푸시합니다—일반 패치 응답과 동일한 형식입니다. 새로 배울 것이 없습니다.
- Turbo Streams도 SSE를 통해 전달될 수 있지만, 여전히
<turbo-stream>/<template>형식으로 작업해야 하며, 서버는 해당 구조를 생성해야 합니다.
TL;DR
| 항목 | µJS | Turbo (Hotwire) |
|---|---|---|
| 크기 | ~5 KB | ~25 KB |
| 빌드 단계 | 번들러가 필요 없음 | npm 및 번들러 필요 |
| 서버 요구사항 | 없음 (일반 HTML 사용 가능) | <turbo-frame> / <turbo-stream> 필요 (고급 기능 사용 시) |
| 패치 구문 | mu-patch-* 속성을 가진 일반 HTML | <turbo-stream> 요소로 감쌈 |
| HTTP 메서드 | GET, POST, PUT, PATCH, DELETE | GET, POST (다른 메서드는 우회 필요) |
| 트리거 | mu-trigger를 모든 이벤트, 폴링, 디바운스에 사용 | 링크와 폼만 |
| SSE 지원 | 내장, 동일한 패치 형식 | 지원하지만 Turbo 전용 마크업 사용 |
만약 모든 백엔드와 동작하는 작고, 설정이 필요 없는 즉시 사용 가능한 솔루션을 원한다면, µJS가 확실히 승자입니다. 이미 Rails/Hotwire 생태계에 깊이 들어가 있고, 제공하는 풍부한 기능 세트가 필요하다면 Turbo가 더 적합할 수 있습니다.
Turbo가 더 적합할 때
Turbo는 다음 경우에 적합합니다:
- Rails / Hotwire 생태계에 있다면 — 통합이 깊고, 헬퍼가 성숙했으며, 커뮤니티가 크다.
- iOS/Android 앱을 위한 Turbo Native가 필요하다면.
- 팀이 이미 Turbo 관례에 익숙하다면.
Rails 생태계 밖에서는 Turbo의 관례가 생태계 혜택 없이 오히려 부담이 된다.
Summary
| 기능 | µJS | Turbo |
|---|---|---|
| 크기 | ~5 KB | ~25 KB |
| 빌드 단계 | 없음 | 필요 |
| 서버 변경 필요 여부 | 아니오 | 프레임 및 스트림을 위해 필요 |
| 다중 프래그먼트 업데이트 | 패치 모드 (일반 HTML) | Turbo Streams (<turbo-stream>) |
| HTTP 메서드 | GET/POST/PUT/PATCH/DELETE | GET/POST |
| 모든 이벤트에서 트리거 | 예 | 아니오 |
| 디바운스 / 폴링 | 내장 | 없음 |
| SSE | 내장 | 내장 |
| Rails 생태계 | 아니오 | 예 |
µJS는 집중된 라이브러리입니다: 프로젝트에 넣고 mu.init()을 호출하면 서버 변경 없이 사이트에 AJAX 탐색 기능이 추가됩니다. 더 많은 기능이 필요하면 속성을 사용할 수 있고, 필요 없으면 비용을 지불하지 않아도 됩니다.
- Live playground — 각 기능을 인터랙티브하게 테스트
- Full comparison: µJS vs Turbo vs htmx
- GitHub
npm install @digicreon/mujs