본문 바로가기
JavaScript & TypeScript

IE 7,8에서 모던하게 개발하기 #4 - backbone.js (2)

by 향로 (기억보단 기록을) 2016. 10. 11.
반응형

현재까지 관련된 포스팅과 코드는 아래를 참고!

IE 7,8에서 모던하게 개발하기 #1 (npm/grunt)

IE 7,8에서 모던하게 개발하기 #2 (require.js)

IE 7,8에서 모던하게 개발하기 #3 (backbone.js -1)

IE 7,8에서 모던하게 개발하기 #4 (backbone.js -2)

IE 7,8에서 모던하게 개발하기 #5 (backbone.js -3)

IE 7,8에서 모던하게 개발하기 #6 (배포환경 구축)

IE 7,8에서 모던하게 개발하기 #7 (Handlebars.js 적용)

프로젝트 및 코드

backbone.js 사용 (2)

이번 시간에는 Ajax를 진행하기 앞서 backbone예제를 좀 더 다듬어 볼 예정이다.
backbone의 view는 값을 셋팅하는것이 주 목적이 아니라 Model에 따라 Rendering 하는것이 주 목적이다.
Freemarker에서 result를 input 박스가 아니라 <span><strong> 으로 조합해서 다시 만들어보자
여기서 좀 더 난이도를 높이자면 result의 합이 100이하 일 경우에는 기존과 동일하게 <input>로,
100 초과일 경우에는 <span><strong> 로 표기하는 것이다.
이럴 경우 freemarker 혹은 JSP/Html 에서는 실시간으로 화면을 변경할 수 없으므로, 클라이언트 사이드에서 화면 변경이 이루어져야 한다.
즉, Javascript로 동적으로 Html을 그려야 (이하 렌더링) 한다는 것이다.
아래의 코드를 보자.

//AddView.js에 추가

render : function() {
    var result = this.model.get('result');
    var template = this.getTemplate(result);

    /*
     AddView를 생성할때 el 인자를 주입하였다.
     this.el : 순수한 dom element
     this.$el : jquery로 wrapping 된 dom element
     즉, $(this.el) == this.$el 이다.
     */
    this.$el.find('#addResult').html(template);
},

getTemplate : function (result) {

    if(result > 100){
        return '<span>+ : '+'<strong>'+result+'</strong></span>';
    }

    return '<input type="text" id="result" value="'+result+'">';
}

코드에서 얘기하는 것은 간단하다.

  • render 함수는 AddModel을 통해 result 값을 가져온다.
  • getTemplate 함수로 result를 전달하여 원하는 형태의 html을 만들어 전달 받는다.
  • getTemplate 함수에서 전달받은 html 코드를 addResult의 innerHtml에 작성한다.

여기까지 진행하고 다시 확인해보면!


(result가 100미만일 경우의 화면)



(result가 100이상일 경우의 화면)


input에 따라 실시간으로 화면이 변하는 것을 확인할 수 있다.

기능은 정상적으로 작동하지만, 위 코드에는 몇가지 문제점들이 있다.

  • 결국 저 코드는 문자열이다.</span> 이 누락되어도 에디터에서는 체크가 되지 않아 오류가 발생할 여지가 많다.
  • 어떤 Dom형태가 될지 예측이 안된다. 이렇게 될 경우 이후 수정이 필요할 때 많은 실수와 시간이 필요하게 된다.

이런 단점으로 인해 backbone.js는 underscore의 template 함수를 사용하여 렌더링 하는것을 기본 가이드로 제공하고 있다.

// index.ftl
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>모던 IE78</title>
</head>
<body>
    <h1>모던하게 개발하는 IE 7/8 Javascript</h1>
    <div id="userInput" class="row">
        입력 1: <input type="text" class="inputs" id="input1" value="0"><br/>
        입력 2: <input type="text" class="inputs" id="input2" value="0">
        <div id="addResult" class="row">
        </div>
        <!--
            1. userInput div 안에 있어야만 AddView.js에서 찾을 수 있다.
            2. type은 text/template 이다. javascript가 아니다.
        -->
        <script id="underTemplate" type="text/template">
            <input type="text" id="result" value="<%= result %>">
        </script>

        <script id="overTemplate" type="text/template">
            <span>+ : <strong><%= result %></strong></span>
        </script>
    </div>
    <br/>

    <script type="text/javascript" src="/js/lib/jquery.min.js"></script>
    <script type="text/javascript" src="/js/lib/underscore-min.js"></script>
    <script type="text/javascript" src="/js/lib/backbone-min.js"></script>
    <script type="text/javascript" src="/js/lib/require.js"></script>
    <script type="text/javascript" src="/js/main.js"></script>
    <script type="text/javascript" src="/js/index.js"></script>
</body>
</html>

index.ftl에 2개의 script가 추가되었다.
text/template 타입의 경우 <%= %> 에 있는 요소들을 기준으로 전달받은 데이터로 치환하여 html문서로 만들수 있게 지원한다.
우리가 사용할 underscore.template 함수는 이를 사용한 것이다.
AddView.js 역시 아래와 같이 변경하자.

//require->define으로 변경, View객체를 전달하기 위해
define(["add/AddModel"], //사용할 AddModel.js를 requirejs를 통해 load
function(AddModel) {
    return Backbone.View.extend({
        model : null,

        /*  el로 지정한 dom 하위 element중 inputs 클래스를 가진 element에
         keyup이벤트가 발생하면 set함수 호출되도록 지정  */
        events: {
            'keyup .inputs' : 'set'
        },

        underTemplate : $('#underTemplate').html(),
        overTemplate : $('#overTemplate').html(),

        // view 객체 생성시 진행할 코드들
        initialize: function () {
            //아래에서 사용하는 this는 현재 객체 즉, AddView객체를 얘기한다.
            this.model = new AddModel();

            //model의 값이 변경되는(change) 이벤트가 발생하면 view의 render 함수 호출되도록 지정
            this.listenTo(this.model, 'change', this.render);
        },

        set : function() {
            var input1 = $('#input1').val(),
                input2 = $('#input2').val();

            this.model.setInputs({'input1': input1, 'input2': input2});
        },

        render : function() {
            var result = this.model.get('result');
            var template = this.getTemplate(result);

            /*
             AddView를 생성할때 el 인자를 주입하였다.
             this.el : 순수한 dom element
             this.$el : jquery로 wrapping 된 dom element
             즉, $(this.el) == this.$el 이다.
             */
            this.$el.find('#addResult').html(template);
        },

        getTemplate : function (result) {
            var template;

            if(result > 100){
                template = _.template(this.overTemplate);
            }else{
                template = _.template(this.underTemplate);
            }

            return template(this.model.toJSON());
        }
    });
});

변경된 템플릿 과정은 아래와 같다.

  • text/template 타입의 script를 호출한다
  • _.template 함수에 호출한 script의 html을 인자로 넣어 결과를 리턴 받는다.
  • 위 리턴된 결과는 JSON 데이터를 <%= %> 의 요소로 치환시켜줄 수 있는 템플릿 함수이다.
  • Model의 데이터를 JSON 으로 변환시켜 템플릿 함수에 인자로 넣어 최종 템플릿된 html을 전달 받는다.
  • addResult의 innerHtml에 템플릿된 html을 덮어쓴다.

다시 화면을 확인해보면 정상적으로 기능이 작동 되는 것을 확인할 수 있다.
이번 시간에 진행한 template 과정은 많은 회사가 사용하는 방식이지만 여전히 다른 문제들이 남아있다.
이후 handlebars.js를 통해 이를 해결하려고 한다. (handlebars.js는 backbone.js 과정이 끝나면 진행할 예정이다.)
다음 과정은 backbone.js를 통한 Ajax이다


(이번엔 진짜로!)


반응형