블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2014. 1. 30. 11:15 AngularJS/Start MEAN Stack

UI-Router를 이용한 화면 라우팅 설정을 app/scripts/app.js 메인 애플리케이션 파일에 설정하였다. 설정 내용중 각 라우팅되는 HTML View의 제어를 담당하는 Controller를 yeoman을 사용해서 생성해 보자 



HTML과 Controller 

  앵귤러는 MVW 프레임워크라고 하는데 여기서 M은 model 이고 V는 View, W은 Whatever를 의미하여 무엇이든지 올 수 있다는 의미이다. Whatever에는 싱글톤패턴의 서비스, 팩토리 또는 필터, 디렉티브(Directive)등이 올 수 있다. 


  - Model : Controller의 $scope를 통한 자동 two-way binding 을 한다 

  - View : HTML에 $scope의 모델들을 설정하거나 앵귤러의 디렉티브를 이용하여 직관적인 설정한다  


  앵귤러의 데이터 모델은 바로 Scope에 의해서 연결이 되며, app.js 가 최초 수행 되면 $rootScope가 생성되고 그 하위로 $scope가 생성된다. 이들은 계층적으로 연결되어 상위의 scope 데이터에 접근할 수 있다. 만일 Chrome 브라우져를 사용한다면 scope 객체들의 계층구조를 보기 위하여 별도의 크롬도구를 설치해야 한다. 


 1) AngularJS Batarang: https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk 설치 

 2) 크롬 개발자도구 : 윈도우(Ctrl+Shift+i), 맥(Command+Option+i) 연다 

 3) 맨 우측의 AngularJS를 선택하고 Enable 옵션을 체크한다 

 4) < Scope (003) 에서 003은 앵귤러가 Scope를 생성하고 부여한 아이디이고 클릭하면 우측에 Scope에 저장된 정보를 볼 수 있다.



1. 화면별 컨트롤러 생성하기 

  Yeoman에서 앵귤러 프레임워크의 기능을 자동 생성해 주는 것은 yo 명령이다. 우리는 meanstack 애플케이션 생성을 위하여 "generator-angular"를 설치하였는데 yo 뒤의 명령은 관례에 따라 "yo angular:<기능> <명칭>"으로 사용할 수 있다. 


  - yo의 generator가 만일 generator-mean 이고 geneartor-mean안에 <기능>으로 controller가 있다면 

  - yo mean:controller sample 을 수행하면 보통은 컨트롤러 코드와 컨트롤러 테스트 코드가 자동 생성된다

  -즉 "yo <generator- 두의 명칭>:<genertor가 제공하는 기능명칭>  <사용자정의 명칭>" 으로 명령은 구성된다 

  - <사용자정의 명칭> 에서 이름을 지정할 때는 "user-biz" 라고 명칭을 주면 index.html에는 "user-biz.js" 파일이 추가 되고, 기능의 명칭은 "UserBiz<기능약어>" 식으로 명칭이 만들어 진다.


  generator-angular 기능 목록은 홈페이지를 참조한다 (https://github.com/yeoman/generator-angular) 컨트롤러 생성시 테스트 코드 파일이 자동으로 생성된다 

// yo angular:controller <명칭> 으로 각 메뉴의 컨트롤러를 생성한다.

$ yo angular:controller my-level

   create app/scripts/controllers/my-level.js

   create test/spec/controllers/my-level.js


$ yo angular:controller my-qna

   create app/scripts/controllers/my-qna.js

   create test/spec/controllers/my-qna.js


$ yo angular:controller my-following

   create app/scripts/controllers/my-following.js

   create test/spec/controllers/my-following.js


$ yo angular:controller tech-area

   create app/scripts/controllers/tech-area.js

   create test/spec/controllers/tech-area.js


$ yo angular:controller ranking

   create app/scripts/controllers/ranking.js

   create test/spec/controllers/ranking.js


$ yo angular:controller member

   create app/scripts/controllers/member.js

   create test/spec/controllers/member.js


$ yo angular:controller login

   create app/scripts/controllers/login.js

   create test/spec/controllers/login.js


// index.html에 자동으로 추가된 것을 볼 수 있다.

<!-- build:js({.tmp,app}) scripts/scripts.js -->

<script src="scripts/app.js"></script>

<script src="scripts/controllers/main.js"></script>

<script src="scripts/controllers/my-level.js"></script>

<script src="scripts/controllers/my-qna.js"></script>

<script src="scripts/controllers/my-following.js"></script>

<script src="scripts/controllers/tech-area.js"></script>

<script src="scripts/controllers/ranking.js"></script>

<script src="scripts/controllers/member.js"></script>

<script src="scripts/controllers/login.js"></script>

<!-- endbuild -->


  컨트롤러를 생성했는데 - 또는 . 를 사용하면 앞뒤의 문자들의 첫글자가 대문자로 변형되어 설정이 되고 뒤에 "Ctrl" 이 자동으로 붙는다 

// app/scripts/controllers/my-level.js 소스

'use strict';


angular.module('meanstackApp')

  .controller('MyLevelCtrl', function ($scope) {

    $scope.awesomeThings = [

      'HTML5 Boilerplate',

      'AngularJS',

      'Karma'

    ];

  });

  

  이제 app/scripts/app.js에 컨트롤러를 설정해 보자 

$stateProvider

      .state('main', {

        url: '/',

        templateUrl: 'views/main.html',

        controller: 'MainCtrl'

      })

      .state('login', {

        url: '/login',

        templateUrl: 'views/login.html',

        controller: 'LoginCtrl'

      })

      .state('mylevel', {

        url: '/mylevel',

        templateUrl: 'views/mylevel.html',

        controller: 'MyLevelCtrl'

      })

      .state('myqna', {

        url: '/myqna',

        templateUrl: 'views/myqna.html',

        controller: 'MyQnaCtrl'

      })

      .state('myfollowing', {

        url: '/myfollowing/{userId:[0-9]{1,4}}',

        templateUrl: 'views/myfollowing.html',

        controller: 'MyFollowingCtrl'

      })

      .state('techarea', {

        url: '/techarea/{techId:[0-9]{1,4}}',

        templateUrl: 'views/techarea.html',

        controller: 'TechAreaCtrl'

      })

      .state('gururanking', {

        url: '/gururanking',

        templateUrl: 'views/gururanking.html',

        controller: 'RankingCtrl'

      })

      .state('gurumember', {

        url: '/gurumember',

        templateUrl: 'views/gurumember.html',

        controller: 'MemberCtrl'

      });


  my-following이나 tech-area를 보면 아이디를 설정하였고 myfollowing.html에서 $stateParam을 사용하기위해 meanstackApp 모듈의 run() 에서 $rootScope에 $stateParams를 저장한다. 그리고 페이지가 전환 되기 시작할 때와 전환하여 로딩 완료되었을 때의 이벤트를 처리하기 위한 Listener를 등록한다. 

// myfollowing.html 

<div class="row">

  <div class="col-md-12">

    <h1>myfollowing.html</h1>

     User ID: {{$stateParams.userId}}

  </div>

</div>


// app/scripts/app.js

.run(['$rootScope', '$state', '$stateParams', 

  function ($rootScope, $state, $stateParams) {

    $rootScope.$state = $state;

    $rootScope.$stateParams = $stateParams;

  }]);


  - html에서 $stateParams 를 찾기위하여 자신의 $scope.$stateParams를 찾는다 없으면 다시 상위의 $rootScope.$stateParams을 찾게 된다. 따라서 클라이언트 애플리케이션 전역에서 사용할 내용들이 있다면 $rootScope에 저장한다. 

  - myfollowing 메뉴를 선택하면 Scope (009) 의 아이디값이 변경된다. 메뉴를 누를 때마다 Scope의 아이디가 변경되는데 이는 클라이언트 화면이 변경될 때 이전 Scope는 destroy되고 새로운 Scope가 생성되기 때문이다. 즉, 앵귤러가 화면 라우팅이되고 해당 화면의 컨트롤러에 신규 $scope 을 생성하여 DI (Dependency Injection)해준다 



2. 컨트롤러 코드 변경하기 

  애플리케이션 배포시에는 "grunt build"를 수행하는데 이때 .js에 대한 단축화(minification)이 수행되어 변수명을 알 수 없는 코드로 바꾸어준다. 앵귤러에서는 $로 시작하는 명칭이 변경이 되면 안되기 때문에 yo로 생성된 코드를 그대로 사용할 수 없다.  '$scope' 문자를 지정해 주면 function($scope) {} 가 최소화 되어 function($ab){} 로 바뀌어도 DI시에 '$scope'로 지정된 $scope 객체가 주입된다.

 angular.module('meanstackApp')

 .controller('MyFollowingCtrl', [

  '$scope',

  function ($scope) {

    ... 중략 ...

  }]);

  

  다른 컨트롤러도 해당 방식으로 전부 수정한다. 소스는 anuglar_setp02_insert-ctrl-menu 브랜치를 체크아웃한다 

https://github.com/MEAN-STACK/MEANStack-Bookwork/tree/anuglar_setp02_insert-ctrl-menu

posted by 윤영식