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

Publication

Category

Recent Post

2016. 11. 23. 16:50 Electron & Ionic

Electron을 통한 테스트 자동화 접근법 세션


- 정적 테스트 프로그램은 테스트 프로그램이 있는 것, 동적 테스트는 기존 애플리케이션을 통해 테스트 하는 방식. 

- ATDD 수용성 테스트는 E2E 테스트를 한다. 

  + Selenium -> WebDriver

  + Nightwatch


- Electron 

  + Node Based Desktop Application

  + View렌더링을 위한 브라우져를 가지고 있으므로 전통적은 Hybrid는 아니다. 전통적인 Hybrid는 view를 쓰기위해 webview를 쓰고 이에 대한 브라우져가 os에 설치되어 있어야 view 표현이 가능했다. 그러나 eletron은 view를 내장하고 있고 standalone으로 application구현이 가능하다.

  + render process (chrome) + main process (node) 간에 RPC통신을 한다. 


- Psyclone: Automated Dynamic Testing

  + https://github.com/firejune/psyclone 

  + Node Canvas: main process에서 수행됨

  + Environment: PTY.js, openCV (게임의 이미지 체크)




Javascript playground 세션


- Swift playground와 같은 형태이다.

- Runtime Context Visualizer 구현하기 

  > 내가 찍어 놓은 console.log를 추적 

  > let stack = new Error().stack 강제 로그 stack-trace 남기기

  > 외계어 스터디 (구글검색하면 나옴): 개발을 모르는 사람들에게 무언가 가르칠 때 힘들다. 코딩하는 것을 비쥬얼라이징 해보자. 

- V8 엔진은 Debugging이 가능한 API를 가지고 있다. 

  > node의 vm module을 사용: v8내에서 다양하게 쓰이는 것을 외부로 노출해 준다.

     runInContext, runInNewContext 등등

- node-inspector

  > IDE 수준의 code base로 꽤 큰 프로젝트

  > DEBUG=*node-debug app.js 하면 node debugging 을 inspector로 가능하다 

  > node v6.3.1 에서만 작동한다. node에 inspector를 merge하는 작업 진행중. 

     v8-debug : node <-> inspector간 내용

     devtools : inspector <-> chrome devtools간 내용


- Node debug mode 를 이용해 자바스크립트 내용을 축출한다

  > node --debug --debug-port=5859 --debug-brk app.js

      Debugger listening:5859

  > v8 debugging protocol using http

  > 전문의 body에 seq, type 이 들어간다. 

     type = request + response + event 포함 


- Node debugger Command 

  > continue : 코드 진행 next, in, out, min

  > backtrace : 코드가 멈춰있을 때 모든 정보를 가져온다 

  > frame : 방금 실행한 것을 이전 상태로 rollback에서 수행 가능하다 

  > setVariableValue : runtime의 로컬 변수를 직접 수정

  > lookup : 로컬 변수로 watching 모니터링 할 수 있다. 


해당 명령을 tcp로 node debugger에 쏴주면 된다. @node/lib/_debugger.js 가 위의 명령어를 사용하고 있다. 

  > npm install v8-debugger


- Javascript Playground 

  > 왼쪽 자바스크립트 코드 오른쪽 결과 값을 보여주기 화면을 제작한다

  > onResponse 핸들러에서 결과 값을 받는다. 

  > 코드의 의미 파악: 식, 문을 파악해야 함 -> Javascript Parser 필요, esprima 파서 

     esprima.parse(코드) 결과는 각 진행 수선의 type을 전달 하는 메타 정보를 준다

  > Runtime Context Visualizer

     https://github.com/ibare/jsplay


 


참조


http://techblog.daliworks.net/Nightwatchjs/ 

posted by 윤영식
2013. 11. 9. 07:08 My Services/PlayHub

PlayHub는 다양한 협업도구를 묶어서 부족한 2%를 채워주기 위한 서비스이다. 단순 매쉬업을 넘어서 정보를 자체 저장하고 확장할 수 있는 기능을 가지고 있다. 일반 협업도구에 어떤 불편한 점을 개선하려는 것일까?



PlayHub Flow

  - 로그인 하기 

    + Facebook 과 Google+ 를 통하여 로그인을 한다. 

    + OAuth를 통하여 얻은 정보를 사용자 정보로 사용한다 

    



  - 최초 로그인을 했을 때의 빈 화면

    + 좌측의 메뉴가 최초에는 열려있게 만드는 것이 좋겠다. 최대한 클릭수를 줄이는 경험을 주어야 한다 (AirBnB 참조)

    


  - 상단 좌/우 메뉴 버튼

    + 메뉴는 Side Slider Menu이다 (Sidr 또는 jQueryMobile 참조)

    + 좌측 메뉴 : 페이스북과 유사하다. Team:Project = 1:1 기준이다. 1개팀은 1개프로젝트만 가능하다

    + 우측 메뉴 : 등록한 친구 목록과 친구들과 채팅한 내역들이 나온다 

    


  - 팀 협업도구 연결하기 

    + 협업을 할 프로젝트 협업도구의 연결(로그인)과 팀명칭을 등록한다  

    


  - 팀 활동 내역

    + 등록한 팀을 선택하면 협업도구에 등록된 항목이 보인다

    + 좌측은 나의 Task가 우측은 팀원들의 Task 카드가 보인다 

    + 카드를 클릭하면 상세내역을 볼 수 있다   

    


  - 카드 상세내역 

    + Google Doc, DropBox, Trello 별로 보여지는 UI가 틀리게 나온다 

    + Google Doc은 기획자가 DropBox는 디자이너가 Trello는 개발자가 주로 사용함을 전제로 한다 

    + 카드형태별 하단에는 코멘트(카드에 대한 요청사항)를 달 수 있고 답변 할 수 있다 

    


  - 채팅하기 

    + 선택한 멤버들과 채팅을 한다 

    + 채팅 멤버추가는 팀단위 멤버와 상관없이 사용자가 선택한 사람과 채팅하는 것이다 

    


  - 메세지 확인하기

    + 자신의 카드에 코멘드(요청사항)를 달아놓은 것을 메세지에서 본다 

    + 자신에게 채팅신청이 왔으나 놓친 채팅 목록을 본다 

    


본 디자인은 개인적인 아이데이션이고 팀과 함께 더 좋은 방안과 UX/UI를 협의하여 완성해 갈 예정이다. 사람들과 대화를 통하여 정반합의 모델을 만들어 가는 재미가 쏠쏠하다



<참조>

  - mash up의 유래 

  - Good UI 전략

  - UX Design for HTML/CSS Mobile WebApp

posted by 윤영식
2013. 11. 9. 07:08 My Services/PlayHub

Angular 기반 SPA를 위한 Push 환경은 Node 기반의 Socket.io를 사용한다. Angular.js의 장점중 하나가 DI(Dependency Injection)이고 이를 Node에서 구현한 프레임워크인 express-train (축약, train)을 사용한다. train은 특정 폴더에 .js 파일을 놓으면 자동으로 DI되어 사용을 할 수 있게 해준다. 일정한 규약만을 지키면 개발 코드를 모듈화 하여 관리할 수 있고 테스트 할 수 있다. train은 express에 DI 기능을 접목해 놓은 것으로 보면 된다





1. Express-Train 설치하기 

  - 설치 : npm install -g express-train 

  - 새로운 Node 환경 프로젝트 생성

// train이 사용하는 기본 템플릿을 기반으로 자동으로 palette.fronend.node 디렉토리에 기본 폴더와 파일을 생성해 준다 

$ train new palette.frontend.node 

// 수행 http://localhost:4000 호출 

$ train run 

  - 디렉토리 구조 

    + app : auto-injected 로 표현된 것 .js 파일을 해당 디렉토리에 놓으면 다른 곳에서 파일 명칭으로 불러와서 (function parameter DI 방식) 사용을 할 수 있다 

    + bin : 이것은 node_modules/express-train 밑에 존재한다 

    + test : Mocha를 이용한다

    + public : Angular.js 기반으로 작성한 모든 static 파일들이 이곳에 놓일 것이다. 엄밀히 따지면 Distributed된 Frontend파일이 놓인다

app

  /controllers      -- application controllers (**autoinjected**)

  /lib                 -- application specific modules (**autoinjected**)

  /middleware    -- application middleware (**autoinjected**)

  /models          -- application models (**autoinjected**)

  /public            -- static content (html, js, css, etc) : SPA모든 파일을 해당 폴더 밑에 복사할 것이다  

  /views            -- view templates (loaded into express' view engine) : 서버단의 파일 jade, ejs, hbs 같은 서버 template 파일

  index.js           -- index file exports the express train application : train run 시에 수행되는 파일 based on Node.js


bin                   -- executable scripts : 

doc                  -- documentation

config              -- environmental configuration files : train 환경 설정 파일 

test                 -- tests : 서버 테스트 파일

package.json    -- npm package.json (needs to have express-train as a dependency)

  - train의 환경파일 : development와 production 환경파일을 구분함 

{

  "cookie_secret": "boggle at the situation",

  "session":{

    "key": "boggle at the situation",

    "secret": "boggle at the situation"

  },

  "client_port": 3000,

  "request_timeout": 1000,

  // RESTful 호출 접두사 Restanuglar 참조 

  "restful_api_version": "/api/v1",

  "server_name": "first",

  // REDIS 연결 Client Library 환경 설정

  "data_broker": {

    "port" : 6379,

    "host" : "localhost",

    "auth" : ""

  },

  // MongoDB 환경 설정

  "mongodb":{

    "uri": "mongodb://localhost/playhub_palette"

  },

  "playhub_channel_file": "channels.json",

  // Winston 에러 로그가 쌓일 MongoDB 정보 

  "winston_mongo": {

    "level": "error",

    "db": "playhub_palette",

    "host": "localhost",

    "port": 27017,

    "collection": "sd_logs"

  },

  // Winston 로그 파일의 명칭 설정

  "winston_file": {

    "filename": "sd.log",

    "exception": "sd_exception.log",

    "maxSize": 20480,

    "maxFiles": 12,

    "colorize": true

  },

  "character_encoding":"utf-8"

}



2. Express-Train 파일 사용하기 

  - auto-injected 되는 폴더에 모듈로 운용하고 싶은 .js 파일을 놓는다. 주로 MVC 파일과 Utility 또는 Service 파일들이다 

  - auto-inject 환경내역은 node_modules/express-train/lib/app.js 파일안에 이미 설정되어 있다.

// app.js 내역중 일부 

// autoinject라는 옵션을 주면 해당 지정된 폴더의 .js파일을 메모리에 로딩하고 DI를 한다 

// 이때 주의할 것은 상호 참조가 되지 않도록 하기 위한 폴더 전략이 중요하다. 위에서 부터 아래순서로 로딩되어 DI 된다 

var LOCATIONS = createApplication.locations = {

    pkg:{

        path: '../package.json'

    },

    config:{

        path: '../config'

    },

    logs:{

        path: '../logs'

    },

    models: {

        path: 'models',

        autoinject: true,

        aggregateOn: 'models'

    },

    views: {

        path: 'views'

    },

    lib: {

        path: 'lib',

        autoinject: true

    },

    controllers: {

        path: 'controllers',

        autoinject: true

    },

    pub: {

        path: 'public'

    },

    middleware: {

        path: 'middleware',

        autoinject: true

    }, 

   // 만약 app밑에 services폴더를 만든다면! 

    services: {

       path: 'services',

       autoinject: true

    },

}; 


// app.js 에서 express를 생성하고 views와 public 폴더를 강제 설정하고 있다

// _.each에서 autoinject 폴더의 모든 파일을 읽고 DI를 수행해 준다. 이때 DI되는 .js 파일은 Singleton 패턴이다 

// tree.constant로 저장된 객체를 DI 받을 수 있다

function createApplication(dir, locs) {

    catchErrors();


    var app = express(),

        locations = _.defaults((locs || {}), LOCATIONS);

        tree = new nject.Tree();


    app.set('views', path.join(dir, locations.views.path));

    app.set('public', path.join(dir, locations.pub.path));


    var config = loadConfig(path.join(dir, locations.config.path));

    tree.constant('config', config);


    _.each(_.where(locations, {autoinject: true}), function(location) {

        traverseAndRegister(path.join(dir, location.path), tree, location.aggregateOn)

    });


    //allow override of app

    if(!tree.isRegistered('app')) {

        tree.constant('app', app);  

    }


    //log path 하나 추가함 

    var logPath = path.join(dir, locations.logs.path);

    tree.constant('logPath', logPath);


    return tree.resolve();

}


  - 폴더 전략 : app.js에 설정된 순서에-위에서 아래로- 따라 로딩됨, 참조가 많은 것은 주로 service가 되지 않을까 함

    + lib/1level : 가장 기본적인 파일 참조하는 것이 없는 것들 - util, logger, db connection, constant

    + lib/2level : express-train의 파일들  - route, views, middleware 설정

    + lib/3level : 1, 2level의 .js를 사용하는 파일들 

////////

// 형식

module.exports = function(app, config, logger, ...) {

  // app, config, logger 등 파일이름을 대소문자 구분하여 넣으면 자동 DI를 해준다. 객체는 train에서 Singleton으로 관리한다 

}


/////////////////////////

// 예) lib/1level/logger.js

// MongoDB에 winston logger를 이용하여 에러발생 내역을 저장하거나 파일로 떨굼 


var winston = require('winston'),

  path = require('path');


module.exports = function(app, config, logPath) {


  winston.info('[1level: log config] init');

  require('winston-mongodb').MongoDB;


  var dbOpts = {

    level: config.winston_mongo.level,

    db: config.winston_mongo.db,

    collection: config.winston_mongo.collection,

    host: config.winston_mongo.host,

    port: config.winston_mongo.port

  };

  winston.info('[1level: log config] DB option is ' + JSON.stringify(dbOpts) );


  var fileName = path.join(logPath, config.winston_file.filename);

  winston.info('[1level: log config] general log : ' + fileName);

  var exceptionFileName = path.join(logPath, config.winston_file.exception);

  winston.info('[1level: log config] exception log : ' + exceptionFileName);


  var fileOpts = {

    filename: fileName,

    maxsize: config.winston_file.maxSize,

    maxFiles: config.winston_file.maxFiles,

    colorize: config.winston_file.colorize

  }


  var exceptionOpts = {

    filename: exceptionFileName,

    maxsize: config.winston_file.maxSize,

    maxFiles: config.winston_file.maxFiles,

    colorize: config.winston_file.colorize

  }


  var logger = new winston.Logger({

    transports: [

      new winston.transports.Console(),

      new winston.transports.File(fileOpts),

      new winston.transports.MongoDB(dbOpts)

    ],

    exceptionHandlers: [

      new winston.transports.Console(),

      new winston.transports.File(exceptionOpts),

      new winston.transports.MongoDB(dbOpts)

    ]

  });


//  testing

// logger.log(config.winston_mongo.level, '[log config] Test logging module completely');

//  logger.info('==============>> hi info');

//  logger.warn('==============>> hi warn');

//  logger.error('==============>> hi error');  <- MongoDB에도 쌓인다 


  return logger;

}


////////////////////////////////////////////////

// 예) lib/2level/ 또는 lib/2level에서 logger사용하기 

// lib/2level/views.js 파일에서 

// logger.js 파일에서 파일명칭을 - 대소문자 구분 - Function Parameter DI 해준다 

module.exports = function (applogger) {

  logger.info('[2level: view engine - jade] init');

  app.set('view engine', 'jade');

};




방법-1. Angular 프로젝트 배포후 Express-Train 프로젝트로 통합 

  - 엄밀히 따지면 합치는 시점은 개발이 다 된후 수행한다. 즉, SPA와 Node 파트의 Git 저장소를 틀리게 가져감을 전제로 한다 

    + SPA 저장소 : palette.frontend

    + Node저장소 : palette.frontend.node 

  - 개발이 된후 SPA와 Node 통합은 다음 순서로 하자 

    + Yeoman을 통하여 생성된 Angular 스케폴딩 파일은 별도로 개발한다 -> grunt build 수행 -> dist 폴더에 배포파일이 생성된다 

    + palette.frontend.node/app/public/ 와 palette.frontend.node/app/views 폴더 밑의 모든 파일을 삭제한다

    + palette.frontend.node/app/public/ 밑으로 dist/* 모든 파일을 복사한다 

// 폴더구조 

playhub

  |_ palette.frontend         (별도 git repository)

  |_ palette.frontend.node (별도 git repository)


// Angular 기반 frontend 파일 

playhub$ cd palette.frontend

playhub$ grunt build 


// Express-train에서 사용하지 않을 파일 삭제  

playhub$ cd ../palette.frontend.node/app/public

playhub$ rm -rf *

playhub$ cd ../views

playhub$ rm -rf *


// Angular 기반 SPA frontend파일을 Express-train의 app/public/ 폴더 밑으로 복사 

playhub$ cp -rf ../../../palette.frontend/dist/* ../public/

  - 테스트 하기 

$ cd palette.frontend.node

train run 

// http://localhost:4000/ 으로 호출한다 



방법-2. Express-Train 프로젝트를 Angular 프로젝트로 통합

  - Angular 프로젝트(palette.frontend)의 grunt, bower, yo, karma 기능을 그대로 사용한다 

  - Express-Train 프로젝트(palette.frontend.node)는 express-train기반으로 이미 스케폴딩된 서버단 애플리케이션이다. 

    즉 palette.frontend.node의 디렉토리 구조를 변경시켜보자  

// express-train 프로젝트로 이동하기 

$ cd palette.frontend.node


// express-train의 bin 디렉토리를 palette.frontend.node로 이동하기  

$ cd node_modules/

$ cd express-train/

$ ls -arlt

total 80

drwxr-xr-x   3 nulpulum  staff    102  9 17 17:20 test

-rw-r--r--   1 nulpulum  staff     90  9 17 17:20 index.js

-rw-r--r--   1 nulpulum  staff     82  9 17 17:20 .npmignore

-rw-r--r--   1 nulpulum  staff  13393  9 26 19:13 ReadMe.md

drwxr-xr-x   4 nulpulum  staff    136 11  8 14:14 bin

drwxr-xr-x   5 nulpulum  staff    170 11  8 14:14 boilerplates

-rw-r--r--   1 nulpulum  staff  14976 11  8 14:14 package.json

drwxr-xr-x   4 nulpulum  staff    136 11  8 14:14 lib

drwxr-xr-x  12 nulpulum  staff    408 11  8 14:14 node_modules

drwxr-xr-x  11 nulpulum  staff    374 11  8 14:14 .

drwxr-xr-x  13 nulpulum  staff    442 11  8 14:14 ..

// bin을 palette.frontend.node 루트로 이동시킨다 

$ mv bin ../../


// bin으로 들어가서 train run 명령을 수행 - 내부적으로 commander 모듈을 사용한다 

$ train run

module.js:340

    throw err;

          ^

Error: Cannot find module 'commander'

    at Function.Module._resolveFilename (module.js:338:15)

    at Function.Module._load (module.js:280:25)

    at Module.require (module.js:364:17)

    at require (module.js:380:17)

    at Object.<anonymous> (/Users/nulpulum/development/playground/playhub/palette.frontend.node/bin/train:3:15)

    at Module._compile (module.js:456:26)

    at Object.Module._extensions..js (module.js:474:10)

    at Module.load (module.js:356:32)

    at Function.Module._load (module.js:312:12)

    at Function.Module.runMain (module.js:497:10)


// 에러가 발생하므로 commander, underscore, handlebars, boilerplate 모듈을 설치한다 

$ cd .. && npm install commander --save 

$ npm install underscore --save

$ npm install handlebars --save

$ npm install boilerplate --save-dev

$ cd bin && train run 

module.js:340

    throw err;

          ^

Error: Cannot find module '../../lib/app'

    at Function.Module._resolveFilename (module.js:338:15)

    at Function.Module._load (module.js:280:25)

    at Module.require (module.js:364:17)

    at require (module.js:380:17)

    at Object.<anonymous>(/Users/nulpulum/development/playground/playhub/palette.frontend.node/bin/commands/console.js:4:13)

    at Module._compile (module.js:456:26)

    at Object.Module._extensions..js (module.js:474:10)

    at Module.load (module.js:356:32)

    at Function.Module._load (module.js:312:12)

    at Module.require (module.js:364:17)


// 에러 다시 수정 하기 

$ cd ../node_modules/express-train/

$ ls -alrt

total 80

drwxr-xr-x   3 nulpulum  staff    102  9 17 17:20 test

-rw-r--r--   1 nulpulum  staff     90  9 17 17:20 index.js

-rw-r--r--   1 nulpulum  staff     82  9 17 17:20 .npmignore

-rw-r--r--   1 nulpulum  staff  13393  9 26 19:13 ReadMe.md

drwxr-xr-x   5 nulpulum  staff    170 11  8 14:14 boilerplates

-rw-r--r--   1 nulpulum  staff  14976 11  8 14:14 package.json

drwxr-xr-x   4 nulpulum  staff    136 11  8 14:14 lib

drwxr-xr-x  12 nulpulum  staff    408 11  8 14:14 node_modules

drwxr-xr-x  10 nulpulum  staff    340 11  9 15:19 .

drwxr-xr-x  16 nulpulum  staff    544 11  9 15:29 ..


// express-train의 lib밑의 모든파일을 bin 밑으로 이동시킨다 

$ mv lib/* ../../bin/

// index.js 파일을 이동한 bin 디렉토리에 같이 놓는다 

$ mv index.js ../../bin/


// express-train 은 삭제한다 

$ cd .. && rm -rf express-train

$ cd ../../bin/

// 최종 lib이 bin 밑으로 들어갔다 

$ ls -alrt

total 32

-rw-r--r--   1 nulpulum  staff    64  9 17 17:20 runner.js

-rw-r--r--   1 nulpulum  staff  3594  9 27 14:06 app.js

drwxr-xr-x  11 nulpulum  staff   374 11  9 15:19 ..

-rw-r--r--   1 nulpulum  staff    89 11  9 15:56 index.js

-rwxr-xr-x   1 nulpulum  staff   785 11  9 16:02 train

drwxr-xr-x   7 nulpulum  staff   238 11  9 16:02 .

drwxr-xr-x   3 nulpulum  staff   102 11  9 16:08 commands


// commands 폴더에서 runt.js를 제외한 사용하지 않는 나머지 파일은 삭제하거나 나중을 위해서 다른 위치로 백업한다 

$ cd commands && rm console.js cycle.js new.js boilerplate.js


// commands 폴더의 run.js 안에 내역을 수정 한다 

// 기존 내역 : var appPath = path.join(process.cwd(), '../app/index.js');

// 수정 내역 

var appPath = path.join(process.cwd(), './index.js');


// lib밑에 있는 index.js가 가르키는 파일 수정 

// 기존 내역 : app: require('./lib/app')

// 수정 내역

// module.exports = {

//   app: require('./app.js')

// };


var paletteApp = require('./app.js');

module.exports = paletteApp(__dirname);


// palette.frontend.node 루트의 app 디렉토리명칭을 api 라고 변경한다 

$ cd ../../ && mv app api 

  

// 다음으로 직접 app.js안의 인식하는 디렉토리 경로를 상대경로로 변경한다 

$ cd bin && vi app.js

//위치 변경하기 

var LOCATIONS = createApplication.locations = {

    pkg:{

        path: '../package.json'

    },

    config:{

        path: '../config'

    },

    logs:{

        path: '../logs'

    },

    models: {

        path: '../api/models',

        autoinject: true,

        aggregateOn: 'models'

    },

    views: {

        path: '../api/views'

    },

    lib: {

        path: '../api/lib',

        autoinject: true

    },

    controllers: {

        path: '../api/controllers',

        autoinject: true

    },

    // 향후 palette.frontend의 grunt build시에 dist 폴더 밑으로 되는 것을 public 폴더로 바꿀 것이다 

    pub: {

        path: '../public'

    },

    middleware: {

        path: '../api/middleware',

        autoinject: true

    }

};


// api 디렉토리 밑에 있는 public 디렉토리를 루트로 옮겨서 테스트 해본다 

$ mv app/public .


// bin 디렉토리 밑에 있는 train 쉘 실행하기 

$ train run 

[express train application listening on 4000]


  - Express-Train기반의 서버구조를 만들었고, 이제 이것을 palette.frontend 쪽으로 옮겨보자 

// palette.frontend.node 프로젝트의 package.json 명칭을 변경 - 나중에 palette.frontend쪽의 package.json과 합치기 위함

$ mv package.json packate.json.node


// public 폴더는 삭제한다 

$ rm -rf public 


// 옮기기 

$ mv * ../palette.frontend/

mv: rename node_modules to ../palette.frontend/node_modules: Directory not empty

mv: rename test to ../palette.frontend/test: Directory not empty

$ cd node_modules

$ mv * ../../palette.frontend/node_modules/


// palette.frontend 에서 dist를 public으로 명칭 변경하여 테스트 

$ cd ../../palette.frontend

$ mv dist public 

$ cd bin

$ train run

[express train application listening on 4000]


// 이제 grunt build를 수행할 때 dist 디렉토리를 만드는 것이 아니라 public 으로 만들어 보자 

$ cd .. && rm -rf public 


// grunt 환경파일의 내역 수정 

$ vi Gruntfile.js

// 변경내역 

 grunt.initConfig({

    yeoman: {

      // configurable paths

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

      dist: 'public'  // 'dist'를 'public'으로 변경한다 

    },


// 다시 grunt로 빌드를 하면 public 폴더가 생성된다 

$ grunt build 

$ cd bin && train run 

[express train application listening on 4000]


// 최종 palette.frontend의 합친 구조

  - api : Node 서버 

  - app : SPA Angular

  - public : app 배포 디렉토리이면서 bin/train run 수행시 인식되는 서비스 폴더


// palette.frontend git 저장소에 push하기전에 package.json.node의 내용을 package.json에 통합한다 

{

  "name": "palette",

  "version": "0.0.1",

  "dependencies": {

    "express": "3.2.x",

    "express-train": "1.0.x",

    "connect-timeout": "latest",

    "connect-mongodb": "latest",

    "mongoose": "latest",

    "async": "latest",

    "express-hbs": "latest",

    "passport": "latest",

    "winston": "latest",

    "commander": "~2.0.0",

    "underscore": "~1.5.2",

    "handlebars": "~1.1.2",

    "nject": "~0.1.6"

  },

  "devDependencies": {

    "grunt": "~0.4.1",

    "grunt-contrib-copy": "~0.4.1",

    "grunt-contrib-concat": "~0.3.0",

    "grunt-contrib-coffee": "~0.7.0",

    "grunt-contrib-uglify": "~0.2.0",

    "grunt-contrib-compass": "~0.5.0",

    "grunt-contrib-jshint": "~0.6.0",

    "grunt-contrib-cssmin": "~0.6.0",

    "grunt-contrib-connect": "~0.5.0",

    "grunt-contrib-clean": "~0.5.0",

    "grunt-contrib-htmlmin": "~0.1.3",

    "grunt-contrib-imagemin": "~0.2.0",

    "grunt-contrib-watch": "~0.5.2",

    "grunt-autoprefixer": "~0.2.0",

    "grunt-usemin": "~0.1.11",

    "grunt-svgmin": "~0.2.0",

    "grunt-rev": "~0.1.0",

    "grunt-concurrent": "~0.3.0",

    "load-grunt-tasks": "~0.1.0",

    "grunt-google-cdn": "~0.2.0",

    "grunt-ngmin": "~0.0.2",

    "time-grunt": "~0.1.0",

    "karma-ng-scenario": "~0.1.0",

    "grunt-karma": "~0.6.2",

    "karma-script-launcher": "~0.1.0",

    "karma-chrome-launcher": "~0.1.0",

    "karma-firefox-launcher": "~0.1.0",

    "karma-html2js-preprocessor": "~0.1.0",

    "karma-jasmine": "~0.1.3",

    "karma-requirejs": "~0.1.0",

    "karma-coffee-preprocessor": "~0.1.0",

    "karma-phantomjs-launcher": "~0.1.0",

    "karma": "~0.10.4",

    "karma-ng-html2js-preprocessor": "~0.1.0",

    "mocha": "latest"

  },

  "engines": {

    "node": ">=0.8.0"

  },

  "main": "./app/index.js",

  "scripts": {

    "test": "grunt test",

    "start": "cd bin && train run",

    "server-test": "mocha test"

  }

}


// npm 명령으로 scripts 설정 내역 호출하기 

$ npm start

[express train application listening on 4000]


  - 최종 완성본 저장소 : MyPlayHub GitHub Repository

// git clone 하여 train run 수행시 다음과 같이 오류가 발생할 경우 

$ train run

env: node\r: No such file or directory


// dos2unix 패키지를 설치하여 수정하여 준다 

$ brew install dos2unix

==> Installing dos2unix dependency: gettext

==> Downloading http://ftpmirror.gnu.org/gettext/gettext-0.18.3.tar.gz

.. 중략 ..


$ dos2unix train

dos2unix: converting file train to Unix format ...

$ train run 

[express train application listening on 4000]



방법-3. Yeoman Generator FullStack을 통한 통합

  - Express + Angular의 통합

  - Angular는 클라이언트의 파일 전송과 암호화를 위하여 Lint와 압축을 위해 Grunt를 사용함 

  - Express는 서버단이므로 압축이 필요없음 

// FullStack generator 설치 

$ sudo npm install -g generator-angular-fullstack

// FullStackTest라는 애플리케이션 명칭으로 스케폴딩 생성

$ yo angular-fullstack FullStackTest

// 빌드하여 클라이언트 파일 Lint 및 압축 

// public 폴더밑으로 배포본이 만들어짐 

$ grunt build 

... 중략 ...

Elapsed time

useminPrepare:html                   25ms

concurrent:dist                          5s

autoprefixer:dist                        113ms

concat:public/scripts/modules.js  23ms

copy:dist                                  640ms

cdnify:dist                                 21ms

ngmin:dist                                263ms

cssmin:public/styles/main.css     33ms

uglify:dist                                  28ms

uglify:public/scripts/plugins.js      373ms

uglify:public/scripts/modules.js   134ms

usemin:html                             482ms

usemin:css                              152ms

Total                                        8s



<참조> 

  - Angular-Express-Train-Seed

  - Yeoman : generator-fullstack with angular and express

  - dos2unix 설치하여 사용하기

posted by 윤영식
2013. 10. 28. 16:49 My Services/PlayHub

SRS는 Software Requirements Specification 약어로 서비스를 만드는 내역의 처음과 끝이 담겨져 있다. "SRS의 중요성"이라는 블로그에서 SRS의 중요성을 인지하고, 몇번의 서비스을 하면서 SRS를 써오고 있다. 여기서 오해하지 말아야 할것은 SRS은 양식이나 포멧이 아니다. 즉, 한장으로 표현될 수도 있고, 몇장으로 정해진 양식에 따라서 써질 수도 있다. 처음은 문서-doc-파일에 정의해 보았으나 내용의 확인 및 업데이트가 불편하여 Trello에 SRS를 정의 하고 있다. 




Trello에 SRS 작성하기 

  - 보드를 하나 만든다 

  - 보드에 챕터별로 리스트를 만든다 

  - 챕터에 하위 Task를 만들어 정의된 내역을 편집하면 된다 

* 각 챕터에 대한 자세한 내역은 해당 파일을 참조한다 

SRS_iPhone_PIMSplus.doc

* 참조 URL : http://sep522.googlecode.com/svn-history/r88/trunk/ 의 doc/srs 밑에 문서가 있다  




  - Trello에 SRS를 작성하면 접근성과 유지보수성이 높아진다. SRS는 기획자, 디자이너, 개발자 누구나 접근하여 쉽게 찾고 업데이트 할 수 있어야 한다 

  - 한가지 아쉬운 점은 문서의 버전관리가 안된다는 점이다. 보완을 위하여 좀 더 자세한 내역은 Google Doc을 이용하고 링크를 걸어 놓는 방법을 사용하자 

  - Playground 멤버 PlayHub의 Trello SRS



<참조>

  - SRS의 중요성 - 전규현

  - PlayHub의 Trello SRS

posted by 윤영식
2013. 10. 24. 15:56 My Services/PlayHub

플레이허브(PlayHub, 이하 플브)는 요즘 제가 놀고 있는 플레이그라운드 Public 페북그룹의 첫번째 파일럿 프로젝트입니다. 어제 일을 잘 기억하지 못하는 습성으로 서비스 런칭과정을 하나하나 정리 해보려 합니다. "서비스디자인" 부터 "개발" "런칭"까지 진행 스토리와 개발 노하우를 공유할 수 있었으면 좋겠습니다. 




플레이그라운드 모임의 가치 

플레이그라운드는 플레이허브 파일럿 프로젝트를 수행하는 주체입니다. 모임의 가치는 다음과 같습니다

  - Fun
  - Interesting
  - Something Cool
  - Together

"재밌게 즐기면서 만들어 낸 서비스를 통해서 먼저 스스로 재미를 느끼고, 그렇게 만들어진 서비스를 통해서 수익을 만들어 내고, 덕분에 경제적 한계성에서 벗어나 재미없는 일로부터 벗어날 수 있는 환경을 만들고, 그러한 환경에서 보다 스스로에게 가치있고 의미있는 일을 해보자는 것"


  저는 여기에 하나의 명제를 더 던져보려 합니다. 

"이런 어지러운 세상의 문제점을 해결해 줄 수 있는 서비스를 사람들에게 제공하고 싶다"


  여하튼 이런 생각들에 동참하신 분이 초기에는 200명가량 되었는데, 적극적 참여의사를 밝힌 분들만 추려서 플레이그라운 Members 페북그룹이 결성되었습니다. 여기서 저는 앞으로 열심히 놀 계획을 가지고 있습니다. 참여를 원하시면 이곳을 참조하세요



플레이그라운드(Playground) 파일럿 프로젝트 

  파일럿 프로젝트의 의미는 "서로 알아가기""협업환경 익숙해지기" 입니다. 


  - 하지만 40명가량의 Member분들이 기획:디자인:개발 = 1:1:2 비율이고 의견을 조율해 본봐 서로간의 사용하는 협업도구가 상이하여 우리만의 통합 협업 허브 시스템이 필요하겠구나 생각했습니다. 

  - PlayHub는 PlayGround에서 사용하는 협업도구들의 중요항목을 모아서 기획,디자이너,개발자이 함께 사용할 수 있는 Hub 시스템입니다.

    + Trello : Agile Scrum 도구 

    + GitHub : Social Repository

    + Redmine or Mantis : Issue 시스템

    + DropBox : 파일 공유

    + Google Docs : 문서 공유 

   등에서 모은 데이터를 UX&UI 가미하여 시각화하는 작업을 거칠 것 같습니다. 


  저의 꿈은 "좋은 개발 협업 문화"를 만들고, "글로벌 소프트웨어"를 만드는 것입니다. 이것은 "소프트웨어 개발의 모든 것"라는 책을 통해 알게된 부분에 대한 결심과도 같습니다. 이제 우리에게 필요한 것은 이러한 문화를 만들어야 하고, 더 넓은 세상을 바라 보아야 한다고 생각합니다. 이것은 스마트폰으로 촉발되어 서비스 산업이 국지적인 것이 아니라 글로벌을 염두에 두고 진행되어야 하는 시대가 되었기 때문입니다. 



플레이허브(PlayHub)의 가치 

  좋은 개발 협업 문화 만들기를 위한 하나의 밑거름이 될 것이라 믿습니다

 

  - 이러한 가치는 적극적이고 자발적으로 참여하는 기획, 디자인, 개발자 분들의 노력으로 만들어 갈 수 있다고 믿습니다. 

  - 웹앱 서비스를 통하여 스마트기기 어디에서나 능동적 알람(Push)을 통하여 온라인 협업을 가능토록 해줄 것이라 믿습니다.  

  - 앞으로 이런 Software Engineer가 되어야 겠다 생각해 봅니다. 스스로의 실천이 꿈을 만들어 가리라 믿습니다 

1. 팀이 없는 것처럼 협업하라. 같이 일을 하게 되면 자리를 옮겨서 같이 해라.

2. 지시하지 말고 토론하라.

3. 자신이 무엇을 하고 있고, 무엇을 잘 하는지, 무엇을 하고 싶어하는지 알려라.

4. 핵심기능·기술에만 먼저 집중하여 작게 시작하여 완성하고, 자신을 성장시키며 제품도 같이 성장시켜라

5. 자신보다 더 똑똑한 사람을 뽑아라. 단 팀플레이어만.

6. 자신과 생각이 다른 사람들과 가까이 하라. 불편함을 우정으로 풀어라.

7. 빠른 성장과 진행을 위해 팀을 작게 만들어라.

8. 잘못되어 가는 것이 보이면 빨리 뒤집어라. 고칠것이 있으면 자신이 고쳐라.

9. 자신이 만들고 있는 것이 어떤 유저의 어떤 문제를 해결하는지 자신에게 물어라

10. 항상 유저를 찾고 그들과 소통하라

11. 지식 공유를 하지 않는다는 것은 자신이 성장하고 있지 않다는 이야기다.

12. 결코 어른이 되지 마라. 기술에 대한 열정과 마음은 그대로 남아 있어라.



<참조>

  - 개발자도 기획자다. 좋은 개발자 되기

posted by 윤영식
prev 1 next