News Feed

“미니멀리스트를 위한 자바스크립트 프레임워크” 알파인js

컨텐츠 정보

  • 조회 686

본문

최근 백패킹으로 빅서 지역 여행길에 올랐는데, 며칠 후 백패커에게 일어나는 필연적인 일이 발생했다. 바로 배낭 안의 모든 물건이 정말 필요한지 자문하게 되는 일이다. 소프트웨어 개발 프로세스에서의 기술 선택도 이와 비슷하다. 시스템의 모든 자산은 복잡성을 더하므로 그에 상응하는 가치를 제공해야 한다.

알파인(Alpine)은 미니멀리스트를 위한 리액티브 프레임워크로 자리를 잡았다. 작은 공간에서 상당한 범위의 기능을 제공한다. 소수의 기능 모음으로 이렇게 많은 일을 할 수 있다는 사실이 놀라울 정도다.

알파인의 미니멀리스트 API

알파인 문서에도 나와 있듯이 알파인은 15개의 특성(attribute), 6개의 속성(property), 2개의 메서드로 구성되는 아주 작은 API다. 단순한 패키지로 반응성을 제공하고, 부가적으로 이벤트 처리, 스토어와 같은 여러 편의 기능을 제공한다.

다음과 같은 간단한 웹 페이지를 생각해 보자.

html>head>  script src="https://unpkg.com/alpinejs@3.14.8/dist/cdn.min.js" defer>script>head>body>  div x-data="">    span x-text="'Text literal'">span>div>body>html>

CDN을 통해 알파인 패키지를 포함하는 것 외에 여기서 알파인과 관련된 요소는 x-datax-text, 두 지시어가 전부다.

시스템의 HTML 페이지에 넣고 브라우저에서 확인하면 “Text literal” 출력 메시지를 볼 수 있다. 간단하지만 여기서 알파인에 관한 2가지 흥미로운 사실을 알 수 있다.

첫째, 반응성이 작동하도록 하려면 마크업을 x-data 지시어로 묶어야 한다. 이 지시어를 제거하면 x-text가 작동하지 않는다. 즉, x-data 지시어는 알파인 구성요소를 생성한다. 여기서 지시어는 비어 있지만 실제 사용하는 경우 거의 항상 데이터가 들어간다. 애초에 데이터에 반응하는 것을 목적으로 하는 구성요소를 작성하고 있기 때문이다

둘째, 유효한 자바스크립트라면 무엇이든 x-text에 넣을 수 있다. 이는 모든 알파인 지시어에 동일하게 해당된다. x-text 속성은 HTML(뷰)과 자바스크립트(동작) 간의 링크를 제공한다.

x-data 및 x-text 요소 사용하기

x- data 내용은 포함된 모든 요소에 제공된다. 이 말을 이해하기 위해 다음 코드를 살펴보자.

div x-data="{ message: 'When in the course of human events...' }">  span x-text="message">span>div>

이제 페이지에 독립 선언서의 시작 부분이 출력된다. x-data는 서문이 포함된 “message”라는 단일 필드를 갖는 자바스크립트 객체를 정의했고, x-text는 이 객체 필드를 참조한다.

알파인의 반응성

다음과 같이 반응성을 사용해서 문서의 오류를 수정한다.

div x-data="{ noun: 'men' }">  button x-on:click="noun = 'people'">Fix Itbutton>  span x-text="`all ${noun} are created equal`">span>div>

여기서 분명히 볼 수 있듯이 x-text 지시어는 x-data 지시어에 의해 노출된 noun 변수를 참조한다. 새로운 부분은 x-on:click 지시어가 있는 버튼이다. 이 클릭 이벤트의 핸들러는 기존의 기본 noun(“men”)을 성별 중립적인 “people”로 대체한다. 그러면 반응성에 따라 x-text에서 참조 업데이트가 처리된다.

UI는 데이터의 변경 사항을 자동으로 반영한다.

데이터의 함수

알파인의 데이터 속성은 정식 자바스크립트 객체다. 이 점을 염두에 두고 위의 요구사항을 처리하는 또 다른 방법을 살펴보자.

div x-data="{       noun: 'men',       fixIt: function(){        this.noun = 'people';      }    }">    button x-on:click="fixIt()">Fix Itbutton>    span x-text="`all ${noun} are created equal`">span>  div>

이 예제에서 data 객체가 이제 클릭 핸들러에 의해 호출되는 fixIt 메서드를 호스팅하는 것을 볼 수 있다. HTML에서 보고자 하는 동작에 가장 적합한 객체 구조를 만들 수 있다.

원격 데이터 가져오기

주제를 바꿔서, 외부 API에서 JSON 형식으로 된 미국 대통령 목록을 로드해야 하는 경우를 살펴보자. 가장 먼저 할 일은 페이지가 로드될 때 목록을 로드하는 것이다. 이를 위해 x-init 지시어를 사용한다.

div x-data="{      presidents: []    }"     x-init="(      async () => {        const response = await fetch('https://raw.githubusercontent.com/hitch17/sample-data/master/presidents.json');        presidents = await response.json();      }    )">    span x-text="presidents">span>  div>

코드를 해부해 보자. x-data 지시어는 명확하다. 빈 배열을 가진 presidents 필드가 있을 뿐이다. span 요소의 x-text는 이 필드의 내용을 출력한다.

x-init 코드는 약간 더 복잡하다. 우선 자체 실행 함수로 래핑된 것을 볼 수 있는데, 이는 알파인이 함수 정의가 아닌 함수를 기대하기 때문이다. 비동기가 아닌 콜백 형태의 fetch를 사용한다면 이처럼 함수를 래핑할 필요가 없다(비동기 범위의 함수가 불필요하므로).

엔드포인트에서 대통령 목록을 가져오고 나면 알파인이 x-data 객체의 일부로 노출한 presidents 변수에 집어넣는다.

다시 말하면 알파인은 x-data의 데이터를 동일한 컨텍스트 내의 다른 지시 함수(예 : x-init)에서 사용할 수 있도록 한다.

알파인으로 반복

이 시점에서 앱은 원격 엔드포인트에서 데이터를 가져와 상태에 저장하지만 출력은 원하는 것과는 다른 [Object],[Object]…와 같은 형태다. 이 문제를 해결하려면 먼저 데이터에 대한 반복을 살펴봐야 한다.

div x-data=...>ul>      template x-for="pres in presidents">        li>div x-text="pres.president">div>          From: span x-text="pres.took_office">span> Until: span x-text="pres.left_office">span>li>      template>    ul>div>

깔끔하고, 따로 설명이 필요 없는 코드와 템플릿이다.

코드에는 일반적인 순서 없는 목록과 x-for 지시어가 포함된 HTML 템플릿 요소가 포함된다. 이 지시어는 다른 리액티브 프레임워크와 같은 방식으로 작동한다. 컬렉션, 대통령, 식별자를 지정할 수 있고, 이는 해당 컬렉션의 각 인스턴스(이 경우 대통령)를 나타내는 포함된 마크업에 제공된다.

나머지 마크업은 pres 변수를 사용해서 x-text를 통해 객체의 데이터를 출력한다. (이런 반복자 사용은 모든 소프트웨어에서 매우 보편적인 패턴 중 하나다.)

이제 앱은 아래 스크린샷과 비슷한 형태로 미국 대통령 목록을 보여준다.

A list of United States presidents generated with Alpine.js.

Figure 1. A list of United States presidents

IDG

표시/숨기기 및 onClick

이제 대통령 이름을 클릭하면 대통령에 대한 데이터를 표시하거나 숨기는 기능을 추가해 보자. 다음과 같이 마크업을 수정한다.

template x-for="pres in presidents">  li>    div x-text="pres.president" x-on:click="pres.show = ! pres.show">div>    div x-show="pres.show">       From: span x-text="pres.took_office">span> Until: span x-text="pres.left_office">span>     div>  li>template>

대통령 세부 정보가 포함된 divx-show 지시어를 사용한다. x-show 값의 참 여부에 따라 콘텐츠가 표시되는지 여부가 결정된다. 여기서는 pres.show 필드에 의해 결정된다. (실제 애플리케이션에서는 데이터와 동작을 서로 더 분리하기 위해 표시/숨기기 변수를 호스팅하는 데 실제 비즈니스 데이터를 사용하지 않는 것이 좋을 수 있다.)

pres.show의 값을 변경하려면 헤더에 x-on:click 핸들러를 추가한다. 이 핸들러는 pres.show: pres.show = ! pres.show의 참/거짓 값을 뒤바꾼다.

전환 애니메이션 추가

알파인에는 표시/숨기기 기능에 적용할 수 있는 전환이 기본적으로 포함돼 있다. 기본 애니메이션을 추가하는 방법은 다음과 같다.

div x-show="pres.show" x-transition>  From: span x-text="pres.took_office">span> Until: span x-text="pres.left_office">span>li>div>

바뀐 점은 x-show 지시어가 포함된 요소가 전부인데, 이제 이 요소에 x-transition 지시어도 포함된다. 알파인은 기본적으로 적절한 전환을 적용한다. 여기서는 슬라이드 앤 페이드 효과가 사용된다. 애니메이션의 다양한 단계에 자체 CSS 클래스를 적용하는 등의 방법으로 폭넓게 전환을 맞춤 설정할 수 있다. 자세한 내용은 알파인 전환 문서에서 볼 수 있다.

입력에 바인딩

이제 간단한 필터 기능을 추가해 보자. 이를 위해서는 데이터에 바인딩할 입력을 추가한 다음 이 값을 기준으로 반환된 데이터 집합을 필터링해야 한다. 변경 사항은 다음에서 확인할 수 있다.

div x-data="{  filter: '',  presidents: [],    getPresidents: function(){        return this.presidents.filter(pres => pres.president.includes(this.filter) )      }    }" ...    ...  ul>      template x-for="pres in getPresidents">

x-data 객체에서 “filter” 필드를 볼 수 있다. 이는 “filter”를 가리키는 x-model 지시어를 통한 입력 요소에 대한 양방향 바인딩이다. 템플릿 x-for 지시어를 변경해서 x-data 객체에 구현된 새로운 getPresidents() 메서드를 참조하도록 했다. 이 메서드는 표준 자바스크립트 구문을 사용해서 “filter” 필드에 텍스트가 포함되어 있는지 여부에 따라 대통령을 필터링한다.

여기에 나온 모든 예제 코드는 필자의 깃허브 리포지토리에서 볼 수 있다.

결론

이름에서 알 수 있듯이 알파인은 산행에 필요한 기본적인 장비를 담은 백팩과 같다. 최소한의 장비지만 충분하다. 중앙 스토어, 이벤트 처리 시스템, 플러그인 아키텍처, 생태계와 같은 고급 기능도 포함돼 있다.

전반적으로 알파인은 사용하기 편리하며, 다른 리액티브 프레임워크를 다룬 경험이 있는 사람에게는 익숙하게 느껴진다. 이런 이유로 쉽고 빠르게 배울 수 있다. 구성요소와 그 데이터를 간단히 x-data 지시어에 선언할 수 있다. 필자는 다음 코딩 작업에서 알파인 사용을 적극 검토할 예정이다.
dl-itworldkorea@foundryco.com

관련자료

댓글 0
등록된 댓글이 없습니다.
Member Rank