# HTMX가 너무 멋져서 직접 만들었다 (2024)

> Clean Markdown view of GeekNews topic #30300. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30300](https://news.hada.io/topic?id=30300)
- GeekNews Markdown: [https://news.hada.io/topic/30300.md](https://news.hada.io/topic/30300.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-06-09T09:20:33+09:00
- Updated: 2026-06-09T09:20:33+09:00
- Original source: [dbushell.com](https://dbushell.com/2024/04/16/htmx-and-modern-javascript/)
- Points: 1
- Comments: 1

## Topic Body

- **HTMX**는 서버 렌더링 HTML을 중심으로 프런트엔드를 점진적으로 향상하며, React식 현대 JavaScript UI가 비대해지기 전의 방식에서 발전한 접근
- 자체 호스팅 podcast web app의 서버 리팩터링에서 **SvelteKit**을 DinoSsr로 교체하자 페이지 이동이 오디오 재생을 끊는 문제가 생겼고, HTMX로 `&lt;main&gt;` 영역만 갱신해 오디오 컴포넌트를 유지할 수 있었음
- HTMX는 프런트엔드 라이브러리로 배포되지만 구현의 상당 부분이 백엔드 템플릿과 서버 설정에 놓이며, HTML을 반환하는 HTTP 요청이 사실상 **HTMX API** 역할
- `hx-*` 속성, 클릭 가능한 `&lt;div&gt;` 예시, 인라인 JavaScript가 많은 고급 예시는 **선언적 속성 템플릿**의 한계와 문서상의 불만점
- 직접 만든 미니 구현은 `304` 캐싱, History API, `&lt;title&gt;` 교체, 포인터 이벤트 기반 프리로드를 주요 요소로 사용했고, 브라우저 JavaScript를 줄여 코드베이스를 더 작고 단순하게 만든 결과

---

### HTMX의 위치
- [HTMX](https://htmx.org/)는 현대 JavaScript UI를 거부하고 서버 렌더링 HTML을 선호하며, React로 프런트엔드가 비대해지기 전의 방식에서 발전한 접근
- 무한 스크롤과 실시간 검색 결과는 인기 있는 HTMX 예시이며, HTMX는 React 등이 풀려는 모든 문제를 해결하지 않고 제한적으로 보이지만 그 제한 안에서는 가치가 큰 도구
- HTMX는 “magic bullet”이 아니며, HTMX 뒤의 일부 아이디어가 HTMX 자체보다 더 중요하다는 관점이 핵심

### 실험
- 문서 읽기만으로는 충분하지 않아 실제 사용을 테스트했고, 자체 호스팅 [podcast web app](https://git.dbushell.com/dbushell/sauropod) 서버 리팩터링이 HTMX 적용 대상
- 이전 구현은 [SvelteKit](https://kit.svelte.dev/) 사용이었고, SvelteKit은 선호하는 도구지만 작은 웹사이트에는 부담스러울 수 있는 프레임워크
- 교체 대상은 직접 만들던 [DinoSsr](https://github.com/dbushell/dinossr/)였으며, 같은 프로젝트는 정적 사이트 빌드와 북마크 블로그 제공에도 사용
- DinoSsr는 주로 서버 사이드 기반이며 프런트엔드 “islands”로 컴포넌트를 제공할 수 있지만, 전체 페이지 상호작용은 제공하지 않는 구조
- 오디오 플레이어 컴포넌트는 페이지 이동 중에도 유지되어야 하며, 페이지 이동이 전체 페이지를 다시 로드하면 재생 경험이 빠르게 종료되는 문제
- SvelteKit은 UI 업데이트와 프런트엔드 라우팅을 처리했지만, 새 빌드에서는 오디오 플레이어 컴포넌트만 프런트엔드 JavaScript를 사용하고 DinoSsr는 클라이언트 사이드 라우팅을 의도적으로 시도하지 않는 구조
- 페이지 몇 개는 `&lt;main&gt;` 섹션만 다르므로, HTMX로 링크를 점진적으로 향상하고 이 영역만 갱신하면 페이지 전체를 다시 로드하지 않고 오디오 컴포넌트를 유지 가능
- HTMX 적용은 잘 작동했지만, 곧 HTMX를 제거하고 같은 아이디어로 직접 만든 미니 버전으로 전환

### HTMX에 대한 몇 가지 생각
- 이 실험에서 HTMX는 프런트엔드 Svelte의 대체재였지만, React처럼 바로 끼워 넣는 대체재가 아니라 사고방식의 큰 전환
- HTMX는 프런트엔드를 점진적으로 향상하는 JavaScript 라이브러리로 배포되지만, 구현의 대부분은 백엔드에서 이뤄지며 서버 템플릿과 설정은 직접 준비해야 하는 구조
- HTML을 제공하는 HTTP 요청은 사실상 HTMX API 역할이며, 올바른 캐싱을 위해 HTTP 헤더를 설정하는 세부 사항이 중요함
- 표준 `data-*` 속성과 [`dataset`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset)이 있는데 비표준 `hx-*` 접두 속성을 쓰는 점은 작은 불만
- HTMX 문서에는 `&lt;div&gt;` 예시가 많으며, 아래 예시는 사용자가 `div`를 클릭하면 `/messages`로 `PUT` 요청을 보내고 응답을 해당 `div`에 로드하는 구조

```html
&lt;div hx-put="/messages"&gt;
    Put To Messages
&lt;/div&gt;
```

- 사용자가 `&lt;div&gt;` 요소를 클릭해야 하는 예시는 바람직하지 않다는 비판
- 인라인 JavaScript를 사용하는 일부 고급 HTMX 예시는 다소 지저분해지며, 선언적 속성 템플릿의 한계를 보여주는 사례
- 비판과 별개로 HTMX는 제한적이지만 유용한 기능 집합을 제공하며, 많은 일반적인 웹 디자인 패턴을 향상할 수 있는 도구

### 직접 만들기
- HTMX를 성공적으로 추가한 직후 제거했고, 같은 아이디어를 사용해 직접 만든 미니 버전 구현
- 캐싱되는 fetch 요청을 허용하기 위해 `last-modified`, `if-modified-since` HTTP 헤더와 `304` 응답을 사용
- 기본 히스토리 통합에는 [`pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)와 [`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event)를 사용
- `&lt;title&gt;` 요소를 추출하고 교체하는 코드를 추가했으며, [HTMX preload extension](https://htmx.org/extensions/preload/)에서 영감을 받아 포인터 이벤트 기반 프리로드를 내장
- 포인터 이벤트 기반 프리로드는 `click` 이벤트가 발생하기 전에 fetch 요청을 시작해 작은 성능 향상을 제공
- 실험용 [소스 코드](https://git.dbushell.com/dbushell/sauropod/src/branch/main/static/scripts/sauropod-state.js)는 매우 기본적이지만, 브라우저에 실제로 필요한 JavaScript가 적다는 점을 보여주는 구현
- HTMX 또는 “we have HTMX at home” 방식으로 코드베이스가 훨씬 작고 단순해진 결과

### 프런트엔드 JavaScript
- 템플릿과 컴포넌트는 아주 작은 웹사이트가 아니라면 코드 구성과 재사용에 사실상 필요하며, PHP, Ruby, Go, JavaScript 등으로 서버 사이드에서도 구현 가능
- 이런 구조를 브라우저에 복제하거나 브라우저에서만 구현할 필요는 없으며, React 등의 인기로 많은 개발자가 이 질문을 멈춘 상태
- 프런트엔드 JavaScript 피로는 실제이며, 오래된 서버 템플릿을 선호하면서도 JS UI를 과도하게 설계해 온 경험과 맞물리는 문제
- HTMX 자체가 아주 훌륭하지 않다고 보더라도, 그 철학은 현대 JavaScript 개발자를 부끄럽게 만들 만큼 강한 가치가 있는 접근

## Comments



### Comment 59232

- Author: neo
- Created: 2026-06-09T09:20:34+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/8hiogg/htmx_is_so_cool_i_rolled_my_own_2024) 
- 사소한 트집이지만, `data-*`를 써야 할 곳에 `hx-*` 접두 HTML 속성을 쓰는 건 별로 마음에 들지 않음  
  Htmx는 오래전부터 **`data-` 접두사**를 지원함  
  사용자가 `&lt;div&gt;` 요소를 클릭하게 만들면 안 된다는 점에는, htmx의 `hx-boost`를 앵커와 폼 태그에 쓰는 게 가장 좋음. 이 태그들을 올바른 방식으로 자동 강화해 주기 때문에 클릭 가능한 div를 피할 수 있음  
  브라우저에 실제로 필요한 JavaScript가 얼마나 적은지 보여주는 프로젝트이고, 앞으로 유지보수는 최소화되며 보안 패치도 거의 필요 없을 듯함. 축하할 만함

- HTMX는 모든 걸 렌더링하니까 서버를 혹사시키지 않나? 예전에 겪던 **CGI 문제**와 비슷한 느낌임
  - 거의 확실히 그렇지 않음. CGI 문제는 주로 짧게 살아 있는 프로세스를 많이 띄우는 비용이었고, FastCGI 같은 것으로 해결됐음  
    HTML 생성은 딱히 비싼 작업이 아니며, 대안 방식에서 비슷한 양의 JSON을 만드는 것보다 더 비싸다고 보기도 어려움
  - “우리”라니 무슨 말인지 모르겠음. 내 [블로그](https://boston.conman.org/)는 CGI 기반이고 서버가 HTML을 렌더링하며 JavaScript는 전혀 없음  
    1999년부터 아무 문제 없었고, 늘 그렇듯 실제 병목이 어디 있는지는 **프로파일링**으로 확인해야 함
  - 보통 **서버 사이드 렌더링**이라고 부르지만, 실제로는 서버에서 원시 HTML을 만드는 것에 가까움. 실제 렌더링과 DOM 생성은 여전히 브라우저가 하고 있고, 항상 그랬음  
    PHP까지 CGI 범주에 넣더라도, 이런 방식이 보통이었던 웹 개발의 10년 반 정도를 건너뛰고 있는 셈임  
    서버에 더 많은 일을 시킨다는 점은 맞지만, 그동안 많은 처리를 클라이언트로 넘긴 주된 이유는 비용 절감이라는 계산된 위험에 가까웠다고 봄. 많은 최종 사용자는 브라우저가 더 많은 일을 한다는 걸 알아채지 못하지만, 오래되었거나 성능이 낮은 기기에서는 지금도, 특히 초기에는 경험이 나빠졌음  
    다만 HTMX는 완전한 서버 사이드 렌더링과는 다름. API가 JSON으로 데이터를 보내고 클라이언트가 HTML로 렌더링하는 대신, 서버가 같은 데이터를 **HTML 조각**으로 보내는 방식임. 그래도 서버가 두들겨 맞는다면 REST API보다 본질적으로 자원을 더 먹어서라기보다는 다른 요인 때문일 가능성이 큼
  - 벤치마크 없이 단정하긴 어렵지만, 비슷할 것 같음. 두 경우 모두 결국 문자 더미를 내보내는 일이고, 차이는 텍스트 렌더링이 더 비싼지 JSON 생성이 더 비싼지임  
    경험상 JSON을 쓸 때 더 많은 것을 직렬화하는 경향이 있지만, 제대로 비교할 방법은 잘 모르겠음
  - 서버 사이드 애플리케이션에서 실제 **HTML 렌더링 단계**가 병목인 경우는 거의 없고, 병목은 대체로 그 이전 과정에 있음

- 비슷한 이유로 htmx와 매우 유사한 **alpine-ajax**를 쓰고 있음
  - `alpine-ajax`도 정말 마음에 듦. “SSR에서 SPA의 장점을 얻기”를 새로 시작한다면 아마 거기로 갔을 것 같음  
    어차피 클라이언트 반응형 기능에는 alpine을 쓰고 있기 때문임. 다만 지금은 저장소에 htmx가 이미 많이 들어가 있고, htmx에도 불만은 없음
  - [datastar](https://data-star.dev/)를 쓰고 있는데, 작업하기 꽤 쾌적했음
