2015/01/31 12:01

최적의 방법을 찾는 행위 



최적화

  

  - Optimization은 무엇일까요?

    + 최고가 아닌 최적을 찾는 것.

  - Optimization 을 왜 하는가?

    + 기회 비용을 최소화해 최적화 값을 얻기 위해 통계적 최적화를 사용할 수 있다. 

  - Optimization 을 하면 최고인가?

    + 최적을 하는 것이다. 




해답 표현하기


  - 예) 비행편 출발 시간, 도착 시간을 하루 중 가장 먼저 출발하는 것을 0부터 시작해서 1씩 증가, 각 인원에 대한 수치를 1차원 배열로 나열하는 행위를 모델링이라 한다. 

    예) [1,4,5,2,3,7,4,2]

  - 첫값 : 0, 그리고 1식 증가 

  - 비행편 API 제공 : 카약 http://www.kayak.com/labs/api/search (개발자 키를 발급 받아야 함)

  - 랜덤 값을 사용한다. 얼마나 제대로 된 랜덤 값을 만들어 내느냐가 중요하다. 만약 랜덤 값을 사용하면 stochastic optimization 즉, 통계적인 최적화이다. 

  - 랜덤 값에 대한 부분은 도메인 지식을 필요로 한다?




비용 함수 (Cost Function)


  - 비용이 될 만한 것을 도출

  - 비용 함수에 적용하여 비용이 많이 들수록 큰값을 반환 




언덕등반 (hill climbing)


  - 무작위 해답으로 시작해서 더 좋은 해답을 찾아 이웃 해답들ㅇ르 살펴보는 기법

  - 내리막에서 오르막이 시작될 즈음에서 찾음. 좌우 비교를 통함. 

  - 결점 : 오르락 내리락할 때 작은 내리막이 최적이라고 판단할 수 있은 오류




시뮬레이티드 어닐링 (Simulated Annealing)


  - 물리학에서 영감을 받음

  - 언덕 등반의 결점을 보안

  - 나쁜 선택이 현재 선택이 될 수 있지만 계속 진행할 수록 낳아진다. 

  - 시장에서 많이 사용. 




유전자 알고리즘 (Genetic Algorithm)


  - 개체군(population)이란 무작위 해답들을 생성하면서 시작

  - elitism, 돌연변이(mutation), 교배(crossover), 번식(breeding)

  - 존 홀랜드 1975년 발생 "Adaptation in Natural and Artificial Systems"




선호도 최적화  


  - 최적화 기법의 필요 조건 : 문제가 정의된 비용 함수 + 유사한 해답이 유사한 결과를 낼 것




네트워크 시각화 

  

  - SNS에서 사용 



<참조> 


  - 시뮬레이티드 어닐링

  - 두번째

저작자 표시 비영리 변경 금지

'Growth Hacker > Machine Learning' 카테고리의 다른 글

[ML] 6주차 - 5장 최적화  (0) 2015/01/31
[ML] 4주차 - 군집하기  (0) 2015/01/03
[ML] 3주차 - 추천하기  (0) 2014/12/13
[ML] 2주차 - 추천하기  (0) 2014/12/06
[ML] 1주차 - 시작하기  (0) 2014/11/22
Posted by peter yun 윤영식
2015/01/21 16:15

2주차 진행을 하며 기존 웹 저장소를 별도로 구성해 완전히 별도의 애플리케이션을 구축할 예정이었으나 프러덕션 저장소의 업무로직의 복잡도와 지속적인 개발로 인한 신규 저장소 소스의 불일치 문제가 발생하였다. 따라서 완전히 새로운 저장소로 별도 애플리케이션을 개발하기 보다 Lagacy 코드를 리팩토링 하고 테스트 코드를 신규로 넣고 동시에 연속적인 빌드 환경을 구축하기로 한다. 



1. 모듈 리팩토링


  - AngularJS에서 하나로 묶여 있는 모듈을 여러개로 쪼개는 작업을 진행한다. 

    + 다행히 기존 애플리케이션이 generator-angular-fullstack 으로 되어 있기 때문에 별도로 작업했던 내용을 적용한다. 

    + jandiApp 모듈만 존재한다면 애플리케이션을 위한 추상화 모듈과 공통 모듈로 두가지를 생성한다. 

  - web_client 폴더는 jandi의 웹 애플리케이션 저장소 이름이다. 

    + web_client/client 폴더 밑으로 components 폴더를 만들고 그 밑으로 app와 base 폴더를 만든다. 

    + components/app는 애플리케이션과 연관이 있는 대표 모듈 폴더이다. 

    + components/base는 jandi외에도 어디서나 사용 가능한 그리고 웹에서 bower로 다운로드한 모듈의 폴더이다. 

$ cd web_client/client/

$ mkdir components && cd components

$ mkdir app

$ mkdir base


  - app와 base에 대한 대표 모듈을 만든다.

    + components/app/app.framework.js 파일 생성

    + components/base/base.farmework.js 파일 생성

    + app.framework 모듈은 base.framework 모듈을 의존한다. 

// app.framework.js 내역 

(function() {

  'use strict';


  angular

    .module('app.framework', ['base.framework']);

    

})();


// base.framework.js 내역 

(function() {

  'use strict';


  angular

    .module('base.framework', []);

    

})();


  - 자바스크립트 로딩 우선순위를 지정한다. 

    + index.html 파일의 app.js 보다 먼저 로딩 될 수 있도록 app.framework.js와 base.framework.js를 지정한다. 

    + grunt serve 명령 수행시 app.framework.js와 base.framework.js 파일이 자동 inject 되지 않도록 ingore 설정을 한다. 

    + watch와 inject에 경로를 설정하고 설정앞에 ! 주면 exclude하겠다는 의미이다. 

// index.html 일부 내역 

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

<script src="components/base/base.framework.js"></script>

<script src="components/app/app.framework.js"></script>

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

<!-- injector:js -->

<script src="assets/javascripts/angulartics-ga-custom.js"></script>



// Gruntfile.js 일부 내역

 watch: {

            injectJS: {

                files: [

                    '<%= yeoman.client %>/{app,components}/**/*.js',

                    '!<%= yeoman.client %>/{app,components}/**/*.spec.js',

                    '!<%= yeoman.client %>/{app,components}/**/*.mock.js',

                    '!<%= yeoman.client %>/components/base/base.framework.js',

                    '!<%= yeoman.client %>/components/app/app.framework.js',

                    '!<%= yeoman.client %>/app/app.js'],

                tasks: ['injector:scripts']

            }, 

... 중략 ....

injector: {

            options: {},

            // Inject application script files into index.html (doesn't include bower)

            scripts: {

                options: {

                    transform: function(filePath) {

                        filePath = filePath.replace('/client/', '');

                        filePath = filePath.replace('/.tmp/', '');

                        return '<script src="' + filePath + '"></script>';

                    },

                    starttag: '<!-- injector:js -->',

                    endtag: '<!-- endinjector -->'

                },

                files: {

                    '<%= yeoman.client %>/index.html': [

                        [

                            '{.tmp,<%= yeoman.client %>}/assets/javascripts/*.js',

                            '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',

                            '!{.tmp,<%= yeoman.client %>}/components/base/base.framework.js',

                            '!{.tmp,<%= yeoman.client %>}/components/app/app.framework.js',

                            '!{.tmp,<%= yeoman.client %>}/app/app.js',

                            '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.spec.js',

                            '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js']

                    ]

                }

            },


  모듈 리팩토링 준비가 되었다. 리팩토링할 대상을 선정한다. generator-angular-fullstack으로 애플리케이션을 생성하면 client/app/app.js 파일이 메인 파일이 된다. 먼저 app.js안에 애플리케이션 모듈 set과 config, run에 다양한 설정이 되어 있다면 이들을 base.framework 또는 app.framework으로 분리할 수 있는지 점검한다. 일반적으로 다음과 같은 상태로 app.js를 설정하고 한다. 





  위와 같이 app.js 한 곳에 다양한 설정들이 있는 것을 리팩토링을 통해 모듈단위로 나눌것이다. 이렇게 할 수 있는 것은 메인 모듈이 의존하는 모듈을 설정하면서 의존모듈을 로딩하면서 의존모듈의 config, run을 수행해 주고 그리고 자신의 모듈을 로딩하기 때문이다. app.js안에 app.framework과 base.framework 모듈의 의존관계를 설정하고 로그를 찍어보자. 먼저 의존관계의 모듈 config와 최종 애플리케이션 모듈인 jandiApp config를 로딩한 후 run을 다시 의존 모듈부터 수행시킨다. 즉, 애플리케이션을 최초 호출할 때 config, run 은 최초 한번 수행됨을 이용해서 각 기능의 초기화를 모듈단위로 나누는 것이다. 

// app.js 의존관계 설정 

angular.module('jandiApp', [

    'base.framework',

    'app.framework',

    ... 중략 ...]);


// config, run의 수행 순서 로그 

=========> Base framework Module config

=========> App framework Module config

=========> jandiApp Module config

=========> Base framework Module run

=========> App framework Module run

=========> jandiApp Module run




2. Config 모듈 생성 


 최초 환경 설정 부분을 모듈로 만들어서 app.framework 모듈에 의존성을 설정해 보자. app.js의 run 메소드에는 api 버전과 서버주소에 대한 기본 환경 설정이 있다. 이것을 config.js라는 별도의 모듈로 빼서 환경설정에 대한 부분을 독립시킨다. 

  - config.js 모듈 파일 생성 : 최초 환경 셋업이 필요한 부분은 config 모듈의 run 메소드에 설정한다. 즉, app.js 있던것을 옮겨옴 

  - config.service.js 서비스 생성 : 해당 서비스를 통해 어디서나 주입을 받아 사용토록 한다. 

$ cd web_client/components/app

$ mkdir config && cd config


// app.js 일부내역 

app.run(function() {

$rootScope.server_address   = configuration.api_address + "inner-api/";

      $rootScope.server_uploaded  = configuration.api_address;

$rootScope.api_version      = configuration.api_version;

$rootScope.configuration    = configuration;  

});


// components/app/config/config.js 내역 

(function() {

  'use strict';


  angular

    .module('app.config', [])

    .constant('configuration', {

      name                : 'local',

      api_address         : 'http://www.jandi.com/',

      api_version         : '2',

      ga_token            : 'UA-222222-1',

      ga_token_global     : 'UA-1111111-1',

      mp_token            : 'abcdefghijklmn',

      base_url            : '.jandi.io',

      base_protocol       : 'http://',

      main_address        : 'http://www.jandi.com/main/#/',

      app_store_address   : 'xxxx',

      play_store_address  : 'yyyy'

    })

    .run(run);


  /* @ngInject */

  function run($rootScope, config) {

    // server address, server api version 

    config.init($rootScope);

  }


})();


// components/app/config/config.service.js 내역 

(function() {

  'use strict';


  angular

    .module('app.config')

    .service('config', config);

    

  /* @ngInject */

  function config(configuration) {

    var self = this;

    this.init = init; 


    function init($rootScope) {

      // TODO : maybe remove next factoring

      // compatibility for current version

      $rootScope.server_address   = configuration.api_address + "api/";

      $rootScope.server_uploaded  = configuration.api_address;

      $rootScope.api_version      = configuration.api_version;

      

      // configuration constant service       

      configuration.server_address  = configuration.api_address + "api/";

      configuration.server_uploaded = configuration.api_address;

      configuration.api_version     = configuration.api_version;


      // config service

      self.server_address  = configuration.api_address + "inner-api/";

      self.server_uploaded = configuration.api_address;

      self.api_version     = configuration.api_version; 

    }

  }

})();


  config.js 에서 app.config 모듈을 run 하면서 config.service.js 를 주입받아 최초에 init()을 하고 있다. 파라미터로 $rootScope를 전달하는데 이는 초기 app.js에서 환경값을 $rootScope에 설정해서 사용하기 때문이다. 향후에는 $rootScope를 통해 접근하는 것을 없애고 config 서비스 통해 필요한 정보를 접근토록 할 예정으로 1차로 기존 버전의 애플리케이션 수정없이 환경설정으로 뺄 수 있는 상태로 리팩토링한다. AngularJS에서 초기 설정 정보를 접근하기 위한 원칙을 다음과 같이 세우면 좋다. 


  - AngularJS의 서비스는 singleton object 이므로 초기 값을 변수로 가지고 있고 접근자 API를 노출한다. 

  - AngularJS 서비스에 $scope, $rootScope를 절대로 주입하지 않는다. 오직 controller와 module.run 에서만 주입을 받아 사용한다. 

  - 따라서 서비스는 서비스를 주입받아 공통정보에 접근해야 한다. 


원칙에 따라 하나씩 모듈로 쪼개고 app.js에는 업무적인 로직에만 집중할 수 있도록 만든다. 향후 components/app/* 모듈은 사용자가 사용하는 웹화면과 관리자가 사용하는 웹화면에 동시에 적용되는 애플리케이션과 관련된 공통 모듈이 들어갈 것이다. 현재까지 모듈의 의존관계 모습은 다음과 같이 app.js의 jandiApp 의존관계는 app.framework 밖에 없다. 하지만 서로 의존관계가 설정되어 있기 때문에 jandiApp 모듈의 AngularJS 모든 컴포넌트는 base.framework과 app.framework의 의존관계 설정 모듈의 컴포넌트를 주입받아 사용할 수 있게 된다. 

// app.js 의존관계 

angular

  .module('jandiApp', [

    'app.framework'

  ]);


// app.framework.js 의존관계

 angular

    .module('app.framework', [

        'base.framework',

        'app.config'

      ])

    .run(run)

    .config(config);


// base.framework.js 의존관계

  angular

    .module('base.framework', [

      'ui.router',

      'ui.bootstrap',

      'gettext'

      'ngCookies',

      'ngResource',

      'ngSanitize',

      'ngAnimate'

    ])


  좀 더 구조적인 관계의 모듈 설정을 통해 구조적인 애플리케이션을 개발하는 첫단추를 꽤었다. 


저작자 표시 비영리 변경 금지

'My Project Diary > Jandi' 카테고리의 다른 글

[Jandi] 애플리케이션 모듈 리팩토링  (0) 2015/01/21
[Jandi] 팀 커뮤니케이션 서비스  (0) 2015/01/07
Posted by peter yun 윤영식
2015/01/07 11:29

Tosslab의 잔디는 팀 그룹간에 원활한 커뮤니케이션을 위한 도구이다. 채팅 및 파일공유를 할 수 있어서 업무 커뮤케이션 툴로 사용하기에 적당하고 모바일, 웹에서 접근할 수 있다. 



잔디의 기술


  잔디는 MEAN Stack 기술을 사용하고 모바일은 네이티브로 개발한다. 업무적인 커뮤니케이션 도구는 사무실에서 웹을 통해 사용할 경우가 많아서 특히 웹에 대한 사용성이 좋아야 한다. 블로그에서는 프론트앤드 영역만을 다루도록 한다. 기존에는 AngularJS v1.2.* 기반으로 되어 있고 개발을 진행함에 따라 웹 애플리케이션의 복잡도가 증가하여서 애플리케이션을 재구성할 필요가 발생하였다. 




모듈단위 애플리케이션 구성


 애플리케이션 복잡도를 단순화 시키고 애플리케이션을 구조화하는 방안이 필요하다. 애플리케이션을 구조화 한다는 것은 거시적인 부분과 미시적인 부분의 조합으로 이루어진다. 먼저 거시적인 부분은 아키텍쳐레벨로 AngularJS의 모듈을 구성하는 것이다. 


 

  AngularJS 모듈은 컴포넌트의 그룹이다. 모듈안에는 다양한 컴포넌트를 가지고 있고 컴포넌트 성격별로 구분해 놓을 필요가 있다. 위의 예에서 가장 기본으로 있어야할 AngularJS에서 제공하는 모듈 묶음과 어느 프로젝트에서나 쓰일만한 모듈을 묶어놓은 공통 모듈이 있을 것이다. 그리고 업무적으로 추상화할 필요가 있는 업무 공통 모듈이 존재하고 업무를 처리하는 업무 모듈식으로 나눌 수 있다. 하위 모듈은 상위 모듈을 참조할 수 없고 상위 모듈만이 하위모듈안의 컴포넌트를 DI(Dependency Injection) 방식으로 사용을 할 수 있다. 




제너레이터를 통한 애플리케이션 구성


 기존의 애플리케이션을 보기하면서 다시 재구성하기 위해 무엇부터 시작을 해야할까? 


  - Yeoman Generator를 선정한다. generator-angular-fullstack을 사용할 예정이다. 

  - 자바스크립트 코딩 스타일은 구글의 자바스크립트 스타일 가이드를 따른다. 

  - AngularJS의 코딩 스타일은 존파파의 AngularJS 스타일 가이드를 따른다.


  generator-angular-fullstack의 템플릿을 존파파의 가이드에 따라 변경한 프로젝트를 만들어 본다. 불필요한 예제는 제거하고 몇가지 영역의 템플릿만을 취할 것이다. 먼저 generator-angular-fullstackgenerator-ng-component를 각각 git clone 하고 명칭을 generator-jdi, generator-jdi-component라고 바꾸고 내부의 .git폴더를 제거한 후 각 템플릿의 내용을 파파죤스 가이드에 따라서 수정을 한다. 

$ git clone https://github.com/DaftMonk/generator-angular-fullstack.git

$ git clone https://github.com/DaftMonk/generator-ng-component.git


$ mv generator-angular-fullstack generator-jdi

$ mv generator-ng-component generator-jdi-component


$ cd generator-jdi && rm -rf .git

$ cd generator-jdi-component && rm -rf .git


 파파죤스 가이드에 따라 generator-jdi-component/templates 폴더 밑의 모든 앵규러 컴포넌트를 다음과 같은 형식으로 수정한다. 

   + IIFE : Immediately Invoke Function Expression

   + 앵귤러 모듈 변수를 만들지 않음 

   + 컴포넌트의 펑션을 밖으로 뺌

   + DI 하는 부분은 ng-annotation을 이용함으로 주입받는 펑션위에 /* @ngInject */ 를 둚

(function() { 

  'use strict';


  angular

    .module('<%= scriptAppName %>')

    .controller('<%= classedName %>Ctrl', <%= classedName %>Ctrl);


  /* @ngInject */

  function <%= classedName %>Ctrl($scope) {

         

  }

})();


 수정한 내역에 대해 테스트는 다음과 같이 진행을 하면 된다.  먼저 테스트용 test 폴더를 하나 만든다. 테스트 폴더 밑에 node_modules 폴더를 만들고 밑으로 generator-jdi와 generator-jdi-component 에 대해 심볼릭 링크를 건다. 각 generator-* 폴더로 들어가 npm install을 해준다. 이제는 test밑에서 "yo jdi Jandi" 명령을 치면 애플리케이션 생성 프롬프트를 묻게 된다. 애플리케이션 템플릿은 generator-jdi/app/templates 밑에 존재하고 여기에 있는 파일도 파파죤스 스타일 가이드에 따라 수정을 해준다. 

$ mkdir test && cd test

$ mkdir node_modules && cd node_modules 


$ ln -s <fullPath>/generator-jdi  generator-jdi

$ ln -s <fullPath>/generator-jdi-component generator-jdi-component


// 둘은 같은 디렉토리에 있어야 함 

$ cd <fullPath>/generator-jdi-component && npm install

$ cd <fullPath>/generator-jdi && npm install 


$ cd test 

$ yo jdi Jandi


  각 수정한 generator-jdi, generator-jdi-component는 링크를 참조한다. 이제는 누구나 사용할 수 있도록 npm repository에 등록을 한다. npm publish 로 package.json 파일에 등록된 내역을 기반으로 배포가 된다. 따라서 clone한 generator의 버전을 따르지 않고 최초 0.0.1 버전으로 수정해 배포한다. 

$ cd generator-jdi-component 

$ npm publish

+ generator-jdi-component@0.0.1


$ cd generator-jdi

$ npm publish

+ generator-jdi@0.0.1


 이제 글로벌로 generator-jdi만을 설치해서 어디서나 "yo jdi <App명칭>" 명령을 수행해 최초 애플리케이션 골격을 만들 수 있다. 

$ npm install -g generator-jdi

$ mkdir web_tiger && cd web_tiger

$ yo jdi Jandi



저작자 표시 비영리 변경 금지

'My Project Diary > Jandi' 카테고리의 다른 글

[Jandi] 애플리케이션 모듈 리팩토링  (0) 2015/01/21
[Jandi] 팀 커뮤니케이션 서비스  (0) 2015/01/07
Posted by peter yun 윤영식
2015/01/05 20:25

AngularJS v1.3에서 많은 기능들이 새롭게 추가되었지만 우선 성능에 영향을 미쳤던 부분을 해결하는 방법을 알아보자. 



양방향 데이터 바인딩 이해


  AngularJS의 특징중 양방향 데이터 바인딩은 reactive programming의 구현체라고 할 수 있다. Meteor의 Blaze, Facebook의 React도 같은 기능을 제공한다. 이들은 HTML과 JS사이에 특별한 코드의 등록없시도 HTML->JS / HTML <- JS 양방향으로 데이터 갱신이 가능하다. AngularJS에서 양뱡향 데이터 바인딩의 중요 매개체는 $scope이고 해당 객체 내부에는 데이터의 변경을 감시하는 $watch가 있는데, 모든 개별 데이터마다 $watch가 등록된다. 하기와 같이 $scope.name에 대한 expression도 watcher(감시자, 즉 $watch)가 등록된다. (예제)

<span> Hi {{name}}</span>


  name이 $scope에 속성으로 선언되어 HTML에서 사용을 하면(사용하지 않는 속성은 등록되지 않음) AngularJS는 $watch를 모두 등록하고 $scope 속성 하나라도 변경이 되면 Duty-Checking방식으로 AngluarJS Context안의 $digest 루프를 돌면서 매칭되는 $scope의 속성을 사용하는 DOM 내역을 동적으로 변경한다. 여기서 생각해 볼것은 만일 화면에 뿌려지는 $scope의 속성값이 100개이고(테이블이나 리스트 같은 경우 ng-repeat을 사용한다면) 최초 화면이 뿌려진 후 단 1개만이 사용자의 액션이나 실시간 Push를 통해 변경되는 것이어도 100의 $watch를 $digest루프를 돌며 변경을 체크하게 된다. 100개가 아니라 10만개라면 어떻게 될까? 분명 성능상에 영향을 미칠것이다. $watch, $digest에 대한 사항은 블로그를 읽어보자




Watch Expressions 성능 개선


  one-time expression은 최초 digest 루프를 한번 타고 값이 설정되면 그 다음에 다시 digest 루프를 타지 않게 해주는 것이다. 따라서 최초 동적 바인딩이 이루어진 후에는 $watch에서 제거되어 digest 루프를 타지 않도록 함으로 성능상의 이점을 누릴 수 있다. 사용방법은 간단히 $scope의 속성앞에 :: 를 하기와 같이 표기한다. (예제)

<span> Hi {{::name}}</span>


  이제 최초에 한번 데이터를 바인딩한 후에 동적 변경이 필요없는 HTML안의 AngularJS Expression들에 One-Time-Binding을 사용하자.




<참조> 


  - Explorering Angular v1.3 - One-Time-Binding

  - $watch, $digest는 무엇인가?

저작자 표시 비영리 변경 금지

'AngularJS > Exploring v1.3' 카테고리의 다른 글

[AngularJS] v1.3 - One-time bindings  (0) 2015/01/05
Posted by peter yun 윤영식
2015/01/05 12:32

베이글은 그룹 컨텐츠 공유 서비스이다. 그룹 관리자는 멀티미디어 컨텐츠 및 설문 조사를 위한 다양한 내용을 개제할 수 있고 멤버는 이에 대한 답변을 하거나 댓글은 단다. 페이스북과 유사한 UI이지만 퍼블릭 SNS가 아닌 버티컬 SNS를 지향한다. 





베이글의 탄생


  이전 StudyGPS의 서비스 v1.5를 v2.0으로 개편하면서 서비스이름을 새로 공모했고 최종적으로 베이글을 선택했다. 미국에서 프로젝트를 하면서 금요일 아침마다 먹었던 베이글이 생각나서 개발팀 이름도 MondayBread로 한 마당에 베이글이 어떠냐는 의견을 내놓았는데 잘 매칭되어 채택이 되었다. 베이글은 교육을 타케팅하는 서비스이다. 주로 선생님이 그룹을 만들고 학생이 답변을 다는 형태이다. 선생님은 학생들에게 학업과 관련한 컨텐츠를 제공하면서 이에대한 설문 조사를 수행할 수 있다. 컨텐츠는 파일 첨부, 이미지, 동영상등을 게재할 수 있고 설문형식은 주관식, 객관식등의 조사와 댓글을 통해 의견을 들을 수 있다. 


  보수적인 교육시스템에서는 자유로운 퍼블릭 SNS로 쌍방향 소통 보다는 단방향의 문제를 내는 사람과 문제를 푸는 사람을 구분하여 관심분야의 그룹을 운영할 수 있도록 하는데 목적이 있다. 




베이글의 기술


  스타트업에서 인기를 누리고 있는 MEAN (MongoDB ExpressJS AngularJS Node.js) 스택을 사용한다. 모바일은 하이브리드 앱방식으로 개발을 진행하고 이를 위한 프레임워크로 Ionic을 사용한다. 그외 Sass트위터 부트스트랩도 함께 사용한다. 하이브리드 앱 개발에서 중요한 체크 포인트는 다음과 같다. 


  1) 네이티브 UX에 근접한 경험을 줄 수 있는가?

  2) 네이티브 UI 컴포넌트와 같이 잘 정의된 레이아웃이나 컴포넌트가 있는가?

  3) HTML과 Javascript의 분리해서 네이티브처럼 개발을 진행할 수 있는가?


  1)번을 위한 약간 2주간 AppGyver를 사용해 보았으나 제약 사항이 많고 특히 MPA(Multi-Page Application)으로 WebView를 정말 Multi개만큼 생성해서 운영해야 제대로된 네이티브 기능을 사용할 수 있다. 이것의 단점은 모든 뷰가 하나의 AngularJS SPA가 되버린다는 것이다.  즉, 화면별로 WebView가 개별적으로 운영되면서 나타나는 현상이다. 하지만 steroids와 scanner 앱을 통해 편한 개발환경을 제공하고 있다. 따라서 아주 간단한 App을 만든다면 AppGyver도 쓸만한 프레임워크이자 플랫폼라 생각한다. AppGyver의 supersonic 하이브리드 프레임워크도 결국 Ionic을 내부적으로 사용하고 있고 SPA 방식으로 개발하면서 네이티브 수준의 UI와 UX를 선사하는 Ionic 프레임워크를 최종 선택하게 되었다. 올해(2015)초에는 정식 v1.0이 릴리즈 될 예정이고 ionic 내부에 angular, angular-sanitize, angular-animation, ui-router를 의존관계로 가지고 있고 AngluarJS v1.3.6 최신버전을 사용하고 있다. 


 2)번은 Sass로 일정부분 디자인을 하고 트위터 부트스트랩과 같은 UI 프레임워크를 사용하면 되고 3)번은 reactive programming을 할 수 있는 AngularJS의 양방향 데이터 바인딩을 사용하면 HTML과 JS파일을 분리해 개발을 할 수 있다.  


앞으로 개발하면서 느꼈던 점과 기술적인 이슈등을 회고식으로 적어볼 예정이다. 


  

저작자 표시 비영리 변경 금지

'My Project Diary > Bagle' 카테고리의 다른 글

[Bagle] 베이글이란?  (0) 2015/01/05
Posted by peter yun 윤영식

티스토리 툴바