HTMX는 WordPress에 큰 도움이 될 수 있습니다.
게시 됨: 2024-05-10브라우저에서 풍부한 사용자 경험을 구축하는 것은 어려운 작업이 될 수 있으며, 종종 상당한 양의 JavaScript 코드가 필요합니다. 애플리케이션의 요구 사항과 야망이 커짐에 따라 JavaScript 코드도 복잡해집니다. 따라서 개발자가 JavaScript 앱에 대해 생각하고 작성하는 방법을 얼마나 자주 수정했는지는 놀라운 일이 아닙니다.
마지막 JS 프레임워크 이후의 일수입니다.
WordPress 플러그인 개발자는 상황이 더 나쁩니다. 우리가 목표로 하는 환경은 우리가 통제하는 서버도 아니고, 전체 페이지를 완벽하게 통제하는 서버도 아닙니다. WordPress 플러그인에서 JavaScript 프레임워크를 성공적으로 사용하는 것이 매우 가능하지만, 의도했거나 예상했던 것보다 규모와 복잡성이 큰 프로젝트로 끝나는 것도 매우 쉽습니다.
하지만 이렇게 될 필요가 없다면 어떨까요? 이 기사에서는 JavaScript를 사용하여 최신 웹 UI를 구축하는 방법, 개발자가 직면하는 어려움, HTMX가 제공하는 대안을 살펴보겠습니다. 특히 HTMX와 WordPress가 왜 천생연분인지 살펴보겠습니다.
우리가 여기까지 어떻게 왔는지
JavaScript 이전에는 브라우저는 기본적으로 미화된 문서 판독기였습니다. 이처럼 웹에서의 대부분의 경험은 '다중 페이지 애플리케이션', 줄여서 MPA였습니다. MPA는 애플리케이션의 각 페이지마다 하나씩 여러 HTML 문서로 구성된 웹 애플리케이션입니다. 사용자가 애플리케이션을 사용하면 사용 가능한 작업이 다른 다양한 문서가 표시됩니다.
MPA는 구축이 매우 간단합니다. 탐색은 <a>
태그를 사용하여 다른 문서에 연결하고 사용자 입력은 <form>
요소로 캡처할 수 있습니다. 서버는 새로운 HTML 문서로 링크 및 양식 요청에 응답하여 화면에 표시되는 페이지를 대체합니다.
여러분에게 매우 친숙한 MPA의 좋은 예는 WP Admin입니다. 각 관리 페이지는 서버에서 실행되는 WordPress PHP 코드에 의해 생성된 HTML이 포함된 문서입니다. WordPress 설정 페이지와 같이 WP Admin의 대부분의 페이지는 대부분 사용자가 제출할 수 있는 양식으로 구성되는 경향이 있습니다.
반대로 단일 페이지 애플리케이션(SPA)은 단일 HTML 페이지를 사용하는 애플리케이션입니다. 그러면 탐색 및 사용자 입력이 JavaScript 코드로 처리되어 전체 페이지를 바꾸거나 새로 고칠 필요 없이 페이지의 일부를 동적으로 변경합니다. 그 결과 더욱 부드럽고 반응성이 뛰어난 사용자 경험이 가능해졌습니다.
요즘 많은 웹 애플리케이션은 웹 인터페이스에 SPA를 사용합니다. RebelCode에서는 두 가지 주요 WordPress 플러그인인 Spotlight와 Aggregator의 관리 인터페이스용 SPA를 구축했습니다. WordPress의 비교적 새로운 사이트 편집기는 블록 기반 게시물 편집기와 마찬가지로 SPA이기도 합니다.
우리가 지불하는 가격
SPA는 JavaScript로 작성되고 브라우저에서 실행되는 자체 애플리케이션입니다. 그들 자신의 정의는 또한 가장 큰 주의 사항이기도 합니다. 즉, 서버 리소스에 즉시 액세스할 수 없다는 것입니다. 이는 SPA와 서버 간의 통신 채널을 설정해야 함을 의미합니다.
예제를 사용하여 간단한 WordPress 플러그인을 만들어 보겠습니다. 이 플러그인은 다음을 제공합니다.
책 관리를 위한 간단한 CRUD 사용자 인터페이스입니다. 서버에 있는 플러그인의 내부 API는 다음과 같습니다.
<?php function get_books(?int $count = null, int $page = 1): Book[]; function get_book(int $id): Book; function insert_book(Book $book): Book; function update_book(Book $book): Book; function delete_book(int $id): void;
최신 SPA 인터페이스를 만들기 위해 React와 같은 JavaScript 프레임워크를 사용합니다. WordPress에서도 사용되는 가장 인기 있는 JavaScript 프레임워크입니다. 관리자 페이지를 추가하는 것부터 시작해 보겠습니다.
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
우리 페이지는 UI의 나머지 부분이 렌더링되는 React 애플리케이션의 루트 역할을 할 단일 빈 <div>
요소를 렌더링합니다.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
그렇다면 데이터베이스에 저장된 책을 어떻게 나열합니까? 이를 수행하는 코드는 서버에 있으므로 이를 호출하고 결과를 얻을 수 있는 방법이 필요합니다.
이를 위해 서버에서 JSON API를 노출할 수 있습니다. 그런 다음 React 앱은 API의 URL에서 요청을 하고 JSON 형식으로 책을 받은 다음 목록을 렌더링할 수 있습니다. 이 예에서는 WordPress REST API에 엔드포인트를 추가했다고 가정합니다.
GET https://my-wp-site.com/wp-json/books { "books": [ { "id": 15, "title": "Mistborn", "author": "Brandon Sanderson", }, { "id": 44, "title": "The Hobbit", "author": "JRR Tolkien", }, ] }
그런 다음 책을 가져와 목록으로 렌더링하는 React 구성 요소를 작성할 수 있습니다.
function BookList() { const [books, setBooks] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect( function () { setIsLoading(true); fetch("https://my-wp-site.com/wp-json/books") .then((res) => res.json()) .then((data) => setBooks(data.books)) .else((error) => setError(error)) .finally(() => setIsLoading(false)); }, [setBooks, setIsLoading], ); if (isLoading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error}</div>; } return ( <ul> <li> {books.map((book) => ( <a key={book.id} href={book.url}> {book.title} </a> ))} </li> </ul> ); }
그러나 이 솔루션은 너무 순진하며 거친 사용자 경험을 제공합니다. 구성 요소가 마운트 해제된 후 상태 변경, 응답 캐싱, 실패한 쿼리 재시도 또는 오래된 상태가 최신 상태를 덮어쓰는 것을 방지하지 않습니다. 실제로 React 효과에서 fetch()
사용하는 방식은 일반적으로 권장되지 않습니다.
여러 면에서 이는 기존 MPA보다 더 나쁠 수 있습니다. 따라서 이를 올바르게 수행하려면 클라이언트에서 몇 가지를 더 구현해야 합니다. 또는 더 현실적으로는 타사 패키지를 사용하세요.
하지만 이 모든 것이 단지 책 목록을 만드는 데 너무 많은 노력이 드는 것처럼 느껴지기 시작했습니다. 원활한 사용자 경험을 만들기 위해 JavaScript 앱과 JSON API를 만들어야 합니까?
이를 MPA와 비교해 보겠습니다. MPA에서는 종속성 없이 단 몇 줄의 PHP 코드만으로 도서 목록 렌더링을 수행할 수 있습니다.
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
그러나 물론 이것은 공정한 비교가 아닙니다. 이 책 목록은 단지 정적 HTML입니다. 상태 변경이나 사용자 입력에 반응하지 않습니다.
코드가 데이터베이스에 즉시 액세스할 수 있는 서버에서 HTML을 렌더링하는 동시에 SPA와 같은 경험을 원한다면 서버에서 렌더링된 HTML이 브라우저에 도달하도록 하는 방법을 찾아야 합니다. 이전 도서 목록을 교체합니다. 그러나 JavaScript 코드 없이 이를 달성하는 것은 현재 불가능하므로 어쨌든 JavaScript를 사용해야 합니다.
하지만 우리가 직접 작성할 필요는 없습니다.
HTMX 소개
HTMX는 주로 한 가지 작업을 수행하는 작은 JavaScript 라이브러리입니다. HTML이 서버에서 새 HTML을 요청할 수 있도록 허용합니다. 이는 새로운 속성을 사용하여 HTMX에 새 HTML을 어디서 가져올지, 무엇으로 교체할지, 무엇이 교체를 트리거하는지 알려줄 수 있습니다. 이는 HTML 서버와 브라우저 페이지 사이의 다리 역할을 합니다.
현재 페이지를 업데이트하기 위해 클라이언트 JavaScript 애플리케이션을 구축하는 것이 아니기 때문에 이는 SPA에 대해 생각하는 방식과 매우 다릅니다. 대신, 특정 이벤트가 발생할 때 페이지가 어떻게 변경되기를 원하는지 HTMX에 알려주기 위해 몇 가지 HTML 속성을 추가하기만 하면 됩니다.
HTMX가 없어도 HTML만 사용하면 화면에 표시되는 내용을 변경할 수 있지만 매우 제한적입니다. 당신은 이미 이 HTML 기능인 <a>
링크 요소에 익숙합니다.
<a href="https://my-wp-site.com/books">View books</a>
링크 요소는 탐색을 수행하는 데 필요한 모든 정보를 브라우저에 제공합니다. 클릭하면 브라우저는 요소에서 href
가져와 해당 URL에서 요청하고 응답을 다운로드한 다음 HTML이 포함되어 있다고 가정하고 페이지의 콘텐츠를 새 HTML로 바꿉니다.
<form>
요소는 HTML이 새로운 HTML을 요청할 수 있는 방법의 또 다른 예입니다.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
이번에는 브라우저가 양식의 모든 입력에서 값을 수집하여 서버로 보내고 응답을 다운로드하여 화면에 렌더링합니다.
왜
HTMX의 GitHub readme에서<a>
와<form>
만 HTTP 요청을 할 수 있어야 합니까? 왜 전체 화면만 교체할 수 있어야 합니까?
글쎄, HTMX는 그것을 바꿉니다.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
HTMX hx-target
속성을 사용하여 링크를 클릭하면 이제 "books"
ID가 있는 요소 내부에 https://my-wp-site.com/books
의 응답이 배치됩니다. 물론, 다른 페이지 안에 페이지를 삽입하는 것이 여기서의 목표는 아닙니다. 우리 서버는 전체 페이지로 응답할 필요가 없으며 대신 HTML 조각으로 응답할 수 있습니다.
서버에서 HTML 조각을 노출하고 해당 조각을 언제 어디서 어떻게 얻을 수 있는지 HTMX에 알려줌으로써 서버가 모든 권한을 갖는 SPA와 같은 웹 애플리케이션을 JavaScript 없이 만들 수 있습니다. 어떤 의미에서 HTML은 새로운 JSON이 되었습니다.
그리고 우리가 해야 할 일은 HTMX 스크립트를 페이지에 로드하는 것뿐입니다.
<script src="https://unpkg.com/[email protected]"></script>
(위 코드가 오래되었을 수 있으므로 지침은 HTMX 문서를 확인하세요.)
또 다른 예를 살펴보겠습니다.
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
여기에는 더 많은 일이 진행되고 있으므로 이를 분석해 보겠습니다.
-
hx-get
버튼을 클릭할 때GET
요청을 보낼 URL을 지정합니다. -
hx-target="this"
HTMX에게 클릭한 버튼을 응답으로 바꾸도록 지시합니다. -
hx-swap="outerHTML"
HTMX에게 버튼 내부뿐 아니라 전체 버튼을 교체하도록 지시합니다.
모두 합쳐서 HTMX에 다음과 같은 내용을 알려줍니다.
버튼을 클릭하면
/button/off
에 GET 요청을 보내고 이 버튼을 응답으로 바꿉니다.
서버가 아래 HTML을 사용하여 /button/off
에 응답한다고 가정해 보겠습니다.
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
차이점이 보이나요? 이제 hx-get
속성은 /button/on
을 가리키고 버튼 내부의 텍스트는 이제 "켜기"입니다. 이 버튼을 클릭하면 /button/on
의 응답으로 대체됩니다. 상상할 수 있듯이 서버가 원래 버튼으로 응답하여 토글을 완료할 수 있습니다!
모든 요소가 서버에서 새 HTML을 요청하고 해당 HTML이 어디로 가는지 결정하도록 허용하는 이 간단한 아이디어는 매우 강력합니다. 탭을 만들고, 실시간 결과로 검색하고, 진행률 표시줄 등을 사용할 수 있습니다.
장점과 단점
대부분의 JavaScript 프레임워크와 달리 HTMX에서는 클라이언트 애플리케이션 코드를 컴파일하고 번들로 묶을 필요가 없습니다. 이것만으로도 큰 이점이 됩니다. JavaScript 빌드 시스템은 설정 및 유지 관리가 매우 어려울 수 있습니다. 특히 TypeScript, JSX, CSS 전처리기 등과 같은 좀 더 이국적인 기능과 라이브러리를 도입하기 시작하면 더욱 그렇습니다. 이 작업을 전담하는 한 명 이상의 구성원.
또 다른 확실한 이점은 별도의 클라이언트 애플리케이션이 없다는 것입니다. 우리에게 필요한 것은 HTML로 응답하는 HTTP 서버뿐이므로 원하는 프로그래밍 언어를 사용할 수 있습니다. 팀이 최신 JavaScript에 익숙하지 않거나 두 개의 애플리케이션을 구축할 만큼 규모가 크지 않은 경우 이는 큰 판매 포인트가 될 수 있습니다. 플러그인의 모든 측면에 PHP를 사용할 수 있기 때문에 WordPress 플러그인 개발자라면 특히 매력적일 수 있습니다.
그러나 아마도 가장 중요한 이점은 애플리케이션의 백엔드와 프런트엔드 사이에 더 이상 API가 필요하지 않다는 것입니다. 이를 통해 엄청난 양의 개발 시간을 절약할 수 있을 뿐만 아니라 버그를 생성할 수 있는 코드의 양을 줄여 장기적으로 시간도 절약할 수 있습니다.
그러나 HTMX를 사용한다고 해서 JavaScript 를 작성할 필요가 없다고 가정할 정도로 순진해서는 안 됩니다. 끌어서 놓기, 차트, 색상 및 날짜 선택기 등과 같은 작업에는 여전히 어느 정도의 JavaScript가 필요할 수 있습니다. SortableJS 및 Floating UI와 같은 프레임워크에 구애받지 않는 솔루션을 항상 사용할 수 있습니다. 또한 웹 표준이 최근 <dialog>
요소와 같은 새로운 HTML 요소로 계속 발전함에 따라 미래에는 JavaScript의 필요성이 줄어들 수도 있습니다.
둘째, PHP는 HTML 템플릿 작성을 위해 제작되었음에도 불구하고 아이러니하게도 HTML 템플릿 작성에 그다지 능숙하지 않습니다. 태그 구문은 지나치게 장황하며 HEREDOC 문자열 구문은 문자열 보간에 대한 지원이 제한되어 있습니다.
마지막으로 WordPress에서 엔드포인트를 생성하는 것은 그리 간단하지 않습니다. 이전 예제의 books 플러그인을 고려해보세요. HTML 형식의 도서 목록으로 응답하는 서버 경로가 필요합니다. 이 끝점을 어떻게 등록합니까?
-
init
또는admin_init
작업 중에 GET 매개변수를 감지합니까? - Admin Ajax API를 사용하시겠습니까?
- REST API 엔드포인트를 등록하시겠습니까?
- 사용자 정의 재작성 규칙을 추가하시겠습니까?
많은 옵션이 있지만 그 어느 것도 그렇게 간단하지 않습니다.
하테오아스
이전 예에는 놓치기 매우 쉬운 미묘한 세부 사항이 있으며 일단 지적하면 명백하게 들릴 것입니다.
서버에서 HTML을 가져올 때 페이지의 버튼은 ON 변형이거나 OFF 변형입니다. 화면에 어떤 것이 표시되는지에 따라 클릭 동작이 달라집니다.
이 때문에 브라우저는 우리의 애플리케이션을 이해할 필요가 없습니다. 우리는 일반적으로 모든 동작을 명시적으로 프로그래밍하기 위해 JavaScript 코드를 제공하여 브라우저가 이해할 수 있도록 합니다 . 이제 우리에게는 HTML만 있고 브라우저는 애플리케이션이 어떻게 작동하는지, 애플리케이션의 상태가 무엇인지에 대한 사전 지식이 필요하지 않습니다. 화면에 HTML을 렌더링하기만 하면 됩니다. HTML 자체가 애플리케이션 상태를 인코딩합니다.
이러한 유형의 아키텍처는 '애플리케이션 상태의 엔진으로서의 하이퍼미디어(Hypermedia As The Engine Of Application State)'를 의미하는 HATEOAS로 알려져 있습니다. 이는 상태 전송을 위한 매체로 하이퍼미디어를 사용하고, 동일한 하이퍼미디어가 사용자가 애플리케이션을 새로운 상태로 구동하는 인터페이스가 되는 특수한 유형의 REST 아키텍처입니다.
더 자세히 알아보고 싶다면 HTMX 웹사이트에 이 주제에 관한 훌륭한 기사, 에세이, 강연 모음이 있습니다. 이 기사의 목적을 위해 HTMX가 WordPress 개발자에게 큰 도움이 될 수 있는 이유를 살펴보겠습니다.
HTMX <3 워드프레스
WordPress는 거대하고 단일화된 PHP 서버입니다. WordPress 플러그인도 주로 PHP로 작성되었습니다. Hooks API 및 Database API와 같이 WordPress에서 제공하는 PHP API를 사용하여 사이트에 새로운 기능을 추가할 수 있습니다. 이러한 API는 JavaScript에서 사용할 수 없으므로 플러그인 개발자는 가능한 한 많은 플러그인 코드를 서버에 유지해야 합니다. HTMX를 사용하려는 동기가 있다면 이것이 바로 그것입니다!
여러 면에서 HTMX는 WordPress용으로 구축되었습니다. 또는 WordPress 와 같은 애플리케이션의 경우; 서버 API 컬렉션을 남겨두도록 강요하는 외국어 부담을 덜고 싶어하는 애플리케이션입니다. 특히 하이퍼미디어를 사용하여 단순히 상태를 전송하는 것만으로는 충분하지 않습니다.
WordPress 플러그인을 위한 좋은 UI를 더 쉽게 만들 수 있도록 하면 플러그인 생태계에 극적인 영향을 미칠 수 있습니다. 무료 플러그인을 유지 관리하는 개발자는 사용자를 위해 더 나은 사용자 경험을 구축하는 것이 더 타당하다고 생각할 수 있으며, 소규모 팀은 시간을 절약하면서 기능을 더 빠르게 반복할 수 있습니다. 이는 더 큰 예산을 가진 대규모 팀이 지배하는 시장에서 소규모 플러그인의 경쟁력을 높이는 데 도움이 될 수 있습니다.
더 큰 플러그인에도 특히 관심이 있을 수 있습니다. JavaScript 앱은 기하급수적으로 빠르게 성장할 수 있습니다. HTMX를 사용하면 이러한 플러그인이 대규모 JSON API 및 JavaScript 앱을 제거하고 WordPress API에 대한 전체 액세스 권한이 있는 간결한 HTML 서버를 그 자리에 남겨둘 수 있습니다.
마지막 생각들
나는 한동안 HTMX를 PHP와 Go와 함께 사용해 왔습니다. 이는 웹에서 사용자 인터페이스를 구축하기 위한 강력한 대안과 하이퍼미디어를 사용하여 애플리케이션 상태를 구동하는 데 대한 설득력 있는 주장을 제공합니다.
플러그인 개발자라면 HTMX를 꼭 확인해 보세요. 이 기사에서는 표면적인 내용만 다루었고 문서는 많은 예제와 함께 매우 잘 작성되었습니다. HTMX가 기본적으로 제공되는 양을 고려하면 놀라울 정도로 짧습니다. 몇 분 안에 HTMX 및 PHP를 시작할 수 있습니다.