9P by xguru 8일전 | favorite | 댓글과 토론
  • 사람들은 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은 단일 페이지 앱의 빈 틀
  • <body> 태그가 htmx를 이용해 앱의 본체를 설정함
    • hx-boost="true": htmx가 전체 페이지 네비게이션 없이 링크 클릭과 폼 제출 응답을 Ajax로 교체하도록 지시
    • hx-push-url="false": htmx가 링크 클릭과 폼 제출에 따라 URL을 변경하지 않도록 함
    • hx-get="./ui": 페이지 로드 시 /ui에서 페이지를 가져와 교체하도록 지시
    • hx-target="body": 결과를 <body> 요소에 교체하도록 지시
    • hx-trigger="load": 페이지 로드 시 이 모든 작업을 수행하도록 지시

/ui 엔드포인트

  • 앱의 실제 마크업을 반환함
  • 이후 htmx가 링크와 폼을 제어하여 인터랙티브하게 만듦
  • 서비스 워커가 Express 스타일 라이브러리로 요청 라우팅 처리
    • setFilterlistTodos는 IDB Keyval을 래핑한 간단한 함수
    • App 컴포넌트는 필터 폼, 할 일 목록, 추가 폼으로 구성됨

/todos/add 엔드포인트

  • 할 일 저장 후 UI를 다시 렌더링한 응답을 반환
  • htmx가 응답을 DOM에 교체함

Todo 컴포넌트

  • 체크박스, 삭제 버튼, 할 일 텍스트로 구성
  • 체크박스는 /todos/${id}/update 요청 트리거
  • 삭제 버튼은 /todos/${id} 삭제 요청 트리거
  • 할 일 텍스트는 "normal"과 "editing" 두 가지 상태
    • htmx가 더블 클릭 이벤트 수신
    • /ui/todos/${id}?editable=true 요청
    • 서비스 워커가 <input>이 포함된 Todo HTML 반환
    • htmx가 응답의 HTML로 현재 할 일 항목 교체

요약

  • 기술적으로는 동작함
  • 좋은 아이디어일까? 과연 하이퍼미디어 기반 앱의 절정일까? React를 버리고 이렇게 만들어야 할까?
  • 완전히 로컬인 앱에서는 htmx의 간접성이 해방감보다는 부담으로 느껴짐
  • 대부분의 앱은 완전히 로컬이 아님
  • "인터랙티브한 섬들(islands of interactivity)" 패턴이 "서버 측" 코드를 서비스 워커와 실제 서버로 나누는 것보다 낫다고 봄
  • 하이퍼미디어로 완전히 로컬인 단일 페이지 앱을 구축하는 모습을 보여주려는 실험적 시도였음