XE3에 Vue.js 도입하기 (입문자용)

본 글은 XE OpenSeminar #3에서 진행한 세션의 내용을 정리한 글입니다. 해당 세션의 발표 영상은 XE youtube 채널에서 보실 수 있고 발표 자료는 XE SlideShare에서 다운로드 받으실 수 있습니다.

최근 떠오르고 있는 프론트엔드인 Vue에 대해서 알아보고 XE3 쇼핑몰 플러그인, <XeroCommerce>에 적용했던 경험을 공유하는 시간을 가지고자 합니다.

변화하는 Frontend

요즘 등장하고 있는 프론트엔드는 이전과 비교해서 어떻게 다를까요?

요즘의 Frontend를 대표하고 있는 Vue, React, Angular입니다.

idname, class속성을 활용하는 순수한 자바스크립트와 셀렉터를 기반으로 DOM에 접근하는 JQuery의 기본컨셉은

<head><body>, <style>, <script>

로 이루어진 html마크업 언어에서 <script>가 html문서를 이루고 있는 각각의 Element들을 가져오는데에서 출발합니다.

이를 통해서 개발자는 사용자에게 기대하는 동작(클릭과 같은 이벤트와, 폼과 같은 입력문)을 처리할 수 있게 됩니다.

그래서 script를 구현하는 개발자는 미리 html로 작성해 놓은 문서에서 다루고자 하는 엘리먼트를 찾아오고, 바꾸고자 하는 속성값을 구해오고, 이를 변화시키는 등의 동작을 기술합니다.

이 컨셉을 저는 DOM을

빌려온다.

라고 표현하겠습니다.

Vue, Angular, React의 컨셉은 이것과 조금 다릅니다. 전통적인 스크립트와 다르게 이들은 virtual DOM과 변화감지라고 하는 진보한 방식으로 사용자화면을 그려냅니다. 동작하고 계산하는 부분은 사용자에게 보이지 않는 곳에서 프로그래밍을 하듯이 처리하고, 가상으로 만들어낸 문서를 통해서 사용자에게는프로그래밍을 통해 준비된 화면을 그려냅니다.

Vue는 html에서 필요한 속성값을 선언하는 방식으로 문서를 작성합니다.

Vue는 v-라는 접두어로 시작하는 속성을 통해 html에 javascript 변수를 직접 넣어 재현합니다. 이것은 전통적인 방법과 극명한 차이를 보입니다.

이전에서 너비값을 바꿔주려면 기존의 엘리먼트에 있는 style을 불러오고, width값을 가져와서 사용자이벤트로 계산해낸 변화값을 주어야했다면,

Vue에서는 그냥 html태그에 v-bind:style을 이용해 상수가 아닌 변수를 대입하기 때문입니다.

width:10을 지정해두고 후에 width를 바꾸기 위해 찾아 가는 것이 아니라 작성할때부터 width:foo로 지정을 해두고 foo=10, foo=20 과 같이 변수에 값을 달리하면 즉각적으로 width가 눈앞에서 변화하는 마법을 부릴수 있게 됩니다.

그래서 저는 이를 DOM을

지배한다.(Dominate)

라고 표현했습니다.

이렇게 최신 프론트엔드는 구현을 하고자하는 html에 직접적인 개입을 하므로써 사용자페이지에서 일어나는 모든 일들을 처리하고자 합니다. Vue는 html에 개입하는 선언적렌더링 방식으로, React는 jsx라고 하는 렌더링을 통해 html자체를 script에서 그려냅니다. (Vue도 render를 지원합니다!) 이런 방법은 개발자로 하여금 빠르고 알기 쉬운 작성을 할 수 있도록 돕습니다.

Frontend 비교하기

이 표보다는 구글링을 통해 질좋은 자료를 확인하는 것이 더 좋습니다.

여기서는 프론트엔드의 각각의 특징보다는 요즈음 프론트엔드 기술들이 어떤 추세에 있는지를 중심으로 알아보려고합니다.

2018.stateofjs.com에서는 개발자를 대상으로 서베이를 합니다.

2018.steteofjs.com에서 제공하는 개발자 약 1만8천명을 대상으로 진행한 servey자료에 따르면 압도적으로 react를 사용하고 있는 개발자가 많다는 것을 알 수 있습니다. 실제로 프로젝트에서는 react를 많이 사용하고 있습니다. “주의깊게 볼 부분은 들어본적이 있고 앞으로 배워볼 계획이 있다.” 라고 답변한 비율은 Vue에서 가장 높게 나타났다는 점입니다.

구글트렌드의 검색어 비교그래프

이어서 구글트렌드에서 검색어를 비교해봐도 Vue가 다른 프레임워크보다 많은 관심도를 가지고 있다는 것을 확인할 수 있습니다. (국가를 대한민국으로 한정하면 react가 vue보다 더 높은 검색어 순위에 랭크되어있습니다.)

이를 통해서 Vue가 차세대 프론트엔드를 대표할 잠재적인 가능성이 있다는 것을 알 수 있었습니다.

Vue는 한번 배워두면 누구나 사용하기 편하게 되어있습니다.

Vue의 강점은 가장 단순하고 누구나 사용하기 쉽다는 것에 있습니다. v-로 시작하는 문법과 vue의 구조를 알아야하지만, 필요한것만 배워둔다면 자신이 원하는 동작을 곧바로 구현해내기 쉽습니다. 또한 프레임워크가 아닌 라이브러리자체로서 구동이 가능하다는 점은, 기존의 다른 프레임워크를 사용하거나 다른 환경에서도 vue를 사용할 수 있도록 만들어줍니다.

Vue 사용해보기

Vue를 사용하는 방법

Vue를 사용하는 방법은 여러가지가 있습니다. node와 npm을 사용하는 개발자들은 npm이나 yarn을 통해 설치할 수도 있고 물론 webpack으로 번들링할 수도 있습니다. vue-cli를 사용해 커맨드를 통해서 vue 프로젝트를 생성할 수도 있습니다.

초심자들이 따라하기 가장 쉬운 방법은 script태그로 js파일을 로드하는 것입니다.

이것만으로 vue를 작성할 준비를 마칠 수 있습니다.

Xe3에 Vue도입하기

Xe3는 php 라라벨을 기반으로한 설치형 프레임워크입니다. Vue는 javascript로 작성하는 프론트엔드 프레임워크이자 라이브러리입니다. 저는 최근 프로젝트에서 쇼핑몰 플러그인에 Vue를 도입해볼 수 있는 기회를 가졌고, Vue의 원하는 기능을 사용하기 위해 여러가지 방법을 사용했습니다.

Vue를 사용하면 개발자는 위에서 이야기했던 것처럼 선언적 렌더링을 통해 미리 생각해야할 것들과 다른 부차적으로 달리는 소스의 수를 굉장히 많이 줄일 수 있습니다.

이러한 예로 쇼핑몰 플러그인에는 상품 옵션 선택과 같은 기능이 있습니다.

상품을 구매할 때엔 크게 신경쓰지 않지만 구현이 안되면 불편한 것들이 있습니다.

사용자가 상품의 여러 옵션을 구매하기위해 선택하면 총 상품금액은 항상 바뀌어야 합니다. 갯수를 줄이거나 늘리거나, 해당 옵션을 삭제하거나 다른 옵션을 선택해서 옵션의 종류가 늘어나거나, 같은 옵션을 선택해서 이미 선택한 옵션의 갯수만 증가하거나 개발자는 이런 행동들의 이벤트를 포착해서 총 상품 금액을 다시 계산하는 함수를 만들어 빼먹지않고 넣어주어야 합니다. 그 함수는 매번 해당 DOM에서 총 상품금액이 위치한 엘리먼트의 값을 가져오고 계산해서 변화시켜줘야 합니다.

하지만 Vue에서는 이러한 고민이 없습니다. 해당 위치에 각 선택한 리스트들의 가격x갯수의 총합(sum)을 총 상품금액 위치에 그려내겠다고 선언만 해주면, 사용자가 갯수를 늘리든 옵션을 추가하든 어떤일이 일어나던간에 다른 일을 해주지 않아도 알아서 실시간으로 가격을 띄워줍니다. 이렇게 하면 소스도 간편해지고 로직도 간편해지며, 한 눈에 알아보기도 쉬워집니다.

이렇게 쇼핑몰플러그인 XeroCommerce에서 Vue를 활용한 방법에는 두 가지가 있습니다.

  1. Vue로 모든 프론트엔드 페이지를 구성하기
  2. 일부분만 Vue로 구성하기

Vue로 모든 프론트엔드 페이지를 구성하기

Vue는 Vue Component를 이용해 컴포넌트 트리로 이루어진 하나의 전체페이지를 생성할 수 있었습니다. 컴포넌트 하나는 독립적인 기능을 하는 컴포넌트들의 집합으로 이루어져 있습니다. 이렇게 작성하고나면 php를 백엔드 서버로만 활용할 수 있게 됩니다. 나머지는 Vue로 렌더링한 프론트페이지가 있을 뿐이죠. 그렇게 되면 다시 vue만을 사용한 spa(Single Page Application)를 사용할 수 있을 뿐만 아니라, 백엔드단에서도 외부의 써드파티 api를 제공할 수도 있게 됩니다…!

쇼핑몰 플러그인의 상품구매 페이지는 한 페이지를 Vue로 구성했습니다.

하지만 xe3와 vue를 사용하게되면 몇 가지 타협점이 발생하게 됩니다. 일단 php blade템플릿을 통한 부분적인 UIObject를 vue로 불러오기 어려워집니다. vue는 컴파일링과 비슷한 과정을 통해서 한번 script를 로드합니다. 이 후에 vue 어플리케이션에 html태그를 삽입하게 되면 render함수를 통해 새로운 엘리먼트들을 그려내지만, script태그가 들어오는 경우 이를 외부의 공격으로 인식하고 차단합니다. 그렇기 때문에 서버측 언어인 php에서 vue를 불러오는건 쉬워지지만 vue에서 blade템플릿을 script까지 완벽하게 가져오는데에는 무리가 있습니다. 다시 vue컴포넌트를 하나 작성해서 넣어줘야합니다.

또 하나는 예전 cgi에서부터 내려오던 php언어는 변수를 html태그에 직접 넣어줄 수 있었기 때문에 백엔드와 프론트엔드를 분리하면 할 수록 변수를 두번씩 초기화해야하는 문제가 발생합니다. 기능과 역할이 완벽하게 분리된 상태에서 개발을 한다면 문제가 발생하지 않습니다만, 한 사람이 vue와 php를 동시에 개발한다고 하면 불필요한 변수를 두번씩 초기화해야하는 문제가 생깁니다. 예를들어 xe3에서 정의한 route name을 사용하고 싶어도 그대로 사용하지 못하고 다시한번 vue를 통해 prop을 받아주어야 하는 등의 문제가 바로 그것입니다. 또한 vue컴포넌트가 여럿 들어있는 페이지를 작성하면 변수를 넣어주어야하는 구조는 더욱 더 복잡해집니다. (전역 변수를 관리할 수 있도록 vuex를 사용하거나 slot을 통한 트리정리로 일부 문제를 해결할 수는 있습니다.) 개발자가 한명일 때에 이런 변수네이밍에 하나하나 신경을 써주지 못한다면 구조와 변수를 하나하나 알아보기 힘들어 질 수 있습니다.

일부분만 Vue로 구성하기

위의 문제를 어느정도 상쇄시켜주는 방법은 전체 페이지를 vue로 사용하기보다는 xe3를 기본으로 하는 blade 템플릿 위에 부분적으로 vue를 도입하는 방법입니다. 이렇게 작성하게 되면 blade 문서 위에서 작업을 하기 때문에 다른 UIObject를 사용하는 것에 허들이 없습니다. 전체적인 프레임워크를 해치지 않으면서 부분적으로 사용가능한 vue라이브러리 사용을 통해서 개발자는 필요한 부분에만 동적인 연출을 할 수 있게 됩니다.

게시판 글쓰기 기능의 태그기능은 부분적으로만 Vue가 활용되었습니다.

첫번째 Vue로 모든 페이지를 작성해 제공하는 방법은 xe3의 커스터마이징을 통해 단일적인 어플리케이션 서비스를 제공해고자 할 때에 유용하게 사용할 수 있습니다. vue를 통해서 프론트엔드를 구성하고나면 일관적인 서비스를 유지하면서 전체적인 사용자화면을 제어할 수 있게되고, 백엔드로 api서비스를 제공할 수 있기 때문에 부분적으로 사용하기보다 전체적으로 일관된 서비스를 제공하는 사이트에 도입하면 잘 사용할 수 있습니다.

두번째로 Vue를 일부분으로 사용해 라이브러리로 제공하는 방법은 xe3사이트 어디에도 동작하는 확장플러그인을 제공하고자 할 때 유용하게 사용할 수 있습니다. 기존의 xe사이트를 유지하면서 부분적으로 동작하는 기능을 구현할 때에는 원래 구현되어있는 UI를 활용하면서도 부가적인 기능을 사용할 수 있도록 라이브러리화된 Vue작성을 하는 것이 더 좋을 것으로 예상됩니다.

지금까지 Vue에 대한 소개와 동향을 알아보고 Vue를 XE3에 활용했던 방법에 대해 이야기해드렸습니다. 갈수록 복잡해지고 빨라지는 웹생태계를 이해하는데에 도움이 되셨으면 좋겠습니다.

XE3도 빨라지는 웹기술을 터득하고 사용자에게 더 좋은 경험을 하기 위해 항상 공부하겠습니다. 감사합니다.


XpressEngine & XEHub Links

- Facebook: https://www.facebook.com/xehub/
- XE3 공식홈페이지: https://www.xpressengine.io/
- GitHub: https://github.com/xpressengine/
- XEHub Medium: https://medium.com/xehub
- XE User Group: Facebook XE Users
- YouTube: XpressEngine XE