# htmx로 SPA 구축하기

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

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=17174](https://news.hada.io/topic?id=17174)
- GeekNews Markdown: [https://news.hada.io/topic/17174.md](https://news.hada.io/topic/17174.md)
- Type: news
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2024-10-10T11:09:01+09:00
- Updated: 2024-10-10T11:09:01+09:00
- Original source: [jakelazaroff.com](https://jakelazaroff.com/words/building-a-single-page-app-with-htmx/)
- Points: 10
- Comments: 0

## Summary

htmx를 사용하여 SPA를 구축하면 서비스 워커를 통해 오프라인에서도 동작 가능하며, 페이지 로드 간에 상태를 유지할 수 있는 장점이 있습니다. 이 아키텍처는 네트워크 요청을 가로채고 비즈니스 로직을 실행하여 새 HTML을 생성하는 방식으로, 기존 SPA와는 다른 접근 방식을 제공합니다. 그러나 개발자 도구 지원이 부족하고, Firefox에서 ES 모듈 지원이 부재하는 등의 단점도 존재하므로 이러한 점을 고려하여 활용할 필요가 있습니다.

## Topic Body

- 사람들은 htmx가 SPA에서 웹을 구원하는 것처럼 말함  
- htmx 제작자 Carson Gross는 이러한 역학을 "헤겔의 변증법"으로 위트 있게 설명함:  
  - 정립(thesis): 전통적인 MPA  
  - 반정립(antithesis): SPA  
  - 종합(synthesis): 하이퍼미디어 기반의 인터랙티브한 섬들로 구성된 애플리케이션  
- 하지만 나는 이 걸 못보고, 예전에 "htmx로 SPA를 만들었음"  
- 단순한 ToDo 리스트앱의 PoC임   
  - 페이지가 로드되면 서버와 더 이상 통신하지 않음  
  - 모든 것이 클라이언트에서 로컬로 처리됨  
  - htmx가 네트워크를 통한 하이퍼미디어 교환 관리에 초점을 맞추고 있다면 이건 어떻게 작동하는 걸까?  
  - 한 가지 단순한 트릭: **"Server-Side" 코드가 Service Worker에서 실행됨**  
  
### 서비스 워커  
  
- 웹페이지와 인터넷 사이에서 프록시로 동작함  
- 네트워크 요청을 가로채고 조작할 수 있음  
- 요청을 변경, 오프라인용 응답 캐싱, 브라우저 밖으로 요청을 보내지 않고 새 응답 생성 가능  
- 마지막 기능이 이 단일 페이지 앱의 핵심   
- htmx로 네트워크 요청하면 서비스 워커가 가로챔  
- 그 다음 서비스 워커는 비즈니스 로직을 실행하고 새 HTML을 생성  
- htmx가 새 HTML을 DOM에 교체함  
  
### 기존 SPA 대비 장점  
  
- 서비스 워커는 IndexedDB를 스토리지로 사용해야 함   
- 이는 페이지 로드 간에 상태를 유지함  
- 페이지를 닫았다가 다시 와도 앱이 데이터를 기억함  
- 이는 이 아키텍처를 선택하면 "무료"로 제공되는 부수적인 이점  
- 오프라인에서도 동작하도록 만들기 쉬움  
  
### 단점  
  
- 개발자 도구 지원이 열악함  
  - `console.log`를 간헐적으로 누락  
  - 서비스 워커 설치 여부 보고가 신뢰할 수 없음  
- Firefox에서 ES 모듈 지원 부재  
  - 모든 코드를 단일 파일에 넣어야 함  
- 일반적인 개발 경험이 "재미없음"  
  
### 그럼에도 불구하고 htmx SPA는 잘 동작함  
  
---  
  
#### 구현 세부 사항  
  
- 기본 HTML은 단일 페이지 앱의 빈 틀  
- `&lt;body&gt;` 태그가 htmx를 이용해 앱의 본체를 설정함  
  - `hx-boost="true"`: htmx가 전체 페이지 네비게이션 없이 링크 클릭과 폼 제출 응답을 Ajax로 교체하도록 지시  
  - `hx-push-url="false"`: htmx가 링크 클릭과 폼 제출에 따라 URL을 변경하지 않도록 함  
  - `hx-get="./ui"`: 페이지 로드 시 `/ui`에서 페이지를 가져와 교체하도록 지시  
  - `hx-target="body"`: 결과를 `&lt;body&gt;` 요소에 교체하도록 지시  
  - `hx-trigger="load"`: 페이지 로드 시 이 모든 작업을 수행하도록 지시  
  
##### `/ui` 엔드포인트  
  
- 앱의 실제 마크업을 반환함  
- 이후 htmx가 링크와 폼을 제어하여 인터랙티브하게 만듦  
- 서비스 워커가 Express 스타일 라이브러리로 요청 라우팅 처리  
  - `setFilter`와 `listTodos`는 IDB Keyval을 래핑한 간단한 함수  
  - `App` 컴포넌트는 필터 폼, 할 일 목록, 추가 폼으로 구성됨  
  
##### `/todos/add` 엔드포인트  
  
- 할 일 저장 후 UI를 다시 렌더링한 응답을 반환  
- htmx가 응답을 DOM에 교체함   
  
##### `Todo` 컴포넌트  
  
- 체크박스, 삭제 버튼, 할 일 텍스트로 구성  
- 체크박스는 `/todos/${id}/update` 요청 트리거  
- 삭제 버튼은 `/todos/${id}` 삭제 요청 트리거  
- 할 일 텍스트는 "normal"과 "editing" 두 가지 상태  
  - htmx가 더블 클릭 이벤트 수신  
  - `/ui/todos/${id}?editable=true` 요청  
  - 서비스 워커가 `&lt;input&gt;`이 포함된 `Todo` HTML 반환  
  - htmx가 응답의 HTML로 현재 할 일 항목 교체  
  
#### 요약   
  
- 기술적으로는 동작함  
- 좋은 아이디어일까? 과연 하이퍼미디어 기반 앱의 절정일까? React를 버리고 이렇게 만들어야 할까?  
- 완전히 로컬인 앱에서는 htmx의 간접성이 해방감보다는 부담으로 느껴짐  
- 대부분의 앱은 완전히 로컬이 아님   
- "인터랙티브한 섬들(islands of interactivity)" 패턴이 "서버 측" 코드를 서비스 워커와 실제 서버로 나누는 것보다 낫다고 봄  
- 하이퍼미디어로 완전히 로컬인 단일 페이지 앱을 구축하는 모습을 보여주려는 실험적 시도였음

## Comments



_No public comments on this page._
