2016년 5월 29일 일요일

[vim, NERDTree] make show hidden file(like .gitignore) in NERDTree


[vim, NERDTree] make show hidden file(like .gitignore) in NERDTree

hi vimmer,

what ever you're use shell type is not important,

it's working almost shell (like zsh)

just add code .vimrc in file

like this

let NERDTreeShowHidden=1

2016년 3월 6일 일요일

[MEANI-Stack] - #10 (Node & Express) User API Test작성

[MEANI-Stack] - #10 (Node & Express) User API Test작성




API test를 하기위해 jasmine Framework를 선택 하였습니다.

jasmine framework는 javascript test framework로써
mochaJS, chaiJS 와 같은 테스트 프레임워크들 사이에 있습니다.

과거 jasmine 1.x시절에는 done() callback메소드
즉 promise스펙을 지원하지 않아
promise 스펙을 지원하는 mochaJS가 압도적으로 우세했지만

jasmine 2.0에서 비동기 콜백 함수 지원, 즉 promise spec을 구현함에 따라
mochaJS + chaiJS promise 조합으로 사용하던 스택과  동등한 위치가 되었지요.

이에따라 angularJS팀에서 만든 protractor 테스트 프레임워크가
기존에 mocha와 jasmine을 모두 지원하다가
공식적으로 mocha를 더이상 지원하지 않겠다고 발표하면서
jasmine의 관심도가 더 높아지게 되었습니다.



protractor link : https://angular.github.io/protractor/#/
mocha limited support link : https://github.com/angular/protractor/blob/master/docs/frameworks.md



이번 펫 프로젝트 기술 스택이 MEANI 즉 angularJS를 사용하는만큼
위와같은 이유들로 protractor를 고려하여 jasmine으로 선택하였습니다.

jasmine 기반으로 제작된 jasmine-node를 사용하려 해 보았으나
몇일간 테스트 해본결과 순수한 jasmine과의 큰 차이를 느낄수 없어
jasmine을 사용합니다.
jasmine 링크 : http://jasmine.github.io/

jasmine-node 링크 : https://github.com/mhevery/jasmine-node/tree/Jasmine2.0



아래 명령어로 jasmin과 request 모듈을 설치합니다.
$ npm install -g jasmine
$ npm install -save request


jasmine으로 http request를 요청하기 위해서는 매번 XMLHttpRequest 객체를 직접 생성해야 하므로
request 모듈도 함께 설치해줍니다.
request 모듈은 simple http request를 제공해줍니다.



CRUD 테스트를 작성하기 위해 아래와 같이 user controller에 remove를 추가해 줍니다.

user.server.controller.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
var User = require('mongoose').model('User');
 
exports.create = function(req, res, next) {
  var user = new User(req.body);
  console.log(req.body);
 
  User.count({email: req.body.email},
    function (err, count) {
      if (!count) {
        user.save(function(err) {
          if (err) {
            res.json(err);
          } else {
            res.json(user);
          }
        });
      } else {
        var errorMessage = 'User email is Already Exists';
        console.log(errorMessage);
        res.json(errorMessage);
      }
    });
};
 
exports.list = function(req, res, next) {
  User.find({}, function(err, users) {
    if (err) {
      return next(err);
    } else {
      res.json(users);
    }
  });
};
 
exports.findUserByEmail = function(req, res, next) {
  User.findOne({
    email: req.params.email
  }, function(err, user) {
    if (err) {
      console.log(err);
      return next(err);
    } else {
      console.log(err);
      res.json(user);
    }
  });
}
 
exports.remove = function(req, res, next) {
  User.remove({
    email: req.params.email
  }, function(err, user) {
    if (err) {
      return next(err);
    } else {
      res.json(user);
    }
  });
}
 
 
cs


mongoose에서 제공하는 기본 메소드들은 model.js를 사용합니다.
기본 제공하는 메소드 들에 대해 궁굼하다면 아래 링크를 참고하세요.
http://mongoosejs.com/docs/api.html#model-js


user.server.routes.js에 아래와같이 delete를 추가해 줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
 
var users = require('../../app/controllers/users.server.controller.js');
 
module.exports = function(app) {
  app.route('/users')
    .post(users.create)
    .get(users.list);
  app.route('/users/:email')
    .get(users.findUserByEmail)
    .delete(users.remove);
}
 
cs



이제 본격적으로 jasmine을 사용하기 위해 아래 명령어를 입력합니다.

$ jasmine init
$ jasmine examples

위 명령어들을 실행하면 spec directory가 생성되고 간단한 예제가 생성됩니다.
spec/
 -helpers/
 -jasmine_examples/
 -support/

최종적으로 위와 같은 directory가 생성되는데
저는 여기에 모델들을 테스트 하기 위한 코드를 모아놓은 models directory와 
순수하게 jamsine을 테스트를 해보기위한 test directory두개를 더 생성했습니다.


spec/
 -helpers/
 -jasmine_examples/
 -support/
 -models/
 -test/


그리고 models 안에 user.model.spec.js를 생성하고 아래와 같이 코드를 작성하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
var request = require('request');
 
// jasmine.getEnv().defaultTimeoutInterval = 500;
var r = request.defaults({'proxy':'http://localhost:4000/users'});
 
var requestDefault = 'http://localhost:4000';
 
describe('User Model Test'function() {
 
  var email = 'test_' + Math.floor(Math.random()*10000+ '@gmail.com';
  var form = {
    email : email,
    password : '12345678',
    role : 'User'
  }
 
  var responseCallback = function(err, res, body, debug) {
    if (debug) {
      console.log(res);
    }
    expect(res.statusCode).toEqual(200);
    if (res.statusCode !== 200){
      console.log(res.statusCode);
      console.log(body);
    }
  };
 
  it('user list get'function(done) {
    request.get(requestDefault + '/users'function(err, res, body) {
      responseCallback(err, res, body);
      done();
    });
  });
 
  it('user create'function(done) {
    request.post({
        url : requestDefault + '/users',
        form : form,
        headers : {
          'Content-Type' : 'application/json'
        }
      }, function(err, res, body) {
        responseData = JSON.parse(body);
        expect(responseData.email).toEqual(email);
        responseCallback(err, res, body);
        done();
      });
  });
 
  it('user read'function(done) {
    request.get(requestDefault + '/users/' + email, function(err, res, body) {
      responseData = JSON.parse(body);
      expect(responseData.email).toEqual(email);
      responseCallback(err, res, body);
      done();
    });
  });
 
  it('user delete'function(done) {
    request.del(requestDefault + '/users/' + email, function(err, res, body) {
      responseData = JSON.parse(body);
      // console.log(body);
      expect(responseData.n).toEqual(1);
      responseCallback(err, res, body);
      done();
    });
  });
 
});
 
 
 
cs




실행하는법은 project directory에서 jasmine 명령어를 입력하면 됩니다.
이때 주의할점은 junit처럼 가상서버를 자동으로 생성해서 테스트를 진행하는게 아니라서
node server가 실행되지 않은 상태에서 테스트를 실행할경우 request요청은 모두 fail이 됩니다.




훌륭합니다. 0.066초 만에 user.model CRUD를 모두 테스트 완료하였습니다.
단순계산으로 해보면 모델이 10개일경우에도 1초 미만에 테스트가 가능해지니
테스트 작성이 조금 번거로울지 몰라도 1시간에 10번씩 테스트해도 아무런 부담이 없어졌습니다.



작업의 마무리는 커밋!
https://github.com/polyglotm/PP-MEANI-stack-back-end


포스트의 마무리는 애자일 보드 확인!



다음 태스크는 (Angular 2) 회원가입 UI 작성 으로 선택 되었습니다.
드디어! 고대하던 Angular 2를 본격적으로 시작할수 있게 되었네요!

한가지 고민이 있다면 ionic2를 위해서 굳이 따로 mobile UI를 따로 만들어야 하는건가 생각이 듭니다.
가급적이면 웹에서 mobile대응을 하고
ionic은 말그대로 컨버팅 되는것에 중점을 둘까 생각중입니다.

물론  ionic2가 컨버팅이 잘 된다면요...

2016년 2월 28일 일요일

[MEANI-Stack] - #9 (Node & Express) 회원가입 API작성

[MEANI-Stack] - #9 (Node & Express) 회원가입 API작성




회원가입 API를 위해 유저 모델부터 정의합니다.

제 생각에 당장 필요한 필드는 email, password, role 세가지이며
언제 생성 되었는지 알기위해 createdAt을 자동으로 추가 하기로 하고 모델을 작성했습니다.



required는 인자를 필수로 설정하는것 입니다.
해당 인자가 없을경우 오류를 발생시킵니다.

enum의경우 들어온 인자를 사전 설정된 값으로 제한시킵니다.

validate의 경우 들어온 인자값을 모델에서 검증하는 도구입니다.
route나 controller에서 작업해도 되지만 순수하게 모델에서 작업하였습니다.
validate 참고링크 : http://mongoosejs.com/docs/validation.html







생성도니 모델을 이용해서 controller에 아래와 같이 작업하였습니다.



create메소드는 파라미터로 넘어온 email이 기존에 존재하는지 count메소드를 통해 체크하고,
count값이 0일경우 회원가입을 진행하도록 하였습니다.

list메소드는 경우 기존 find를 사용하였고
findUserByEmail 메소드는 리퀘스트의 파라미터로 오는 email로 찾도록 하였습니다.








라우터 구성은 위와같이 restful하게 접근하였고 delete는 만들지 않았습니다.
(나중에 필요하면 만들 예정)






작성한 내용들을 아래와 같이 각각 express.js와 mongoose.js에 등록합니다.



model과 routes를 등록한것 이외에
express에 bodyParser.urlencloeded를 extended: false -> true로 변경하였고
mongoose 디버깅을 위해
mongoose.set('dedub', true);를 추가하였습니다.

만약 process.env.NODE_ENV에 대해 잘 모르겠다면 아래 링크된 글을 참고하세요

[Node.js] Node.js 환경변수 process.env.NODE_ENV 에 대한 이해 및 사용 [Node.js] Understanding the Node.js and using environment variables process.env.NODE_ENV







postman으로 작성한 API를 테스트 해봅니다.


첫번째는 회원가입 비정상 케이스, password를 6자리만 입력해봅니다.

에러 메시지가 이쁘진 않지만 그럭저럭 잘 넘어오는군요



두번째는 회원가입 정상케이스





회원가입된 유저를 호출 해봅니다.




굿 제대로 넘어오네요




다음은 유저 리스트



좋습니다 잘 넘어옵니다.
이상있는 데이터들은 validate를 하기 전 테스트 한 데이터들 입니다.



mongoose 디버깅 되고있는 부분도 확인해봅니다.



잘나옵니다.





작업의 마무리는 커밋!
github : https://github.com/polyglotm/PP-MEANI-stack-back-end

그리고 문서 업데이트!






언제나 포스트의 마무리는 애자일 보드 확인 및 다음 태스크 선정입니다.



이번 태스크를 진행하면서 절실하게 머리속을 맴돈것은
"유닛 테스트를 빨리 붙여야겠다" 였어요...

API는 계속 늘어만 갈텐데 뭐 하나 바뀔때마다
손가락으로 클릭 클릭해서 포스트맨 날리려면 어휴... 끔직합니다...
그리하여 다음 태스크는 (Node & Express) 회원가입 API Test 작성 으로 선정되었습니다.



[MEANI-Stack] - #8 (Side-Jobs) 요구사항 및 기능 명세서 작성

[MEANI-Stack] - #8 (Side-Jobs) 요구사항 및 기능 명세서 작성

지난번에 요구사항 재정의를 하고나서 느낀것은
진행하는데 제법 요구사항이 많고 사전에 모든 태스크를 등록하고 진행하지 않기 때문에
엑셀 시트로 된 요구사항 및 기능 명세서가 필요하다고 느꼈습니다.
그리하여 아래와 같이 명세서 문서를 작성해 보았습니다.







다음 태스크를 확인해봅니다.


다음 태스크는 (Node & Express) 회원가입 API 작성입니다.

2016년 2월 27일 토요일

[Node.js] Node.js 환경변수 process.env.NODE_ENV 에 대한 이해 및 사용 / [Node.js] Understanding the Node.js and using environment variables process.env.NODE_ENV

[Node.js] Node.js 환경변수 process.env.NODE_ENV 에 대한 이해 및 사용
[Node.js] Understanding the Node.js and using environment variables process.env.NODE_ENV


process.env는 아래 공식적인 문서에 나와있듯이 유저 환경변수를 사용합니다.
process.env uses the user's environment variables as shown in the following official documents.

Note Links : https://nodejs.org/api/process.html#process_process_env



만약 유저 환경변수에 대해 잘 모른다면 아래 글을 참조 하세요.
If you see the following articles if you do not know about the user's environment variables.

[Linux, Mac] environment variable path / 환경변수 설정






1.한가지 변수만 사용할때.
1. When you use only one kinds of variables.


한가지 환경변수 이를테면 production / development 등의 분기로직만 사용한다면
아래 순서대로 실행합니다.
If you use only one environment variable, such as a branch of logic, such as production / development Run the following order.


우선 ~/.bash_profile의 환경변수를 추가하여줍니다.(전역변수로 할경우 /etc/profile 에 설정합니다)
Priority will add environment variables in ~ /.bash_profile. (If you set a global variable in the /etc/profile)









추가된 환경변수가 제대로 동작하는지 아래와 같이 source명령어로 컴파일후 echo로 확인해 봅니다.
Add the environment variable is how it works properly after compiling a source command as follows: Demonstrate to echo.

$ source .bash_profile
$ echo $NODE_ENV









node에서 주로 상용하는 파일명인 app.js를 만들고 아래와 같이 console.log를 이용해
콘솔에 출력하도록 작성한후 node로 실행시켜 봅니다.
The file name usually used to create a node in app.js using console.log as follows:
After creating the console to try to run as a node.













2.여러가지 변수를 사용할때
2. When you use a variety of variables



그러나 node에서 여러가지 환경변수들, 이를테면 암호화 복호화를 위한 키값을 위한 변수들을
추가 하다보면 환경변수가 늘어나게 되는데 이럴경우 아래와 같은 방법을 추천합니다.
In this case, however, there is a variety of environmental variables in the node, such as the variables are added to the encrypted decryption key value for the environment variables it look stretched recommend the following methods:





유저 홈 디렉터리에 .node_profile 파일을 생성한후 아래와 같이 편집합니다.
After you create a file in the user's home directory, edit .node_profile below.




.bash_profile을 열어 가장 하단에 아래 내용을 추가합니다.
Open the .bash_profile and add the following lines to the bottom.

source "$HOME/.bash_profile"





방금 작성한 .bash_profile을 아래 명령어로 현재 터미널에 적용시킵니다.
Written to apply to just the current terminal .bash_profile down command.


$ source .bash_profile



app.js 파일을열어 아래와 같이 방금 입력한 NODE_ENV와 SECURE_KEY를 출력하도록 작성합니다.
app.js open the file you just created for output and input one NODE_ENV SECURE_KEY below.









마지막으로 node로 실행해서 결과를 확인합니다.
Finally, we run a node to see the results.



2016년 2월 21일 일요일

[MEANI-Stack] - #7 (Ionic 2) Seed Project 생성 (미해결)

[MEANI-Stack] - #7 (Ionic 2) Seed Project 생성 (미해결)



하이브리드 어플리케이션은 웹앱을 만드는것처럼
HTML, CSS그리고 JavasScript를 이용하여 개발하며
한번의 개발로 Android, IOS모두 컨버팅 가능하다는 큰 장점이 있습니다.

이런 하이브리드를 가능케 해준것의 중심에는 apache cordova프로젝트가 있었습니다.



apache cordorva : http://cordova.apache.org/






그리고

가장 유명한 플랫폼 으로는 phone gap 이 있지요.

phonegap : http://phonegap.com/







개념 자체는 아주 신선하고 좋지만 어느정도 명백한 한계는 존재합니다.

출처 :https://developer.salesforce.com/page/Native,_HTML5,_or_Hybrid:_Understanding_Your_Mobile_Application_Development_Options




여러가지 갑론 을박이 있지만 제생각은 아래와 같습니다.


0.웹앱이 네이티브 영역을 넘나드는데는 한계가 있다.
  3D그래픽을 구현하는 모바일 어플리케이션을 제외하고 대부분 모바일 웹앱으로 대체 될 수 있을거라
  생각했지만 apple진영에서 마켓에서 버는 수익이 막대하다보니 api를 완전히 열 계획도, 앞으로 완전히
  열 가능성도 매우 적어보입니다.

1.네이티브 앱에 비해 퍼포먼스는 떨어질수밖에 없다.
 만약 그래픽적인 요소들을 많이 포함하고 있다면 하이브리드 앱은 고려 대상이 아니다.

2.초창기 스타트업의 경우 하이브리드 앱을 충분히 고려 해 볼만 하다.
 진입장벽이 확실히 낮아지는 장점이 있다.
 그러나 퍼포먼스 즉, 성능은 사용자 경험에 중대한 영향을 미치므로
 중장기적으로 최고의 퍼포먼스를 위해 결국 네이티브로 변환해야만 한다.


이러한 상황속에서도 Angular진영에서는 phonegap을 사용할수 없다보니
Angular를 메인 스택으로 가져가는경우 하이브리드 앱은 고려하기 힘든 대상이었지만

Ionic의 등장으로 AngularJS기반 하이브리드 앱 도입의 길이 열리게 되었죠







그리고 Angular2의 Beta버젼 등장과 함께 
혜성같이 등장한 Ionic2 Beta가 등장하자마자 다운받아 실행해보았지만!

실행이 안되어 낑낑... stack overflow에도 저와 같은 질문들만 수두룩하고 
답변은 아무도 없는 그런 아비규환의 1월을 보내고

이 글을 시점인 2월달에 새로 릴리즈된 Ionic2는 웹 버전은 잘 실행되더군요 
그래서 (ionic 2) Seed Project 태스크를 진행해야겠다 생각했습니다.




자 그럼 Ionic2 Seed Proejct를 시작해봅니다.

공식 홈페이지 에 나온대로 진행해봅니다.

1.ionic2 다운로드
$ npm install -g ionic@beta

2.ionic2 seed project 다운로드
$ ionic start cutePuppyPics --v2

3.cordova 설치
$ sudo npm install -g cordova

4.ios platform추가
$ ionic platform add ios

5.xCode 설치 (맥만 가능)
맥 소프트웨어 센터에서 xcode검색후 설치하면 됩니다.






6.android platform추가
$ ionic platform add android

7.android sdk설치
공식홈페이지 다운로드 링크 : http://developer.android.com/sdk/installing/index.html




우측의 stand-alone sdk tools를 눌러서 들어가니 download 링크를 한번 더 태우는군요





그냥 recommend 해주는데로 했어야 했습니다.

차마 여기 적지못하는 온갖 삽질을 다하고 결국 Android studio를 설치했습니다.
여러분 그냥 Android studio를 받으세요. 
여러분의 정신건강을 위해서...

바로 맥용을 다운받습니다.

제가 사용하는 개발환경 폴더로 이동시킨후 path설정을 해줍니다.

환변경수 설정을 잘 모르는경우 아래 글을 참고하세요.


[Linux, Mac] environment variable path / 환경변수 설정

[zsh, YADR, dotfiles] environment variable path / 환경변수 설정






이제 sdk를 실행시킨후 기본 체크된 사항들만 install 해줍니다


 







아래 명령어로 실행해봅니다.
$ ionic run android





이런!
android-22를 요구하는군요...

다시 22버전을 설치한후 다시 실행해봅니다







하...


그냥 recommend 해주는데로 했어야 했습니다.

차마 여기 적지못하는 온갖 삽질을 다하고 결국 Android studio를 설치했습니다.
여러분 그냥 Android studio를 받으세요. 
여러분의 정신건강을 위해서...


Android studio를 설치하고 아무 프로젝트나 하나 만든후
아래 스크린샷에 강조 표시한 avd manager를 이용해 virtual device를 하나 생성합니다.






$ ionic run android
다시 실행!!!



Launch Success!!!!!!!!!
드디어 실행성공!!!!!






그렇습니다. 1월에 이어서 2월의 아비규환이 또 찾아왔습니다.


사실 한번 실행되는것만 확인하면 이후부터는 웹으로 작업을 진행하면 되기때문에
문제가 안되는데 한번이!!!!!!!!!! 제대로 실행이 안되네요...
스택오버플로우 검색해보았지만 ionic2관련된것은 없군요...




휴... 답답한 마음 부여잡고 ios라도 해봅니다.




$ ionic build ios 

no target specified for emulate. Deploying to iPhone-6s-Plus 라고 뜨네요
하지만 빌드는 된거같군요.



$ ionic emulate ios



잘 나옵니다!
하지만... iPhone-6s-Plus의 엄청난 해상도가 모니터 절반을 집어삼켜서
디버깅엔 부적절하군요. 어쨋든 실행은 됩니다...






이번 태스크는 미완성으로 일단 여기서 마무리 짓고
애자일보드를 확인합니다.



이번 태스크를 진행하면서 느낀것은 지금 진행하는데 ionic 2가 꼭 필요한게 아니고
워낙 초창기 버전이다보니 릴리즈가 빨라서 서버 API를 작성하는 도중에 버그가 해결될수도 있는데 
이걸 이렇게 진행해야 하나 생각이 들었습니다.
그러다 문득 든생각이 연관관계에 따른 우선순위를 명시적으로 매기지 않고
애자일 보드를 사용하더라도 한번에 모든 태스크를 추가 하지 않고 진행하다보니
기능명세서의 필요성을 느껴 (Side-Jobs) 요구사항 및 기능 명세서 작성 태스크를 추가하였습니다.


다음 태스크는 (Side-Jobs) 요구사항 및 기능 명세서 작성 을 진행 하도록 하겠습니다.