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

Publication

Category

Recent Post

2015. 10. 22. 10:41 AngularJS



본 서적은 자바스크립트와 앵귤러 프레임워크를 프로젝트에 도입해 보려는 개발자 또는 프로토타입을 해보고 싶은 개발자 또는 사용해 본 경험이 있는 개발자를 대상으로 한다. 앵귤러에 대해 처음 공부하는 분에게는 다소 어려울 수 있으므로 기초서적을 권장드린다. 책 제목처럼 3장이후 부터 실전 프로젝트 실습을 위한 상세 소스를 GitHub에서 제공한다. 1~2장은 개념 정리이므로 읽고 나중에 참조하는 장으로 사용한다. 참고로 2장은 실습이 없이 개념을 설명하는 장이기에 소스를 제공하지 않고 있다. (소스의 Git Branch는 장이 끝나는 시점에 언급하고 있다. 먼저 전체 소스를 보고 싶다면 GitHub 내용을 참조하자)








출판의 여정 


8개월의 원고작성, 3개월의 편집기간을 거쳐 드디어 책이 출간되었다. 책을 통해 개발자들과 공유하자는 의기투합은 2013년 겨울로 거슬러 올라간다. 이강훈님을 통해 알게된 이규원님, 김충섭님, 김대권님, 박유진님, 구교준님과 함께 MEAN 스택을 기획했었다. 그 당시 미국에 있었던 지라 구글 행아웃을 통해 주말마다 화상미팅을 하며 깃헙과 페이스북을 통해 서로의 의견과 결과물을 공유했다. 2014년 봄 귀국후 함께 오프라인에서 헤커톤도 하면서 책의 샘플을 만들며 진행했지만 각자의 일정으로 인해 MEAN 스택 집필을 흐지부지 되어갔다. 2014년 7월쯤 결단을 내리고 이렇게 진행하면 끝나지 않겠다 싶어서 다음 기회를 기약하였고, 홀로 책을 쓰기로 결심했다. 


2014년 8월 이강훈님 회사인 스터디지피에서(https://bagle.io)의 서비스를 개발하면서 미국 플젝에서 얻은 AngularJS 경험과 개념정리가 덜 된 부분을 하나하나 집어가며 집필을 시작했다. 처음에는 한 페이지를 나가는데 하루의 시간이 걸리더니 조금씩 속도가 붙으면서 한달만에 100p 가량을 썼다. 하지만 다시 가을 미국 프로젝트로 2달간 집필 중단 후 한국에 돌아와 마음을 다잡고 12년전 내 책을 출판해 보자는 꿈을 다시한번 상기했다. 위키북스의 박찬규 대표님도 은근히 압력을 넣어주시며 언제쯤 나올까요 물어볼때마다 곧 나올겁니다 대답하곤 하루 1~2시간씩 짬을 내어 집필을 계속했다. 2015년 3월 집필을 완료하고 출판사에 전달했지만 피드백으로 날아온 것은 맞춤법과 문장 난해함에 대한 엄청난 지적질의 빨간줄이었다. 


한달간 주말마다 빨간 선생님과 싸움하며 "그래 글쓰는 것도 배우는 거다"라고 생각하고 나의 국어실력을 한탄하며 글을 풀어서 이야기식으로 고쳐나갔다. 사실 블로그를 쓰다보니 블릿(점, 점으로 요약한 내용)으로 내용을 요약해 표현하다 보니 책도 그렇게 썼드랬다. 블릿 내용을 다 풀어쓰는 것만도 한달. 다시 피드백받아 또 고치고 피드백받아 또 고치고, "아 무한루프의 피드백". 점점 스트레스와 화가 살짝 났다. 인생 목표 10가지중 1가지가 1년에 책한권씩 내자였던 것이 여지없이 깨지는 순간이었다. 이렇게 하다가는 2년에 한권내는 것도 힘들겠다 싶었다. 하지만 일에는 끝이 있는 법. 5월초 거의 마무리 피드백을 보내고, 책 추천사를 받고 인덱스를 보내고, 몇가지 피드백을 마무리하며 3개월의 수정작업은 6월 5일 마무리되었고, 예약 판매가 모든 온라인 서점에서 시작되었다. 그렇게 나온 것이 "실전 프로젝트로 배우는 AngularJS" 이다. 


본 서적은 AngularJS가 하도 유행이라 하여 한번쯤은 기초서적을 구매하거나 빌려서 본적이 있고, 온라인 튜토리얼을 통해 프로토타입핑을 해보았지만 당췌 AngularJS로 서비스를 어떻게 만들어야 할지 모르는 개발자를 위한 책이다. "나도 내가 원하는 서비스 뚝딱 만들어 보고 싶어 근데 어떻게 시작해야는 거야?"라고 생각하는 모든 개발자를 위한 책이다. AngularJS는 생태계를 가지고 있고 인식의 전환을 해야하는 새로운 용어들이 존재한다. 


처음 1장에서는 간단한 ToDo 서비스를 만들면서 주변의 생태계 도구와 개념을 이해하고 2장에서는 AngularJS의 장점들과 그중에 지시자(Directive)에 대해 좀 더 심도있게 설명을 했다. 3장, 4장에서 서비스를 바로 만들 줄 알았다면 오산이다. 이제 서비스를 만들 준비운동단계이다. 먼저 요건정의를 하고 이에 맞는 코딩 컨벤션 부터 AngularJS를 이용한 SPA 개발시 준비할 것들을 프론트앤드 아키텍처로 접근해 보았다. 5장에서 이제 좀 개발들어가려 했더니 그래도 요즘 많이 사용하는 NodeJS, MongoDB는 알고가자는 취지에서 개념과 실습코드를 넣었다. 1장~5장이 준비운동과 스타트 단계였다면 6장, 7장은 엄청난 스피도로 골인점을 향해가는 단계이다. 올초 2개월간 TossLab의 JANDI(http://www.jandi.com)에서 AngularJS에 대한 컨설팅 경험을 적용한 장이다. 





목차


▣ 01장: 단일 페이지 애플리케이션 개발 준비
1-1. 개발 도구 설치 
   - 깃 설치 
   - 노드 설치 
   - 요맨 설치 
   - 서브라임 텍스트 편집기 설치 

1-2. 단일 페이지 애플리케이션 생성 
   - yo generator 선택과 설치 
   - Yo를 이용한 ToDo 애플리케이션 생성 
1-3. 애플리케이션 컴포넌트 생성 
   - 앵귤러를 위한 index.html 설정 이해하기 
   - yo를 이용한 앵귤러 컨트롤러 추가 
   - bower를 이용한 앵귤러 지시자 추가 
1-4. 애플리케이션 테스트 및 빌드 
   - grunt를 이용한 테스트 
   - grunt를 이용한 배포 
정리 

▣ 02장: AngularJS 프레임워크 이해
2-1. MV* 프레임워크 
2-2. 양방향 데이터 바인딩 
   - 스코프 내부와 상속 관계  
   - MyToDo 애플리케이션에서 양방향 데이터 바인딩 
   - 스코프 생명 주기(Life Cycle) 
   - 그 외 $scope 객체 메서드 
2-3. 의존성 주입(DI, Dependency Injection) 
2-4. 클라이언트 템플릿 
2-5. 지시자(Directive) 
   - 지시자가 DOM에 적용되는 순서 
   - 지시자 정의 
   - 지시자의 스코프 객체의 범위 종류 
   - Template, TemplateUrl, TemplateCache, replace와 ng-template 사용 
   - compile, link의 $watch 등록을 이용한 양방향 데이터 바인딩 
   - controller, require와 link 네 번째 파라미터와의 관계 
   - transclude, ng-transclude 사용 
2-6. 테스트 프레임워크(단위, E2E) 
   - 카르마 기반 단위 테스트 
   - 프로트랙터 기반 E2E 테스트 
정리 

▣ 03장: 싱글 페이지 애플리케이션 기획및 생성
3-1. 애플리케이션 기획
   - 메인 페이지 
   - 그룹 정보 페이지 
   - 그룹 활동 페이지 
   - 설문 생성 페이지 
3-2. 애플리케이션 제너레이터 설계 
   - 애플리케이션의 폴더 구조 전략 
   - 애플리케이션 제너레이터 선정 
   - 앵귤러 코드 스타일 전략 
   - 스타일 가이드에 따른 제너레이터 템플릿 수정 방법 
   - IE8 지원을 위한 index.html 설정 
3-3. SPA 생성 
   - 애플리케이션의 모듈 구성 
   - 라우팅 설정 방식 
3-4. 단위 업무를 위한 앵귤러 컴포넌트 조합 
   - $resource를 통한 REST 모델 사용 
   - promise와 $q Async 호출에 대한 이해 
정리

▣ 04장: 애플리케이션을 위한 공통 프레임워크 개발
4-1. 공통 프레임워크 모듈 개발 
   - 다국어 처리 
   - 메시지 처리 
   - 팝업 메시지창 지시자 
   - HTTP 에러 처리 
   - 사용자 정의 Bower 컴포넌트 등록 
   - 로컬 저장소 서비스 
   - 유틸리티 지시자 
4-2. 로그인 화면 개발 
   - 트위터 부트스트랩 기반의 화면 디자인 및 폰트 사용 
   - 폼 유효성(Form Validation) 검사 
   - 인증을 위한 토큰과 쿠키 
4-3. OAuth를 이용한 인증 처리 
   - 백엔드에서 Passport 모듈을 이용한 인증 처리 
   - 페이스북 인증 처리 
   - 크롬 브라우저 개발자 도구를 이용한 클라이언트 디버깅 
   - 노드 인스팩터를 이용한 서버 디버깅 
정리

▣ 05장: 메인 페이지 개발
5-1. 백엔드 API 개발 
   - REST API 별 서버 모듈 조합 
   - 노드 모듈의 exports 이해 
   - 몽고디비와 몽구스 이해 
   - 서버 모델 개발 
   - 그룹 REST API 개발 
   - 포스트맨을 이용한 REST API 검증 
   - 백엔드 단위 테스트 수행 
5-2. 메인 화면 개발 
   - 공통 컴포넌트 재구성 
   - 메인 화면 레이아웃 개발 
   - 그룹 생성 
5-3. 그룹 목록 및 정보 표현 
정리 

▣ 06장: 그룹 페이지 개발
6-1. 그룹 정보 페이지 
   - 그룹 상세 정보 조회 
   - 그룹 프로필 이미지 변경 
   - 그룹 가입, 탈퇴 
6-2. 그룹 활동 페이지 
   - 그룹 활동 화면 레이아웃 개발 
   - 그룹 멤버 목록 표현 
6-3. 설문 카드 생성 
   - 설문 카드 생성 
   - 카드 지시자 개발 
6-4. 설문 종류별 카드 표현 
6-5. 설문 응답 및 결과 표현 
정리

▣ 07장: 실시간 반응 개발
7-1. Socket.IO 기반 실시간 연동 
   - 노드 기반 백엔드 Socket.IO 
   - AngularJS 기반 프런트엔드 Socket.IO 
   - 상단 알림 메뉴 추가 
7-2. 카드 목록 UX 개선 
   - 카드에 동영상 추가 
   - 무한 스크롤 적용 
   - 애니메이션 효과 적용 
7-3. AngularJS 성능 옵션 
   - 일회 바인딩 
   - ngModelOptions 지시자 
   - 디버깅 정보 비활성화 
   - $applyAsync 적용 

정리




구매


예스24 온라인 서점


알라딘 온라인 서점


인터파크 온라인 서점


교보문고 온라인 서점


G마켓 온라인 서점


현재는 예약 판매로 10% 싸게 구매 할 수 있다. 6월 17~19일간 배송을 시작한다. 당초 높은 가격이 책정되었지만 위키북스 대표님에게 가격이 높아 개발자에게 부담이 될 것 같다하였더니 파격적인(?) 가격에 판매를 시작해 주셨다. 지금까지 독자로 책을 사보면서 철자하나 틀리면 왠지 기분이 나쁘고 지적을 해주고 싶었는데 이제부터는 너그러이 용서해 줄것 같다. 정말 많은 공력과 시간이 투여되는 시간이었다. 하지만 새로운 경험을 하게 되었고 이렇게 해서 책 한권 한권이 출판된다는 생각을 하니 한권의 책을 사도 감사히 볼 마음가짐이 생긴다.  


이번달 중으로 출판사의 양해를 얻어 1장과 2장은 블로그에 공개하려 한다. 2장은 AngularJS v1.* 이 계속 사용되는 한 유용한 레퍼런스가 되리라 생각한다. 이렇게 생애 첫 책 출판을 자축하며... 내년에는 "Data Visualization using D3.js" 이고, 여기에 ReactJS 또는 AngularJS v2.* 와 Meteor를 접목한 경험을 출판할 계획이다. 글쓰기도 가끔은 중독이다. 자전거 처럼 잘 타지는 못하지만 타고 있는 동안은 자유다. 나를 표현하고 느낄 수 있는 시간이랄까~~~




소스 


책의 소스는 모두 깃헙에 있습니다. 책 챕터마도 브랜치에 대한 정보가 담겨 있습니다. 


책 소스를 위한 깃헙 그룹 : https://github.com/AngularJS-SPA-Development



posted by 윤영식
2014. 5. 28. 21:20 AngularJS/Start MEAN Stack

다국어 처리를 Angular.js 기반인 클라이언트단에서 처리하는 방법에 대해 알아본다. angular-translateangular-gettext 두가지가 존재하는데 여기서는 angular-gettext를 살펴보도록 한다 



준비사항

  - 먼저 poedit을 설치한다. 언어 번역을 일괄적으로 관리할 수 있는 툴이다. 기본 영문에서 한글 번역내역을 입력하여 언어별로 .po 파일을 관리한다 

  - angular-gettext 모듈을 사용한다. --save 옵션넣어서 bower.json 업데이트 한다. 인스톨 가이드를 참조한다 

$ bower install angular-gettext --save

  - grunt-angular-gettext 를 설치한다. --save-dev 옵션. 해당 모듈은 .po파일을 생성하거나 생성된 내용을 angular 자바스크립트로 변환을 담당한다 

$ npm install grunt-angular-gettext --save-dev



Grunt Config 수정

  - grunt-angular-gettext를 통하여 poedit에서 읽을 수 있는 원본 파일(.pot)을 생성하고, 원본에서 다른 언어의 번역을 넣은 파일(.po)을 읽어서 angular 형식의 자바스크립트 파일을 생성한다. 

  - Gruntfile.js 첨부내역

    + nggettext_extract : 다국어 지원이 필요한 .html을 읽어서 원본 origin_template.pot 파일 생성 위치와 파일명 지정

    + nggettext_compile : 다국어 .po 파일을 읽어서 angular 형식의 파일을 만들 위치와 파일명 지정. 

                                   별도의 모듈로 gettext_translation을 적용한다 

    // Translation for multi-lang

    nggettext_extract: {

      pot: {

        files: {

          'app/translation/po/origin_template.pot': [

            'app/index.html',

            'app/views/**/*.html',

            'app/domain/**/*.html'

          ]

        }

      },

    },

    nggettext_compile: {

      all: {

        options: {

          module: 'gettext_translation'

        },

        files: {

          'app/translation/translation.js': ['app/translation/po/*.po']

        }

      },

    }, 



다국어 지원 자바스크립트 생성 작업

  - html 수정 : 다국어 지원이 필요한 부분에 translate 애트리뷰트를 넣는다. 한줄은 <span></span> 태그를 사용한다

    <form name="signupForm" novalidate>

        <div class="session-signup-main-subject">

            <span translate>Create an Account</span>

        </div>

        <div class="session-signup-name-subject">

            <span translate>Name</span> 

            <span style="color:red" ng-show="focusName" translate> @Please input your full name.</span>

        </div>

        <input type="text" name="user_name" placeholder="{{'Enter Full Name'|translate}}" class="session-signup-name-input" ng-model="user.name" required sg-focus="focusName">

        <div class="session-signup-email-subject">

            <span translate>Email</span> 

            <span style="color:red" ng-show="focusEmail" translate> @Please input your email.</span>

        </div>

        <input type="email" name="user_email" placeholder="{{'Enter Email'|translate}}" class="session-signup-email-input" ng-model="user.email" required sg-focus="focusEmail">

        <div class="session-signup-password-subject">

            <span translate>Password</span> 

            <span style="color:red" ng-show="focusPassword" translate> @Please input your password.</span>

        </div>

        <input type="password" name="user_password" placeholder="{{'Enter Password'|translate}}" class="session-signup-password-input" ng-model="user.password" required sg-focus="focusPassword">

        <div class="session-signup-have">

            <span translate>Have an account?</span>

        </div>

        <a ui-sref="signin" class="session-signup-login-btn">

            <span translate>Log-in</span>

        </a>

        <button class="session-signup-create-btn" ng-click="signup(signupForm)">

            <div class="session-signup-create-btn-text">

                <span translate>Create New Account</span>

            </div>

        </button>

    <form> 


  - grunt를 통해서 html의 translate 을 해석하여 origin_template.pot파일을 생성한다

$ grunt nggettext_extract


  - origin_template.pot 파일을 poedit로 import 한다. 한글을 언어로 설정하여 번역을 한후, ko_KR.po 파일을 생성한다.

    + 새 번역 만들기 클릭 후 origin_template.pot파일 선택한 후 번역 언어 선택함  

    

    + 번역을 입력하고 "다른 이름으로 저장하기..."를 선택하여 ko_KR.po 파일을 만든다 

    


  - 번역된 ko_KR.po 파일 내역을 translate.js 파일로 만들기 

$ grunt nggettext_compile 


// ko_KR.po 파일 내역

msgid ""

msgstr ""

"Project-Id-Version: \n"

"POT-Creation-Date: \n"

"PO-Revision-Date: 2014-05-27 16:20+0900\n"

"Last-Translator: \n"

"Language-Team: \n"

"Language: ko_KR\n"

"MIME-Version: 1.0\n"

"Content-Type: text/plain; charset=UTF-8\n"

"Content-Transfer-Encoding: 8bit\n"

"X-Generator: Poedit 1.6.5\n"

"X-Poedit-Basepath: .\n"

"Plural-Forms: nplurals=1; plural=0;\n"


#: app/domain/session/signup/signup.html

msgid "@Please input your email."

msgstr "@이메일주소를 입력해 주세요."


#: app/domain/session/signup/signup.html

msgid "@Please input your full name."

msgstr "@전체 이름을 입력해 주세요."


#: app/domain/session/signup/signup.html

msgid "@Please input your password."

msgstr "@전체 패스워드를 입력해 주세요."


#: app/domain/session/signup/signup.html

msgid "Create New Account"

msgstr "신규 계정 생성"


#: app/domain/session/signup/signup.html

msgid "Create an Account"

msgstr "계정 생성"


#: app/domain/session/signup/signup.html

msgid "Email"

msgstr "이메일"


#: app/domain/session/signup/signup.html

msgid "Enter Email"

msgstr "이메일 입력"


#: app/domain/session/signup/signup.html

msgid "Enter Full Name"

msgstr "이름 입력"


#: app/domain/session/signup/signup.html

msgid "Enter Password"

msgstr "패스워드 입력"


#: app/domain/session/signup/signup.html

msgid "Have an account?"

msgstr "계정이 있나요?"


#: app/domain/session/signup/signup.html

msgid "Log-in"

msgstr "로그인"


#: app/domain/session/signup/signup.html

msgid "Name"

msgstr "이름"


#: app/domain/session/signup/signup.html

msgid "Password"

msgstr "패스워드"



// translate.js 파일로 ko_KR.po 파일을 기반으로 생성된 내역 

angular.module('gettext_translation').run(['gettextCatalog', function (gettextCatalog) {

/* jshint -W100 */

    gettextCatalog.setStrings('ko_KR', {"@Please input your email.":"@이메일주소를 입력해 주세요.","@Please input your full name.":"@전체 이름을 입력해 주세요.","@Please input your password.":"@전체 패스워드를 입력해 주세요.","Create New Account":"신규 계정 생성","Create an Account":"계정 생성","Email":"이메일","Enter Email":"이메일 입력","Enter Full Name":"이름 입력","Enter Password":"패스워드 입력","Have an account?":"계정이 있나요?","Log-in":"로그인","Name":"이름","Password":"패스워드"});

/* jshint +W100 */

}]);


  - 별도의 모듈 gettext_translation을 생성하고 index.html에 파일들을 추가한다  

// translationModule.js 을 생성

angular.module('gettext_translation', []); 


// index.html에 <script>도 추가한다 

<script src="bower_components/angular-gettext/dist/angular-gettext.js"></script>

<script src="translation/translationModule.js"></script>

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


  - 메인 애플리케이션인 App.js 에 gettext와 gettext_translation모듈을 추가하고, run 메소드에 언어 설정을 한다

var App = angular.module('studyGpsApp', [

  'ngCookies',

  'ngResource',

  'ngSanitize',

  'ui.router',

  'ui.bootstrap',

  'restangular',

  'gettext',

  'gettext_translation'

]);


App.run(function ($rootScope, gettextCatalog) {

    //translate for multi-lang

    $rootScope.setLang = function(lang, isDebug) {

      if(lang) {

        gettextCatalog.currentLanguage = lang;

      } else {

        gettextCatalog.currentLanguage = 'ko_KR';

      }

      gettextCatalog.debug = isDebug;

    }

    // init

    $rootScope.setLang('ko_KR', true);


  - 결과화면

  



지속적인 번역 파일 만들기 

  - 만일 화면이 추가되어 신규 번역이 필요할 경우 다음과 같이 수행을 하면 추가된 부분만 따로 설정 할 수 있다. 

  - poedit을 사용하게 되면 html 마다 반복적으로 사용되는 용어의 중복을 unique하게 관리 할 수 있고, 별도의 .js 코딩을 할 필요가 없다.

  - 많은 언어를 관리해야 한다면 poedit을 통해 관리 편의성을 얻을 수 있다

// 먼저 origin_template.pot 파일을 생성한다 

$ grunt nggettext_extract


// poedit 에서 ko_KR.po 파일을 open 한 후에 다음의 메뉴를 선택하고 origin_template.pot를 선택하면 새롭게 추가된 번역할 내역이 자동으로 ko_KR.po 파일에 추가되어 나온다 

// 이제 <언어별>.po 파일들을 translate.js 파일로 만든다. 

$ grunt nggetext_compile 


* angular-translate 모듈이 있는데 해당 모듈은 html 화면에 기본 랭귀지가 아닌 KEY값을 넣어서 바인딩해야 하는 번거로움이 존재하고, poedit와 같은 도구를 통한 번역의 편리성을 제공하지 않는다. 



Gulp를 사용할 때

  - gulp용의 angular-gettext를 설치한다. 물론 gulp도 설치한다. 

$ npm install gulp 

$ npm install gulp-angular-gettext

  

  - gulpfile.js 의 설정 내역

    + gulp-rename 플러그인을 이용해서 파일명을 바꾼다. 

    + translation 할때는 format을 javascript로 한다. 포맷은 json과 javascript가 있다.

var rename = require('gulp-rename');

var gettext = require('gulp-angular-gettext');


gulp.task('lang', ['extract', 'translation']);

gulp.task('extract', function() {

  return gulp.src(['./www/app/**/*.html'])

             .pipe(gettext.extract('origin_template.pot', {}))

             .pipe(gulp.dest('./www/lib/common/translation/po/'));

});


gulp.task('translation', function() {

  return gulp.src('./www/lib/common/translation/po/*.po')

             .pipe(gettext.compile({

                module: 'mb.translation',

                format: 'javascript'

             }))

             .pipe(rename('lib/common/translation/translation.js'))

             .pipe(gulp.dest('./www'));

});




<참조>

  - AngularJS Multi-Language Support

  - AngularJS GetText Homepage

  - Grunt Angular GetText GitHub

  - angular-translate Hompage


posted by 윤영식
2014. 1. 26. 07:50 AngularJS/Start MEAN Stack

yeoman은 자바스크립트 기반의 프론트앤드 개발을 도와주는 자동화 툴이다. 자바에서 요즘 많이 사용되는 Maven과 유사하다. 



1. 사용이유

  서비스 개발의 규모가 커지고 자바스크립트의 각 모듈별의 버전 의존성을 관리하려면 어떻게 해야 할까? 그리고 필요한 자바스크립트 모듈을 다운로드하기 위하여 각 사이트를 방문하여 다운로드 해야할까? 기본적인 코드 골격과 코딩 컨벤션은 최초에 어떻게 해야할까? 개발하고 나서 테스트 및 빌드 자동화는 어떻게 해야할까? 이러한 의문에 대한 해답을 주는 것이 Yeoman이다.

  - 스케폴딩 생성 : 기본적인 코드 골격을 만들어 주고 이후 추가되는 앵귤러 코드는 명령을 통해 생성한다 

  - 라이브러리 의존성 관리 : 프론트앤드에서 사용하는 다양한 jquery 모듈과 angular.js 모듈의 설치 및 버전 관리를 한다 

  - 테스트 및 빌드 자동화 : 테스트 코드를 작성하였다면 테스트 수행 및 코드 압축과 문법오류 검사 그리고 배포파일의 생성을 한다 

  - 사전 점검 : 프론트단의 코드를 Node.js기반 수행하여 브라우져에서 개발한 화면을 사전에 테스트 점검 가능하다



2. 설치하기  

  설치는 의외로 간단하다. 사전 준비로 Node.js를 설치 하였다면 NPM (Node Package Manager)을 통해 설치한다. yo, bower, grunt 의 특징은 자바스크립트로 개발하여 node.js기반위애 구동하는 도구이다 

// 1) yo 설치 

$ npm install -g yo


// 2) bower 설치 

$ npm install -g bower


// 3) grunt 설치 

$ npm install -g grunt-cli

  * http://yeoman.io, http://bower.iohttp://gruntjs.com 에서 설치관련 자세한 사항을 참조한다. 



3. 주요 기능 

  yeoman은 크게 3가지 기능으로 구분된다. 각 기능의 구분이 명확하고 사용하는 목적이 틀리기 때문에 잘 알아 두기 바란다. 기본적으로 yo를 yeoman팀에서 자체적으로 만들었고, bower와 grunt는 이미 존재하였던 도구로써 yeoman이라는 이름으로 통합한 것이다. 따라서 bower와 grunt를 별개의 독립적인 도구로 사용할 수도 있다


  yo 

  - 프론트앤드 개발을 위한 기본 구조를 만들어 준다. yeoman에서는 스켈폴딩 코드를 만들어 준다고 말한다 

  - 스케폴딩 파일을 생성하려면 목적에 맞는 제너레이터를 사전에 설치해야 한다.

    1) 제너레이터 명칭 구성 : generator-<UserDefine> 로서 UserDefine 명칭을 정한다. 예) generator-angular

    2) npm 을통하여 글로벌 설치한다 

    3) UserDeinfe 명칭이 angular 라면 yo 명령 다음에 제너레이터의 구분을 위하여 항시 해당 UserDefine 명령이 온다 

        yo angular <Subject>  또는 yo angular:<SubCommand>  <Subject>

    4) yo angular <Subject> 를 통해 초기 프로젝트의 명칭을 정하고 기본 골격을 생성한다 

    5) yo angular:<SubCommand> <Subject> 를 통해 기본골격 밑으로 기능을 추가한다. SubCommand는 제너레이터에 따라 사용자 정의 할 수 있다 

  - 프로젝트에 필요한 골격 코드 생성을 위한 자신만의 제너레이터를 만들 수 있다. 

  - 사용법

    1) angular 제너레이터 설치

    2) 프로젝트 폴더생성

    3) angular 프로젝트 생성을 하고 Sass 미사용, Bootstrap을 사용체크하면 필요한 파일과 모듈을 자동 설치한다

    4) 프로젝트 기본 골격코드 자동 생성하면 app 폴더가 프론트 개발 ROOT 폴더가 된다

// 1) 

$ npm install -g generator-angular


// 2) 

$ mkdir meanstack & cd meanstack


// 3) 

$ yo angular meanstack

     _-----_

    |       |

    |--(o)--|   .--------------------------.

   `---------´  |    Welcome to Yeoman,    |

    ( _´U`_ )   |   ladies and gentlemen!  |

    /___A___\   '__________________________'

     |  ~  |

   __'.___.'__

 ´   `  |° ´ Y `


Out of the box I include Bootstrap and some AngularJS recommended modules.


[?] Would you like to use Sass (with Compass)? No

[?] Would you like to include Twitter Bootstrap? Yes

[?] Which modules would you like to include? (Press <space> to select)

❯⬢ angular-resource.js

 ⬢ angular-cookies.js

 ⬢ angular-sanitize.js

 ⬢ angular-route.js


// 4) 


bower

  - bower는 트위터에서 개발한 프론트앤드 라이브러리 설치 및 버전 의존성 관리 도구이다 

  - yo를 통하여 스케폴딩 파일이 생성하면 bower 사용을 위한 기본 환경파일도 자동 생성된다 

    1) 환경파일은 bower.json 으로 현재 설치된 라이브러리 명칭과 버전을 자동 기록한다 

    2) 라이브러리 설치 위치정보는 .bowerrc 에서 변경한다. 기본값으로 "bower_components" 를 사용한다 

// 1) bower.json 최초 설치 정보 

{

  "name": "meanstack",

  "version": "0.0.0",

  "dependencies": {

    "angular": "1.2.6",

    "json3": "~3.2.6",

    "es5-shim": "~2.1.0",

    "jquery": "~1.10.2",

    "bootstrap": "~3.0.3",

    "angular-resource": "1.2.6",

    "angular-cookies": "1.2.6",

    "angular-sanitize": "1.2.6",

    "angular-route": "1.2.6"

  },

  "devDependencies": {

    "angular-mocks": "1.2.6",

    "angular-scenario": "1.2.6"

  }

}


// 2) .bowerrc 위치정보

{

    "directory": "app/bower_components"

}


  - 사용법 

   1) 검색 : "bower search <명칭>"

   2) 설치 : "bower install <명칭>  --save (또는 --save-dev)"

   3) 보기 : "bower list"

   3) 도움말 : "bower help" 또는 "bower help <명령어>"

$ bower list

bower check-new     Checking for new versions of the project dependencies..

meanstack#0.0.0 ~/meanstack

├── angular#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

├─┬ angular-cookies#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

├─┬ angular-mocks#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6

├─┬ angular-resource#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6

├─┬ angular-route#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6

├─┬ angular-sanitize#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6

├─┬ angular-scenario#1.2.6 (latest is 1.2.11-build.2184+sha.319dd1a)

│ └── angular#1.2.6

├─┬ bootstrap#3.0.3

│ └── jquery#1.10.2 (2.1.0 available)

├── es5-shim#2.1.0 (latest is 2.3.0)

├── jquery#1.10.2 (latest is 2.1.0)

└── json3#3.2.6 (latest is 3.3.0)

  * angular 개발시점에 정식 릴리즈된 가장 최신버전을 사용할 예정이고 bower를 통하여 업데이트할 것이다. 


Grunt

  - grunt는 자바의 ant와 같은 기능을 수행한다

  - 다양한 플러그인을 통하여 기능을 첨부하여 확장할 수 있다. 

  - yo을 통해 프로젝트 골격 코드생성시 Gruntfile.js 환경파일이 기본 생성된다 

  - 또한 골격 코드 생성시 기본적으로 사용되는 플러그인은 node_moudles 폴더에 자동 설치된다 

// 1) node_modules에 기본 설치된 grunt 플로그인 


// 2) Gruntfile.js 내역 중 명령 일부

module.exports = function (grunt) {

  // Load grunt tasks automatically

  require('load-grunt-tasks')(grunt);


  // Time how long tasks take. Can help when optimizing build times

  require('time-grunt')(grunt);


  // Define the configuration for all the tasks

  grunt.initConfig({


    // Project settings

    yeoman: {

      // configurable paths

      app: require('./bower.json').appPath || 'app',

      dist: 'dist'

    },

    ... 중략...


grunt.registerTask('serve', function (target) {

    if (target === 'dist') {

      return grunt.task.run(['build', 'connect:dist:keepalive']);

    }


    grunt.task.run([

      'clean:server',

      'bower-install',

      'concurrent:server',

      'autoprefixer',

      'connect:livereload',

      'watch'

    ]);

  });


  grunt.registerTask('server', function () {

    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');

    grunt.task.run(['serve']);

  });


  grunt.registerTask('test', [

    'clean:server',

    'concurrent:test',

    'autoprefixer',

    'connect:test',

    'karma'

  ]);


  grunt.registerTask('build', [

    'clean:dist',

    'bower-install',

    'useminPrepare',

    'concurrent:dist',

    'autoprefixer',

    'concat',

    'ngmin',

    'copy:dist',

    'cdnify',

    'cssmin',

    'uglify',

    'rev',

    'usemin',

    'htmlmin'

  ]);


  grunt.registerTask('default', [

    'newer:jshint',

    'test',

    'build'

  ]);

};


  - 사용법

   1) 테스트 : grunt test

   2) 빌드 : grunt build

   3) 프리뷰 : grunt serve

// 1) 

$ grunt test

Running "clean:server" (clean) task


Running "concurrent:test" (concurrent) task


    Running "copy:styles" (copy) task

    Copied 1 files


    Done, without errors.



    Execution Time (2014-01-25 22:42:19 UTC)

    loading tasks   4ms  ▇▇▇▇ 25%

    copy:styles    10ms  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 63%

    Total 16ms


Running "autoprefixer:dist" (autoprefixer) task

Prefixed file ".tmp/styles/main.css" created.


Running "connect:test" (connect) task

Started connect web server on 127.0.0.1:9001.


Running "karma:unit" (karma) task

INFO [karma]: Karma v0.10.9 server started at http://localhost:8080/

INFO [launcher]: Starting browser Chrome

WARN [watcher]: Pattern "/Users/nulpulum/prototyping/yeomain/meanstack/test/mock/**/*.js" does not match any file.

INFO [Chrome 32.0.1700 (Mac OS X 10.9.1)]: Connected on socket nUaNX14YFrQJ_aeDkWM5

Chrome 32.0.1700 (Mac OS X 10.9.1): Executed 1 of 1 SUCCESS (2.184 secs / 0.033 secs)


Done, without errors.



Execution Time (2014-01-25 22:42:17 UTC)

concurrent:test  2.2s  ▇▇▇▇▇▇▇▇▇▇▇26%

karma:unit       6.2s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 73%

Total 8.4s


// 2) 브라우져가 자동 실행된다 

$ grunt serve 


Yeoman에 대한 이해와 기본적인 설치, 사용법을 익혔다. 프론트 앤드 개발을 하면서 계속 사용하게 되므로 잘 익혀 놓도록 하자 


posted by 윤영식
2013. 11. 16. 05:46 My Projects/BI Dashboard

Spring MVC의 RESTful 방식을 사용하면서 AngularJS를 Eclipse에서 개발하기 위한 제반 설정 환경을 만들어 보도록 한다. 핵심은 Java를 위한 라이브러리 의존성 관리와 빌드를 위하여 Maven을 사용하고 JavaScript는 의존성 관리는 bower를 사용하고 빌드도구는 grunt를 사용하게 된다. 따로 따로 사용하지 않고 하나의 프로젝트로 합치는 과정을 생각해 보자 



1. Maven을 이용한 Spring MVC 환경 만들기 

  - 이미 Eclipse Juno 기반에서 Maven + Spring MVC 환경 설정 블로깅을 하였다

  - pom.xml 에 logback 관련 내용 추가 (참조)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.ysyun</groupId>

<artifactId>DashboardTest</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>war</packaging>

<url>http://maven.apache.org</url>


<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<spring.version>3.2.0.RELEASE</spring.version>

<junit.version>4.11</junit.version>

<jdk.version>1.6</jdk.version>

</properties>


<dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

<exclusions>

<exclusion>

<artifactId>commons-logging</artifactId>

<groupId>commons-logging</groupId>

</exclusion>

</exclusions>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-web</artifactId>

<version>${spring.version}</version>

</dependency>


<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${spring.version}</version>

<exclusions>

<exclusion>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

</exclusion>

</exclusions>

</dependency>


<!-- use logback logger -->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-access</artifactId>

<version>1.0.13</version>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-core</artifactId>

<version>1.0.13</version>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>1.0.13</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.7.5</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>1.7.5</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>log4j-over-slf4j</artifactId>

<version>1.7.5</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-jcl</artifactId>

<version>1.7.5</version>

</dependency>


<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

<scope>test</scope>

</dependency>

</dependencies>


<build>

<finalName>DashboardTest</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>${jdk.version}</source>

<target>${jdk.version}</target>

</configuration>

</plugin>

</plugins>

</build>

</project>

  - 다음에 logback.xml 환경파일을 resource에 놓아 classpath에 잡아준다. 개발/배포 따로 구성한다 

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true">

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">

        <encoder>

            <charset>utf-8</charset>

            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>

        </encoder>

    </appender>

    <logger name="ch.qos.logback" level="WARN"/>

    <logger name="org.apache" level="WARN"/>

    <logger name="org.springframework" level="WARN"/>

    <logger name="org.springframework.web" level="WARN"/>

    <logger name="org.springframework.security" level="WARN"/>

    <logger name="org.springframework.cache" level="WARN"/>


    <root level="DEBUG">

        <appender-ref ref="CONSOLE"/>

    </root>

</configuration>




2. SPA 환경 잡아주기 

  - Yeoman을 통하여 angular 프로젝트 만들기 (참조)

$ yo angular SolarDasbhoard


  - 위의 파일을 각각 다음과 같이 이동한다 

    + app/ 폴더에 있는 것을 src/main/webapp로 복사한다 

    + node_modules 및 test 폴더 그리고 나머지 모든 파일을 eclipse 프로젝트 root로 복사한다 

      여기서 node_modules안의 모듈은 grunt와 karma 테스트 모듈들로 운영에 배포될 필요가 없다. 

      운영 배포는 webapp/ 밑에 있는 파일들이고, 사용하는 모듈은 src/main/webapp/bower_components/ 밑에 위치한다 

      


  - app폴더 밑의 내용이 src/main/webapp로 이동하였으므로 관련 환경설정 내역을 수정한다 

// bower 설정파일인 .bowerrc  변경 

{

    "directory": "src/main/webapp/bower_components"

}


// karm.conf.js 파일 내역 수정

    files: [

      'src/main/webapp/bower_components/angular/angular.js',

      'src/main/webapp/bower_components/angular-mocks/angular-mocks.js',

      'src/main/webapp/bower_components/angular-resource/angular-resource.js',

      'src/main/webapp/bower_components/angular-cookies/angular-cookies.js',

      'src/main/webapp/bower_components/angular-sanitize/angular-sanitize.js',

      'src/main/webapp/scripts/*.js',

      'src/main/webapp/scripts/**/*.js',

      'test/mock/**/*.js',

      'test/spec/**/*.js'

    ],


// grunt build를 위한 Gruntfile.js 내역 수정 

// 소스의 위치와 grunt build시에 dist 폴더에 .html과 WEB-INF/* 파일까지도 copy 하도록 수정 

 yeoman: {

      // configurable paths

      app: require('./bower.json').appPath || 'src/main/webapp',

      dist: 'dist'

    },

... 중략 ...

 copy: {

      dist: {

        files: [{

          expand: true,

          dot: true,

          cwd: '<%= yeoman.app %>',

          dest: '<%= yeoman.dist %>',

          src: [

            '*.{ico,png,txt,html}',

            '.htaccess',

            'bower_components/**/*',

            'images/{,*/}*.{gif,webp}',

            'styles/fonts/*',

            'WEB-INF/*'

          ]

        }, {

          expand: true,

          cwd: '.tmp/images',

          dest: '<%= yeoman.dist %>/images',

          src: [

            'generated/*'

          ]

        }]

      },

      styles: {

        expand: true,

        cwd: '<%= yeoman.app %>/styles',

        dest: '.tmp/styles/',

        src: '{,*/}*.css'

      }

    },



3. .war 배포파일 만들기 

  - Maven(java 서버)와 Yo(javascript 클라이언트) 환경설정을 완료하였다면 빌드했을 때 최종파일을 .war파일로 묶어보자 

  - grunt build를 했을 경우 프로젝트의 root/dist 디렉토리가 신규 생성되어 src/main/webapp/* 파일이 minification 되어 들어있다

  - 해당 파일을 .war안에 묶기 위하여 pom.xml 에 플러그인 설정 추가

<build>

<finalName>DashboardTest</finalName>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.0</version>

<configuration>

<source>${jdk.version}</source>

<target>${jdk.version}</target>

</configuration>

</plugin>

<!-- grunt build 수행하여서 생성되는 폴더인 dist 를 지정한다 -->

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-war-plugin</artifactId>

<version>2.4</version>

<configuration>

<warSourceDirectory>dist</warSourceDirectory>

</configuration>

</plugin>

</plugins>

</build>


  - 배포파일 war 만들기 순서

$ grunt build (if error ocurred, option --force)

$ mvn clean install

[INFO] Scanning for projects...

[INFO] ------------------------------------------------------------------------

[INFO] Building DashboardTest 0.0.1-SNAPSHOT

[INFO] ------------------------------------------------------------------------

.. 중략 ..

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 5.109s

[INFO] Finished at: Fri Nov 15 15:43:09 EST 2013

[INFO] Final Memory: 12M/81M

[INFO] ------------------------------------------------------------------------

  * eclipse 의 "Run As..." 의 "5 Maven Build"를 해도 같은 결과를 받음 


이제 eclipse 상에서 Spring Framework + AngularJS Framework 으로 개발을 해보자 

GitHub URL : https://github.com/ysyun/SPA_Angular_SpringFramework_Eclipse_ENV



<참조>

  - SLF4J를 통하여 logback 사용하기

  - Yeoman을 통한 AngularJS + Express 환경구성하기

  - Maven 기본 디렉토리 layout, pom.xml 에서 변경하는 방법

posted by 윤영식
2013. 10. 30. 14:31 My Services/PlayHub

프론트 개발을 위해 준비해야할 것들은 무엇이 있을까? 우선 개발 및 테스트 프레임워크와 라이브러리 관리, 테스트/코드커버리지/빌드 자동화 수행등 준비할 것들이 많다. 이것을 한번에 준비하고 자동화할 방법은 없을까?



1. Yeoman

  - yo : 코드 스케폴딩 역할 (프로젝트를 시작할 때 최초에 디렉토리구조와 템플릿 파일일 제공해 준다) generator-* 로 시작

  - grunt : test, lint, concatenate, build등 Java의 Ant와 같은 Task를 자동 수행

  - bower : 내부적으로 사용하는 컴포넌트의 버전 의존성 관리 및 설치/업데이트/삭제 관리

  - 참조 



2. Addy Osmani의 Frontend Workflow

  - 자동화는 반복적인 작업을 효율적으로 만드는 과정

  - Frontend Automation = Scaffolding + Download Libraries + Download Template + Download Framework



3. PlayHub Workflow 만들기 

  - 자신의 개발환경에 GitHub 저장소 설정하기

    + mac 또는 windows

    + nitrous.io 같은 PaaS 에도 설정가능 

// Node Version Manager 설치 

$ curl https://raw.github.com/creationix/nvm/master/install.sh | sh

$ exit

logout

Connection to 127.0.0.1 closed.


// 현재 CentOS에 설치된 Node version 정보가 나오고 원하는 버전정보를 선택하여 사용할 수 있다. 명령은 help 참조

$ nvm list

       N/A

current: v0.11.5


// playhub 디렉토리 만듦 - 해당 디렉토리 밑으로 playhub의 저장소를 놓을 것임 

$ mkdir playhub 


// playhub의 저장소를 git clone하기 위하여 자신의 ssh 공개키가 없다면 생성한다

// 생성방법 참조

$ cd .ssh

$ ssh-keygen -t rsa -C ysyun@yuwin.co.kr  // 이후 쭉 enter

Generating public/private rsa key pair.

Enter file in which to save the key (/home/vagrant/.ssh/id_rsa):

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/vagrant/.ssh/id_rsa.

Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.

The key fingerprint is:

8a:32:de:ef:de:fd:22:8f:8d:38:70:b0:d7:56:e1:da ysyun@yuwin.co.kr

The key's randomart image is:

+--[ RSA 2048]---+

|                            |

|          .                 |

|         . .                |

|    .     o                |

|     o .S+               |

|    o.o.+ E              |

|  o .+..                  |

| . +  .o.=.              |

|  . .+=.+o+o.         |

+------------------+

$ ssh-add id_rsa

Could not open a connection to your authentication agent.


// 두개의 id_rsa 파일 생성 

$ ls -lart

-rw-rw-r--  1 vagrant vagrant  399 2013-10-30 05:59 id_rsa.pub

-rw-------  1 vagrant vagrant 1675 2013-10-30 05:59 id_rsa

drwx------  2 vagrant root    4096 2013-10-30 05:59 .


$ cat id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAyvfJRNE/Kx+VwuGcQX8+PYbFadT6mCLZ1.. 중략 ..XS0U0uQ== ysyun@yuwin.co.kr


// GitHub -> "Account Settings" -> "SSH Keys"에서 SSH key값 등록



// 이제 GitHub에서 PlayHub의 Palette를 clone 해 보자 (git 기본 설치를 전제로 함)

$ cd ../playhub/

$ git clone git@github.com:playground-ko/palette.git

Initialized empty Git repository in /home/vagrant/playhub/palette/.git/

.. 중략 ..


$ ls - lart

drwxr-xr-x  5 vagrant vagrant 4096 2013-10-30 06:07 palette


// submodule에 대하여 초기화 하고 업데이트 한다 (Git 환경만들기 참조)

$ cd palette

$ git submodule init

Submodule 'backend' (git@github.com:playground-ko/palette.backend.git) registered for path 'backend'

Submodule 'frontend' (git@github.com:playground-ko/palette.frontend.git) registered for path 'frontend'

$ git submodule update

Initialized empty Git repository in /home/vagrant/playhub/palette/backend/.git/

.. 중략 ..

Submodule path 'backend': checked out 'f8276822e8a12a15f2af19e0c62cbd74a9172d84'

Initialized empty Git repository in /home/vagrant/playhub/palette/frontend/.git/

.. 중략 ..

Submodule path 'frontend': checked out 'e1b7201011321e1df2cc990c4eb2042c765c8a3c'


// playhub 디렉토리로 이동하여 bankend, frontend 저장소를 별도로 받아서 개발을 시작한다 

$ cd ..

$ git clone git@github.com:playground-ko/palette.backend.git

Initialized empty Git repository in /home/vagrant/playhub/palette.backend/.git/

.. 중략 ..

$ git clone git@github.com:playground-ko/palette.frontend.git

Initialized empty Git repository in /home/vagrant/playhub/palette.frontend/.git/

.. 중략 ..


  - yo/grunt/bower, generator-angular 를 설치 또는 업그레이드 하고, frontend 디렉토리로 이동하여 프로젝트를 만든다 

// yo를 설치하면 grunt와 bower가 같이 설치된다 

sudo npm install -g yo

// 현재 버전은 1.0.4 (2013.10.31 기준)

$ yo --version

1.0.0-rc.1.4

$ grunt --version

grunt-cli v0.1.9

grunt v0.4.1

$ bower --version

1.2.7


// 이미 설치되어 있다면 최신버전으로 업데이트  한다 

$ sudo npm update -g yo

$ sudo npm update -g grunt-cli

$ sudo npm update -g bower


// angular framework 설치

sudo npm install -g generator-angular


// angular 웹앱을 만든다 

$ cd  palette.frontend/

$ yo angular Palette


// 빌드하면 배포할 수 있는 dist 배포 디렉토리가 나온다. 

// dist는 온전한 html, css, js 파일들이고 이것은 어느 웹서버에 가져다 놓아도 구동이 된다

// 즉, 굳이 node.js위에 구동되지 않아도 됨 

// 기본적으로 build를 하면 관련 js 파일을 minification하여 사이즈를 줄여준다 

// Sublime Text에 Grunt build를 설정할 수 있다

$ grunt build

// karma 통하여 unit, e2e 테스트 수행

$ grunt test

// node.js 기반으로 서버가 열리면서 브라우져(Chrome)도 자동으로 열린다 

$ grunt server


// dist 배포본은 python을 통하여 간단히 테스트 해 볼 수도 있다 

// 브라우져에서 8000 port를 열어서 배포본이 정상적으로 작동하는지 아이체킹

$ cd dist 

python -m SimpleHTTPServer 8000


이제 Frontend를 Yeoman을 통하여 개발해 보자



4. BootFlat 적용하기 

  - yeoman의 generator-bootstrap은 v2.* 버전이 적용되어 있다. Bootstrap v3.* 버전이 적용된 BootFlat 확장판을 적용하기 위한 방법은 기존 블로깅을 참조한다. 

  - Twitter Bootstrap 고도화



<참조>

  - Yeoman을 통해 AngularJS 프로젝트 자동 구성하기

  - nvm 설치 방법

  - GitHub을 위한 SSH 키 생성방법

  - Sublime Text에 Grunt build 설정하기

  - BootFlat Homepage

posted by 윤영식
2013. 4. 15. 11:44 Dev Environment/Build System

AngularJS 개발시 반복적인 작업을 제거하고 생산성을 높일 수 있는 통합 도구인 Yeoman의 사용법에 대해 알아보고, 처음 개발을 시작할 때 코드의 틀을 잡아 주는 몇가지 Seed 프로젝트를 통하여 어떤 구조로 애플리케이션을 만들어야 하는지 알아두자



1. 필요 요소 기술

  - UI : Bootstrap from Twitter  간혹 Foundation을 이용

  - Build/Preview : Grunt

  - Test : 기본은 Karma이고, Mocha를 사용하고 싶다면 Karma-Mocha Karma구동을 위한 Mocha adapter 존재

  - Package Management : Bower from Twitter

이들의 통합적으로 사용하기 위한 툴로 yeoman 을 설치하면 된다. 간단한 명령으로 AngularJS 관련 코드를 자동 생성하여 준다



2. Yeoman startup

  

yo - the scaffolding tool from Yeoman

bower - the package management tool  

  + component.json : 의존관계 설정

  + .bowerrc : 컴포넌트 설치 위치정보

grunt - the build tool 

  + Gruntfile.js : ant와 같은 수행 Task 정의

  + package.json : Node.js위에 구동되므로 package.json에 Grunt contributor 라이브러리 정의

karma - grunt test 시에 수행 

  + karma.conf.js : 로컬 테스트 환경

  + karma-e2e.conf.js : Real Browser 테스트 환경 즉, end-to-end (Client<->Server) 테스트 수행. 사용 port 8080


  - Yeoman command for AngularJS

// 설치 : grunt-cli, bower가 같이 설치된다 

npm install -g yo


// Yeoman을 위한 generator 설치 for AngularJS & Karam

// 하기 에러 내역 참조하여 generator-angular의 script-base.js 파일 수정

// Generator는 Yeoman에서 생성하는 boilerplate 나 scaffolding 코드를 만들어주는

// Yeoman의 플러그인이라 생각하면 된다. 이미 만들어지 Generator 목록이 존재한다

// > https://github.com/yeoman (generator-* 목록들)

// > Generator 만들기 참조

npm install -g generator-webapp generator-angular generator-karma


// 명령어 (프로젝트 디렉토리에서 수행)

yo angular 또는 yo angular:app 애플리케이션 생성

yo angular:controller myControllerName 컨트롤러 생성

yo angular:directive myDirectiveName 디렉티브 생성

yo angular:filter myFilterName 필터 생성

yo angular:service myServiceName 서비스 생성


  - yo angular:* 사용시 에러 발생 해결방법

예) yo angular:controller Test 수행시 하기와 같은 에러 발생

~/angularjs/sd_01> yo angular:controller Test


path.js:360

        throw new TypeError('Arguments to path.join must be strings');

              ^

TypeError: Arguments to path.join must be strings

    at path.js:360:15

    at Array.filter (native)

    at Object.exports.join (path.js:358:36)

    at Generator (/usr/local/lib/node_modules/generator-angular/script-base.js:38:29)

    at new Generator (/usr/local/lib/node_modules/generator-angular/controller/index.js:10:14)


==> 해결하기 

1) /usr/local/lib/node_modules/generator-angular/script-base.js 의 38 번째 줄 내용을 하기와 같이 수정함

 37     if (!this.options.coffee &&

 38       //this.expandFiles(path.join(this.appPath, '/scripts/**/*.coffee'), {}).length > 0) {  // 주석처리 

 39       this.expandFiles(path.join(process.cwd(), '/scripts/**/*.coffee'), {}).length > 0) {  // process.cwd() 로 바꿈

 40       this.options.coffee = true;

 41     }


2) 재수행 : 친절하게도 TestCase까지 자동 생성해 준다 

   ~/angularjs/sd_01> yo angular:controller Test

   create app/scripts/controllers/Test.js

   create test/spec/controllers/Test.js


  - Yeoman command for Bower : 의존관계 라이브러리에 대한 관리 담당 

// 명령어

bower search <dep> - search for a dependency in the Bower registry

bower install <dep>..<depN> - install one or more dependencies

bower list - list out the dependencies you have installed for a project

bower update <dep> - update a dependency to the latest version available


// 설치하기 

// .bowerrc 에 설정된 디렉토리로 다운로드된 라이브러리가 설치된다

$ bower install angular-ui

bower cloning git://github.com/angular-ui/angular-ui.git

bower cached git://github.com/angular-ui/angular-ui.git

bower fetching angular-ui

bower checking out angular-ui#v0.4.0

bower copying /Users/nulpulum/.bower/cache/angular-ui/bd4cf7fc7bfe2a2118a7705a22201834

bower installing angular-ui#0.4.0


$ cd app/components/

$ ls

angular angular-scenario es5-shim json3

angular-mocks angular-ui jquery


$ cd ../..

$ cat .bowerrc

{

    "directory": "app/components"

}


  - Yeoman command for Grunt : 프러덕션 빌드, 미리보기, 테스팅 

    + grunt는 task에 대한 여러 target들이 존재하는 구조이다. 

    + 명령을 grunt <task> 로 주면 task밑의 모든 target이 순서대로 수행된다

    + 명령을 grunt <task>:<target> 을 지정하여 특정 target만 수행할 수도 있다

    + task와 관련한 여러가지 Plugins 이 이미 만들어져 있고 직접 만들 수도 있다 (기존 Plugins 목록)

// 명령어

grunt test  - 테스트하기. run the unit tests for an app  

grunt server - 브라우져에서 보기. 변경사항 실시간 반영됨. preview an app you have generated (with Livereload)

grunt - 배포본 빌드하기.  build an optimized, production-ready version of your app  (warning 무시 옵션 --force 사용가능)


// 브라우져 미리보기 in app root folder

grunt server

// warning -jslint 같은- 무시하고 계속 build하기

grunt  --force 



3. 기본 코드 생성

  - Grunt-Express : Grunt와 Express 연동하기

  - Yeoman-Angular-Express : Yeoman을 이용하여 Angular project 생성한 후 Express와 통합하는 예제

  - Angular-Socket.io-Seed : Angular와 Socket.io를 접목 시키고자 할때 사용 (포스팅)



4. Addy Osmani 님이 이야기 하는 Automation Front-end workflow



결론적으로 Yeoman을 사용하여 기반 코드를 생성하고 빌드/테스팅 자동화를 한다. 그리고 필요한 코드들은 Seed 프로젝트를 참조하여 자기것으로 만들면 되겠다



<참조>

  - 원문 : Google, Twitter and AngularJS

  - 보다 많은 AngularJS와 BackboneJS에 대한 기사 in DailyJS

  - Grunt를 위한 express 플러그인 테스트

posted by 윤영식
prev 1 next