Nextree

jQuery: data() 이해와 활용

Nextree May 27, 2014 0 Comments

jQuery를 조금이나마 접해보신 분들은 다양한 방법으로 DOM을 select하거나 이벤트 제어, Ajax통신 등 jQuery가 지원하는 편리한 기능에 많이 익숙해지셨을 거라 생각됩니다. 이번에 준비한 글은 매우 유용하고 활용도가 높은 함수이지만 지나치기 쉬운 jQuery의 data()에 대해 알아보겠습니다. 간략하게 말해 data()는 HTML 엘리먼트 내에 데이터를 저장하고 읽는 역할을 하는 함수입니다. 딱히 데이터를 HTML에 삽입하는 이유가 있는가? 하는 의문도 들 수 있고, 이것을 언제, 어디서, 왜 써야하는지 의문점이 생길 수도 있어 지금 제가 진행중인 프로젝트에서 적용한 몇가지 부분을 예로 들어보겠습니다.

현재 진행중인 프로젝트에서는 data()를 적용한 부분은 다음의 2가지로 압축할 수 있습니다.

  • 서버에서 조회된 데이터를 추후 ajax통신을 하기 위한 data 저장
  • data()를 활용하여 Form의 <input>엘리먼트의 validation 적용

위의 용도 이외에도 data()는 여러방면으로 활용이 가능하며 jQuery 특성상 매우 쉽게 적용할 수 있다는 장점이 있습니다. 또한 HTML 엘리먼트에 data를 저장하기 때문에 Javascript에 data를 저장하기 위한 변수 설정이 필요없어지므로 source code를 깨끗하게 유지할 수 있으며, 2번째의 data()를 활용하면 매우 가볍고 쉽게 적용가능한 클라이언트 측 validation을 구현할 수 있습니다. 뿐만아니라 jQuery의 data()는 여타 jQuery의 API를 사용해 왔던것처럼 매우 직관적인 문법을 사용해 쉽게 배우고 적용할 수 있습니다. 그럼 jQuery의 data()에 대해 알아보겠습니다.

1. data()

설명 : 해당 엘리먼트에 Javascript Type의 value를 로 저장할 수 있으며, 값으로 저장되어 있는 데이터를 읽습니다.

[ case 1. 데이타 저장 ]

  • 문법 : $(selector).data(key, value)
  • key : string type의 변수로 data가 저장될 key값입니다.
  • value : object type으로 JavaScript 에서 지원하는 모든 type의 데이터를 저장할수 있습니다.
<script src="http://code.jquery.com/jquery-2.0.0.js"></script>  
<html>  
    <head>
    <meta http-equiv="Context-Type" context="text/html;charset=UTF-8" />

    <script type="text/javascript">
        //span 엘리먼트에 data()함수로 "name"과 "address"세팅방법
        $("span").data("name", "Nextree");
        $("span").data("address", "가산");
    </script>
    </head>

    <body>
    <!-- data()가 호출되면 span엘리먼트에 "name"과 "address"가 추가됩니다.-->
    <span>jQuery의 data()의 저장 방법</span>
    </body>
</html>  

위와 같이 형태로 data를 엘리먼트에 저장할 수 있습니다.

* 추가적으로 HTML5에서는 HTML 엘리먼트에 data-*형식을 이용하여 미리 데이터를 저장할 수 있습니다. 이 방법은 jQuery의 data()를 이용해 저장한 것과 동일한 효과를 나타낼 수 있습니다.

사실 HTML5의 data-*가 나오기 전에는 개발자들마다 가지각색으로 HTML 엘리먼트에 허용되지 않는 속성(임의의 Attr속성)을 추가하여 사용했기 때문에 유지보수 측면이나 해석할때 매우 난해하고 지저분한 HTML이 많았습니다. 하지만 HTML5로 넘어오면서 data-* 속성이 표준화가 되면서 이전의 문제점들이 해결되었습니다.

<body>  
    <div>
        <span
            data-name='nextree'
            data-address='가산'
            data-member='{"name" : "김대호"}'
        >.data()가 저장되는 방식</span>
    </div>
</body>  

[ case 2. 데이터 읽기 ]

  • 문법 : $(selector).data(key)
  • key : 앞서 저장한 data를 읽어오기 위한 key값입니다.
  • key를 생략하고 .data()으로 호출할 경우에는 해당 엘리먼트에 저장된 모든 data들이 JSON형식으로 리턴됩니다.
<script src="http://code.jquery.com/jquery-2.0.0.js"></script>  
<html>  
    <head>
    <meta http-equiv="Context-Type" context="text/html;charset=UTF-8" />

    <script type="text/javascript">
    $(function(){
        //span 엘리먼트에 data()함수로 "name"과 "address"세팅방법
        $("span").data("name", "Nextree");
        $("span").data("address", "가산");

        //data(Key)로 저장된 data읽기
        var name = $("span").data("name");
        var address = $("span").data("address");

        $("p").eq(0).text(name);
        $("p").eq(1).text(address);
    });
    </script>
    </head>

    <body>
    <!-- data()가 호출되면 span엘리먼트에 "name"과 "address"가 추가됩니다.-->
    <span>jQuery의 data()의 읽기 방법</span>
    <p></p>
    <p></p>
    </body>
</html>  

위의 방법으로 저장된 data를 읽어 올 수 있습니다.

* HTML5의 data-*로 저장한 경우 읽어올 경우에는"data-"를 생략한 key를 이용하여 data를 읽어올 수 있습니다.

예 ) $("span").data("name");

또한 아래처럼 snake-case문법으로 저장된 데이터는 camelCase문법으로 읽어올 수 있습니다.

<span  
    data-member-name='김대호'
>camelCase</span>

예 ) $("#span").data("memberName") ;

* 마찬가지로 camelCase형태의 key값으로 데이타를 저장하였다면 HTML에는 snake-case형태로 데이터가 저장됩니다.

다음은 HTML5의 data-*를 이용해 string, int, boolean, json 타입(Javascript Type)의 data들을저장하고 "==="를 이용한 비교연산을 해보았습니다.

[ html ]

<div  
    data-name="홍길동" 
    data-number="99" 
    data-hidden="true" 
    data-options='{"name":"홍길동"}'>
</div>  

[ chrome console ]

[그림1. ] 자동으로 형변환된 데이터 결과

보다시피 HTML5에서는 아래의 결과처럼 "String" Type으로 저장되는 Value의 타입을 판별하여 Javascript에서 지원하는 Data Type으로 알맞게 형변환을 시켜줍니다.

[ case 3. 데이터 삭제 ]

  • 문법 : $(selector).removeData(key)
  • key : string type으로 삭제할 data의 key값.

아래 HTML의 첫번째 <p>엘리먼트에 동적으로 "name" data를 저장하고 removeData()를 이용하여 저장된 데이터를 삭제해 보겠습니다.

[ html ]

<body>  
    <p>data Name</p>
    <p>data Number</p>
</body>  

[ chrome console ]

보다시피 첫번째 <p>에 name이 nextree로 저장되었다가 removeData()를 이용하여 "name"으로 저장된 데이터를 삭제한 것을 확인할 수 있습니다.

이번엔 HTML5의 data-*로 미리 저장되어 있는 "name" data를 removeData()를 이용하여 삭제해보겠습니다.

[ html ]

<span  
    data-name='nextree'
    data-address='가산'
    data-mamber='{"name":"김대호"}'
></span>

[ chrome console ]

위의 결과처럼 미리 HTML에 data-*로 저장된 data들은 removeData()를 이용하여도 지워지지 않는 문제가 있습니다. 이런 경우는 .data("name", null)로 저장되어있는 값을 null로 바꿔주는것으로 해결이 가능합니다.

2. data() 활용방안

현재 제가 진행중인 프로젝트에서 data()를 활용한 부분을 살펴보며 이번 글을 마치겠습니다.

[ 활용방안 1. ]

서버에서 조회된 데이터로 테이블을 구성할때 다음과 같이 사용합니다. ( el표현식을 이용하여 서버에서 조회된 data를 받고 있습니다. )

[ jsp file ]

 <c:forEach var="item" items="${itemList}" varStatus="status">
    <tr  
         data-idx='${status.count}'
         data-distb-idntfc-no='${item.distbIdntfcNo}'
         data-sn='${item.sn}'
         data-regn-detail-code='${item.regnDetailCode}'
         data-regn-code='${item.regnCode}'
         data-regn-nm='${item.regnNm}'
         onclick='fn_popupItem(this)'
    >
     <td>${status.count}</td>
     <td>${item.distbIdntfcNo}</td>
     <td>${item.prdlstNm}</td>
     <td>${item.regnNm}</td>
    </tr>
</c:forEach>  

[ javaScript file ]

var fn_popupItem = function(obj) {

    var param = $(obj).data();

    // POST 요청
    $("#itemLayer").load(CTX + "/bm/sel/insertPuchasFragment.do", param);
};

조회된 데이터를 화면에 보여주기 위한 목적 이외에 추가적으로 data를 조작할 경우가 있을때 에 data를 저장시켜 놓습니다.

이후 저장된 데이터로 ajax통신을 할 경우에는 에 저장된 데이터를 .data() 메소드를 이용하여 JSON타입의 data로 가져온 후 ajax통신을 합니다.

특히나 ajax통신을 할때 data()메소드를 이용하면 JSON type의 데이터로 리턴이 되기 때문에 따로 JSON타입으로 치환하지 않아도 쉽게 ajax통신을 할 수 있다는 장점도 있습니다.

[ 활용방안 2. ]

화면에서 서버측으로 Form submit할 경우 추가적인 jQuery plug-in이나 외부 라이브러리가 필요없이 간단한 정규식과 data()를 활용함으로써 가볍고 쉽게 사용할 수 있는 클라이언트 측 validation을 추가하였습니다.

다음의 소스코드를 따라하면 쉽게 적용할 수 있습니다.

< step >

  1. <input>엘리먼트에 data-valid에 [정규식, 검증실패 메시지] 형식으로 데이터를 저장합니다.
  2. form submit 이벤트 핸들러에서 validFormNow()메소드를 호출하고 true일 경우에만 form submit을 합니다. 만약 input태그의 정규식 검증이 실패하면 data-valid에 세팅한 검증실패 메시지를 확인할 수 있습니다.

[ index.html ]

<script src="http://code.jquery.com/jquery-2.0.0.js"></script>

<html>  
    <head>
    <script type="text/javascript" src="underscore.js"></script>
    <script type="text/javascript" src="common.js"></script>
    <meta http-equiv="Context-Type" context="text/html;charset=UTF-8" />

    <script type="text/javascript">

        $(function(){
            //form submit할 버튼이벤트에 validFormNow()호출
            $("#search").click(function(){
                //검증이 true일 경우에만 form submit
                if($("#searchForm").validFormNow()){
                    //$("#searchForm").submit();
                };
            });
        });

    </script>
    </head>

    <body>
        <form name="searchForm" id="searchForm">
            숫자 : <input type="text" data-valid="[[/^[\d]{4,4}$/,'네자리 숫자를 입력해주세요']]"/><br>
        문자 : <input type="text" data-valid="[[/^.{3,8}$/,'3글자에서 8글자사이로 입력해주세요']]"/><br>
            <button id="search">조회</button>
        </form>
    </body>
</html>  

data-valid의 첫번째 요소가 정규식 형태의 데이타인지 확인하기 위한 "_.isRegExp()"메소드를 호출하기 위해 underscore.js를 include하였습니다.

data 검증을 위한 javaScript 파일(common.js)을 공통파일로 분리하고 include합니다.

[ common.js ]

$.fn.extend({
    valid : function(tests) {
            tests.forEach(function(test){
                var $input = $(this);
                var value = $input.val();
                if (Array.isArray(test)) {
                    var testTerm = test[0];         //정규식
                    var exceptionMessage = test[1];     //정규식이 틀릴 경우 보여줄 검증 실패 메시지

                    //배열의 첫번째요소가 정규식이 아니거나 정규식 테스트를 실패한 경우에
                    //exception에 검증실패메시지를 세팅한 후 throw한다.
                    if( _.isRegExp(testTerm) && !(testTerm.test(value)) ){
                        throw {exceptionMessage : exceptionMessage};
                    }
                } else {
                    throw {exceptionMessage : "스크립트 오류", input :$input};
                }
            }, this);

    },

    validFormNow : function(){
        var $this = $(this);
        $this.find(':input').each(function(idx, el){
            var validData = eval($(el).data("valid"));
            if(validData != ""){
                try{
                    $this.valid.call(el, validData);
                } catch (e) {
                    //정규식 검증 실패한 경우 실패 메시지 alert
                    if(e.exceptionMessage){
                        alert(e.exceptionMessage);
                        $(el).focus();
                        return false;
                    }
                }
            }
        });
        return true;
    }
});

jQuery 함수를 확장하여 validFormNow()를 구현하였습니다. 위의 소스코드 그대로 테스트를 해보실 수 있으며 위 소스코드는 이해를 돕기위해 만든 간단한 소스코드이니 해석은 생략하겠습니다.

3. 마치며

이전 프로젝트에서는 대부분 jQuery를 이용하여 다양한 방법으로 DOM을 select 하거나 Ajax통신을 하기위한 용도로 많이 사용하였지만 이번 프로젝트에서 data() 처음 적용하게 되었는데 매우 유용하게 다방변에서 사용하고 있습니다. 클라이언트측에서 <input>엘리먼트의 값을 검증하는 방법은 매우 다양한 하지만, 간단한 정규식과 jQuery의 data()를 이용하여 validation적용하는 부분은 다른 validation적용보다 더욱 간편하게 사용할 수 있고 직관적이기 때문에 매우 좋은 방법이라고 생각됩니다. 사용하는 방법이 매우 간단하므로 실제 현장에서 적용해보시는것을 추천드리며 이번 글로인해 조금이나마 jQuery의 data()메소드 사용에 친숙해지길 바랍니다. 마지막으로 data()를 활용한 클라이언트 측 validation 적용 부분을 개발하고 많은 도움을 주신 장유현님께 고마움을 전합니다.

참조도서 및 사이트

Nextree

Read more posts by this author.