블로그 이미지
Peter Note
Web & LLM FullStacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 6. 5. 14:06 Middleware, Cloud/WAS

JBoss 나 WebLogic에서 Oracle을 연결할 때 Oracle이 RAC(Oracle Real Application Clustering)으로 구성이 되어 있다면 이에 맞는 DB Pool 설정을 해야한다 



1. Oracle Clustering Config

  - 환경설정

<connection-url>

jdbc:oracle:thin:@(description=(address_list=(load_balance=on)(failover=on)(address=(protocol=tcp)(host=host1)(port=1521))(address=(protocol=tcp)(host=host2)(port=1521)))(connect_data=(service_name=xxxxsid)(failover_mode=(type=select)(method=basic))))

</connection-url>



2. JBoss Config

  - 환경파일 : <domainName>/deploy/oracle-ds.xml 

 <datasources>

   <local-tx-datasource>

  <jndi-name>cmstDs</jndi-name> 

  <connection-url>

jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST = (LOAD_BALANCE = off)(FAILOVER = on)(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))(ADDRESS = (PROTOCOL = TCP)(HOST = 128.0.0.1)(PORT = 1521)))(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = PGTMO)(FAILOVER_MODE =    (TYPE = SELECT)(METHOD = BASIC))))

</connection-url> 

  <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> 

  <user-name>yun</user-name> 

  <password>dowon</password>


  <min-pool-size>30</min-pool-size>

  <max-pool-size>50</max-pool-size>


  <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>

  <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>


   <query-timeout>300</query-timeout>

   <background-validation-minutes>5</background-validation-minutes>

   <blocking-timeout-millis>10000</blocking-timeout-millis>


  </local-tx-datasource>

 </datasources>



3. Weblogic Config

  - 환경파일 : <domainName>/config/jdbc/xxxx-jdbc.xml

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

<jdbc-data-source xmlns="http://xmlns.oracle.com/weblogic/jdbc-data-source" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/jdbc-data-source http://xmlns.oracle.com/weblogic/jdbc-data-source/1.2/jdbc-data-source.xsd">

  <name>youngsik-test</name>

  <jdbc-driver-params>

    <url>

jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=OFF)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=128.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=PGTMO)))

    </url>

    <driver-name>oracle.jdbc.OracleDriver</driver-name>

    <properties>

      <property>

        <name>SendStreamAsBlob</name>

        <value>true</value>

      </property>

      <property>

        <name>user</name>

        <value>MOBICON</value>

      </property>

      <property>

        <name>oracle.net.CONNECT_TIMEOUT</name>

        <value>10000</value>

      </property>

    </properties>

    <password-encrypted>dowon-manse</password-encrypted>

  </jdbc-driver-params>

  <jdbc-connection-pool-params>

    <initial-capacity>1</initial-capacity>

    <connection-creation-retry-frequency-seconds>10</connection-creation-retry-frequency-seconds>

    <test-frequency-seconds>120</test-frequency-seconds>

    <test-connections-on-reserve>true</test-connections-on-reserve>

    <test-table-name>SQL SELECT 1 FROM DUAL</test-table-name>

    <seconds-to-trust-an-idle-pool-connection>0</seconds-to-trust-an-idle-pool-connection>

  </jdbc-connection-pool-params>

  <jdbc-data-source-params>

    <jndi-name>jdbc/oracle/yun</jndi-name>

    <global-transactions-protocol>None</global-transactions-protocol>

  </jdbc-data-source-params>

</jdbc-data-source>



<참조>

  - Weblogic DB Configuration 이해하기

  - Oracle Cluster config

  - JBoss Deploy 및 ClassLoader구조와 Hibernate 사용하기 

  - JBoss 5 환경설정 및 튜닝 (필독)

posted by Peter Note
2013. 6. 3. 11:44 HTML5, CSS3/jQuery

요즘 들어 솔루션, 서비스를 만들때 늘 구글의 UX를 떠올린다. UI 보다 먼저 UX를 생각하게 되고 어떻게 하면 좋은 사용자 경험을 줄 수 있을까 생각한다. 구글의 10가지 디자인 원칙이라는 글이 있어서 잠시 요약해 본다. 제품/서비스 UX 설계시 이와 같은 관점에서 다시 생각해 보자. 



구글의 UX팀 목표

  - 실용적이면서 빠르고

  - 단순하면서 매력적이고

  - 혁신적이면서 보편적이고

  - 유익하면서 아름답고

  - 신뢰할 수 있으고 품위있는 

  디자인을 창작하는 것을 목표로 하고 있다. 


1. Useful

  - 사람을 향합니다. 그들의 삶과 일과 꿈을 위하여 

  - 사람이 원하지 않는 것을 강제하지 않는다

  - 보다 빠르고 창의적으로 일하게 한다


2. Fast

  - 천분의 일초까지 헤라린다

  - 구글의 페이지를 날씬한 코드와 주의깊게 선택된 이미지를 사용한다 

  - 불필요한 클릭, 타이핑, 단계 활동들을 제거된다

  - 필수 기능과 문자들은 가장 찾기 쉬운 위치에 배치된다

  - 단 한번의 정보만을 요청하고 단순한 기본값을 포함한다 


3. Simple

  - 단순함은 사용성, 속도, 시각적 호소력과 접근성을 포함하여 디자인의 많은 소요들에 작용한다

  - 단순함은 제품의 근본적인 기능에 대한 설계로 시작하지 풍부한 기능을 창작하는것으로부터 시작하지 않는다


4. Engaging

  - 많은 사람들을 위한 설계는 최소한의 공통분모를 위한 디자인을 의미하지 않는다

  - 고급 사용자들이 제품을 소개하는 동안 초심자가 가슴벅찬 첫 경험을 하도록 이끄는 것이다 

 

5. Innovative 

  - 혁신을 두려워하지 않는다 

  - 사용자의 욕구를 만족시켜주기만 한다면 혁신적이고 모험적인 디자인을 장려한다 


6. Universal 

  - 모두를 위한 설계를 한다 

  - 어떤 장치나 방법으로도 접근 가능하게 하며 현실에 대응 가능한 의미있는 제품을 디자인한다

  - 정보의 보편적 접근에 대한 사명은 구글의 제품이 보조기술을 지원토록 한다 

  

7. Profitable 

  - 사업계획에 도움이 된다 

  - 사용자들의 목표와 사업적인 고려를 한결같이 통합한다

  - 구글의 사용자를 감소시킨다면 제품으로부터 수익을 증가시키려고 노력하지 않는다. (광고)


8. Beautiful 

  - 주의를 산란시키지 않고 눈을 즐겁게 한다

  - 긍정적인 첫인상은 사용자를 편안하게 하고 믿음을 주며 자신들의 제품으로 만들 수 있다는 확신을 갖게 한다 

  - 최소한의 장식, 군더더기 없는 디자인은 빠르게 로드되고 사용자들의 목표달성에 방해를 주지 않는다 

  - 고상한 단순함 : 심미적 디자인은 사용성을 증가시키고 사용자를 즐겁게 한다 


9. Trustworthy

  - 사람들에게 확신을 주어야 한다 

  - 제품을 사용하는 사람들로부터 장기적인 신뢰를 얻어야 한다 

  - 경쟁자와 공헌자들의 링크 또한 포함시키며 세상을 향해 열려 있다 

  - 사용자들의 데이터를 보호한다 


10. Personable

  - 인간미를 보탠다 

  - 문자와 디자인 요소들은 친근하고 빠르고 재치가 있으면서 지겹지 않고 거만하지 않다 

  - 텍스트는 사람들에게 직관적이고 동일한 경험을 제공한다 

 

사용자들의 피드백에 열려있고 이에 반응하여 실행합니다. 그에 따라 혁신과 개선은 지속될 것입니다.  



<참조>

  - 원문 : http://fillrider.egloos.com/254736

  - UI 와 UX 차이 : 수화물 예제를 통한 설명 (필독)

  - 모바일에서의 UX 고려 사항 10가지 

posted by Peter Note
2013. 6. 1. 12:05 Meteor

미티어의 중요 개념중 하나인 Reactive Programming을 이해하자. 



1. 개념

  - 위키피디아

In computingreactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow.


프로그램에서 쉽게 동적 데이터 흐름을 만들어서 데이터가 변하면 자동으로 전파되게 하는 기술. 예로 서버에서 데이터가 변하면 모든 클라이언트쪽으로 변경 데이터를 Push 하여 준다.


  - 백본에서 이야기하는 개념도 

    오른쪽 클라이언트<->서버간의 흐름에서 

    + Output : reactive ( == push )

    + Input : interactive ( == polling )

 

  - 미티어의 Reactive 개념

    + 미티어서 reactive가 동작하는 코드영역

       > Template

       > Meteor.render 또는 Meteor.renderList : DOM 동적으로 다시 그리기  

       > Deps.autorun : 의존관계 변경시 자동 재수행 - reactive computation을 수행한다 (Deps maybe is Dependency)



2. Todos 예제 리팩토링하기 

  - 예제 보기 

  

  - 예제 설치 및 실행 (참조)

$ meteor create --example todos

$ cd todos

$ meteor


  - 파일 쪼개기 

미티어는 client, server 폴더 밑으로 자유롭게 폴더를 만들 수 있다. 즉, 미티어가 실행되면 client, server디렉토리를 스캔하여 자동 로딩한다. 또한 파일간의 참조 관계에 대한 환경 설정 필요없이 name기반으로 자동 연결한다. 마치 WAS(예로 JBoss같은)가 lib를 스캐닝하여 자동 로딩하고  *.war파일을 인식하여 애플리케이션 컨텍스트를 만들어 주는 것과 같다. 이렇게 본다면 미티어는 서비스 개발을 위한 미들웨어 스택이라 생각해도 무방하지 않을까 한다. 

    + todos.html 파일의 Template 영역을 쪼갠다 : partials 디렉토리 만들기 -> list.html, tag_filter.html, todo.html, todo_item.html 로 쪼개기

    

   

    + todos.js  파일 쪼개기 : js 디렉토리 만들기 -> list.js, tag_filter.js, todo.js 로 쪼갠다

      > 주의 : Meteor.*에 관련된 코드가 있는 것은 그대로 놓는다.

      > todos.js 안에 var listHandle 의 var를 제거 

      > todos.js 안에 var todosHandle 의 var를 제거 

    


      > todos.js 에서 두개의 펑션을 짜른다 -> 루트에 lib 디렉토리 생성 -> common.js 안에 붙인다.

        okCancelEvents, activateInput앞의 var를 제거한다.

    


  - 쪼갠 파일을 인식하는 순서 (참조)

  • Files in the lib directory at the root of your application are loaded first. Files that match main.* are loaded after everything else.   (애플리케이션 루트에 lib를 만들고 그곳에 .js를 만들면 가장 먼저 인식 - WAS의 lib와 유사)

  • Files in subdirectories are loaded before files in parent directories, so that files in the deepest subdirectory are loaded first (after lib), and files in the root directory are loaded last (other than main.*). (부모 디렉토리가 먼저 인식된 다음 하위 자식 디렉토리가 그 인식됨) 

  • Within a directory, files are loaded in alphabetical order by filename. (같은 디렉토리는 파일 알파벳 순서 인식)

These rules stack, so that within lib, for example, files are still loaded in alphabetical order; and if there are multiple files named main.js, the ones in subdirectories are loaded earlier.


  - 짜잔 : 할일을 넣으면 바로 MongoDB로 insert 된다

  



3. Todos의 Reactive 이해하기 

  - 서버에서 publish -> 클라이언트에서 subscribe 한다.

  - 서버 영역의 publish 

    + server/publish.js 안에 Meteor.publish 등록

      > MongoDB 의 데이터가 업데이트 되면 자동 인식하여 subscribe 한 곳으로 publish 해 준다

      > lists는 MongoDB의 컬렉션이다  

    

     > mongo shell 에서 강제로 넣어보면 클라이언트 UI 단이 자동 live reloading 된다

$ meteor mongo

MongoDB shell version: 2.4.3

connecting to: 127.0.0.1:3002/meteor

> show collections

lists

system.indexes

todos

> db.lists.find();

{ "name" : "Meteor Principles", "_id" : "fEwuoo7Ja5quzPwa4" }

{ "name" : "Languages", "_id" : "fBtKCjyJxLTdMWXet" }

{ "name" : "Favorite Scientists", "_id" : "Jnr3u6gSNh26uRseH" }

> db.lists.insert({ name: 'Dowon todo' });


// 몽고 쉘에서 insert 하는 순간 "Dowon todo"가 들어간다


// 또는 클라이언트 브라우져에서 (크롬 DevTool에서 직접 insert 하기)

// DevTool콘솔에서 insert 를 하면 좌측 메뉴가 자동으로 업데이트되어 나온다 

  

  - 클라이언트 영역의 subscribe

    + 'lists' 컬렉션에 대한 subscribe를 등록하고 데이터 변경으로 서버에서 publish를 하여주면 등록한 callback function을 수행한다

    + Meteor.subscribe('lists', <CallBack Function>)

  

   + 쪼갠 list.js 소스 파악 : Template.lists.loading시에 listsHandle.ready() 를 수행하여 좌측 메뉴를 보여준다 

  



<참조>

  - 파일을 인식하는 순서에 대한 글(필독)

  - 미티어 Reactive 소스 처리에 대한 이해

  - 미티어 채팅(Chatting) 예제

  - todos 쪼갠 프로젝트 파일 다운로드 

todos.tar


posted by Peter Note
2013. 5. 29. 14:16 Middleware, Cloud/WAS

제이보스에서 버전별 Session 객체의 타임아웃 설정하는 곳은 어디일까?


1. 버전별 설정 위치 

  - 기본 설정사항 

JBoss 6.x

deploy/jbossweb.sar/web.xml

JBoss 5

deployers/jbossweb.deployer/web.xml

JBoss 4.3
deploy/jboss-web.deployer/conf/web.xml
Earlier versions

deploy/jbossweb-tomcat55.sar/conf/web.xml


    <!-- ==================== Default Session Configuration ================= -->

   <!-- You can set the default session timeout (in minutes) for all newly   -->
   <!-- created sessions by modifying the value below.                       -->

   <session-config>
      <session-timeout>30</session-timeout>
   </session-config>



2. 재설정 방법

  - 컨텍스트별 설정 변경

  - WEB-INF/web.xml 에 동일 태그로 설정한다.  (단위, min)

  - 값이 0 이면 영구적으로 보관 즉, WAS 재기동전까지...

Add the same tags as above to WEB-INF/web.xml.  Here is the DTD for further explanation:

<!--
The session-config element defines the session parameters for
this web application.

Used in: web-app
-->
<!ELEMENT session-config (session-timeout?)>

<!--
The session-timeout element defines the default session timeout
interval for all sessions created in this web application. The
specified timeout must be expressed in a whole number of minutes.
If the timeout is 0 or less, the container ensures the default
behaviour of sessions is never to time out.

Used in: session-config
--> 

<!ELEMENT session-timeout (#PCDATA)>


  - 또는 애플리케이션에서 호출해도 된다. 

    + 만일 web.xml 설정을 해도 제대로 동작되지 않으면 하드코딩 되어 있는지 확인한다 (참조1 , 참조2)

    + 해당 코드를 넣으면 전역으로 반영이 된다

HttpSession.setMaxInactiveInterval(int seconds)



<참조>

  - 원문 : 세션 Timeout 설정

  - 세션 Timeout 설정하기 정리

posted by Peter Note
2013. 5. 28. 16:32 MongoDB/Prototyping

Mongoose를 사용하여 개발하는중 외래키를 어떻게 잡는지 궁금하여 찾아보았다. 몽구스 현재 버전은 3.6.11 - GitHub



1. 외래키 잡기 

  - 메뉴얼 : http://mongoosejs.com/docs/populate.html

    + _id가 Number이므로 story에서도 Number로 타입을 가져가야 한다 

var mongoose = require('mongoose') , Schema = mongoose.Schema var personSchema = Schema({ _id : Number, name : String, age : Number, stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] // 여러 이야기 - 배열 }); var storySchema = Schema({ _creator : { type: Number, ref: 'Person' }, // 글쓴이 한 사람 title : String, fans : [{ type: Number, ref: 'Person' }] // 해당 글에 대한 여러 팬들 - 배열 }); var Story = mongoose.model('Story', storySchema); 

var Person = mongoose.model('Person', personSchema);



2. 플러그인

  - 플로그인은 mongoose의 middleware 기능을 이용하여 만들 수 있다. 즉, 몽고디비에 대한 쿼리가 진행되기 전에 pre action을 수행하고 next할 수가 있는 것이다. Connect 프레임워크의 next와 유사하다고 보면 된다.

  - 플러그인 검색 사이트 : http://plugins.mongoosejs.com

    + 해당 사이트에서 검색을 통하여 플러그인을 찾을 수 있다. 

    + increment로 검색을 수행하여 auto increment 플러그인 찾음.

      https://github.com/mariodu/mongoose-id-autoinc

var dbName = 'id_autoinc_example',
    mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    db = mongoose.createConnection('127.0.0.1', dbName),
// 모듈 로딩
    autoinc = require('../index');

// 모듈 초기화
// Counter 테이블이 만들어 진다. 만일 Sequence 관리용 다른명칭을 주고 싶다면 
// autoinc.init(db, 'AnotherName');
autoinc.init(db);

var UserSchema = new Schema({
  name: String,
  email: String
});

// 플로그인 설정
UserSchema.plugin(autoinc.plugin, {
  model: 'User',
  field: 'seqnumber', // field 정보 안주면 기본 _id 를 Number의 sequence field로 사용한다
  start: 100,
  step: 10
});

var User = db.model('User', UserSchema);

console.log('Database: ' + dbName);
console.log('Collection: ' + User.collection.name);

var user_1 = new User({
  name: 'Dowon',
  email: 'dowon@google.com'
});
user_1.save(function (err, res) {
  console.log('New record added:');
  console.log(res);
});
var user_2 = new User({
  name: 'YoungSik',
  email: 'youngsik@apple.com'
});
user_2.save(function (err, res) {
  console.log('New record added:');
  console.log(res);
  mongoose.disconnect();

});


  - StackOverFlow 에서 도움을 받자 

    + http://stackoverflow.com/questions/tagged/mongoose



3. Smart Dashboard 외래키와 _id 숫자 증가 시키기 

  - service 모듈에서 mongoose와 db connection을 만들어서 전달 받았다. db connection을 두번 만들면 mongoose에서 오류 뱃음.

  - Dashboard안에는 여러 Component가 존재하고 Component는 여러 Dashboard에서 사용 될 수 있다

  - 하기와 같이 사용을 하면 mongo shell 을 통하여 direct insert를 하면 안된다 (주의)


<참조>

  - Connect의 next() 이해하기 (필독)

  - Auto Increment 소스

posted by Peter Note
2013. 5. 25. 17:11 Meteor

미티어는 Full Stack Framework를 지향한다. 미티어는 클라이언트와 서버단의 코드를 통합적으로 지원하며 Node.js와 MongoDB를 기본 스택으로 사용한다. 따라서 단일 언어로 자바스크립트를 사용한다. 미티어 개념을 이해하고 설치 사용해 본다.


1. 미티어 개념이해 

  - 사용하는 서브 프레임워크들

    + Connect, SocketJS, Handlebars, Stylus, CoffeeScript

    + Node.js, MongoDB

  - 박준태님의 파워포인트

    + 현재 버전 : v0.6.3

    + 윈도우 버전 설치 존재 



2. 설치하기 

  - 설치 : meteor를 설치하면 자체적으로 node, mongodb 의 binary가 함께 설치된다 (Linux, Mac기준)

$ curl https://install.meteor.com | /bin/sh


// 설치된 경로 : ~/.meteor 폴더 밑으로 설치됨

$ ls 

 meteor -> tools/latest/bin/meteor

 packages

 tools

 releases


// mongodb binary와 bin 밑에 node binary가 존재하여 별도로 수행한다

// 기본 포트는 node - 3000 port, mongodb - 3002 port 를 사용한다 

$ cd tools/latest && ls

LICENSE.txt examples launch-meteor mongodb tools

bin include lib share


  - 웹애플리케이션 하나 만들고 수행하기 

$ meteor --help

sage: meteor [--version] [--release <release>] [--help] <command> [<args>]


With no arguments, 'meteor' runs the project in the current

directory in local development mode. You can run it from the root

directory of the project or from any subdirectory.


Use 'meteor create <name>' to create a new Meteor project.


Commands:

   run             [default] Run this project in local development mode

   create          Create a new project

   update          Upgrade this project to the latest version of Meteor

   add             Add a package to this project

   remove          Remove a package from this project

   list            List available packages

   bundle          Pack this project up into a tarball

   mongo           Connect to the Mongo database for the specified site

   deploy          Deploy this project to Meteor

   logs            Show logs for specified site

   reset           Reset the project state. Erases the local database.

   test-packages   Test one or more packages


See 'meteor help <command>' for details on a command.


$ meteor create webapp && cd webapp

$ meteor run 또는 meteor


// 수행을 하면 어떤 프로세스가 수행이 될까?

// node 프로세스는 2개가 수행된다 (3000 port listen)

$ ps -ef | grep node

  ~/.meteor/tools/11f45b3996/bin/node /Users/nulpulum/.meteor/tools/11f45b3996/tools/meteor.js

  ~/.meteor/tools/11f45b3996/bin/node /Users/nulpulum/prototyping/meteor/webapp/.meteor/local/build/main.js --keepalive


// mongodb 가 3002 port로 webapp 수행한 위치 밑으로 mongodb file system 저장소를 자동으로 셋팅한다 

$ ps -ef | grep mongodb

~/.meteor/tools/11f45b3996/mongodb/bin/mongod --bind_ip 127.0.0.1 --smallfiles --port 3002 --dbpath /to/path/webapp/.meteor/local/db


  - 브라우져에서 http://localhost:3000/ 을 호출하면 기본 파일인 webapp.html이 수행된다 

  - 미티어가 사용하는 MongoDB쪽을 살펴보자 

// 미티어가 사용하는 

$ meteor mongo

MongoDB shell version: 2.4.3

connecting to: 127.0.0.1:3002/meteor

> show dbs

local 0.03125GB

meteor (empty)  <--- meteor 저장소가 새롭게 생성되었다 (주의 : 3번의 기존 프로그램 수정하기 해야 나옴)

> use meteor

switched to db meteor

> show collections


  - 애플리케이션을 만들고 다음과 같이 하위 디렉토리를 만들면 자동으로 파일을 인식한다 (참조)

webapp 디렉토리 밑으로 

  client      – This folder contains any JavaScript which executes only on the client.

  server    – This folder contains any JavaScript which executes only on the server.

  common – This folder contains any JavaScript code which executes on both the client and server.

  lib          – This folder contains any JavaScript files which you want to execute before any other JavaScript files.

  public     – This folder contains static application assets such as images.

  .meteor  - 미티어가 자동으로 만들어주는 폴더 

    local - build - app 밑에 webapp.js 가 존재하여 해당 파일을 사용함 

  



3. 기존 프로그램 수정해 보기 

  - 해당 동영상을 보고서 수정해 본다 


  - webapp.html 기존코드 삭제 후 수정

<head>
<title>webapp</title>
</head>
 
<body>
hi dowon
> : encoding sign sleeping
{{> color_list }}
</body>
 
<template name="color_list">
{{#each colors }}
<ul>
{{> color_info }}
</ul>
{{/each }}
 
<div class="footer">
<button>Like!</button>
</div>
</template>
 
<template name="color_info">
<li class="{{maybe_selected}}">
{{likes}} people like {{ name }}
</li>
</template>


  - webapp.js 기존코드 삭제 후 수정

// create common store collections to mongodb
Colors = new Meteor.Collection("colors");
 
if (Meteor.isClient) {
// UX Coding
Template.color_list.colors = function() {
// likes: -1 = descending
// name: 1 = ascending
// return Colors.find({},{sort:{likes:-1, name:1}});
return Colors.find({},{sort:{name:1}});
}
 
Template.color_info.maybe_selected = function() {
console.log('---> 2: ' + this._id);
return Session.equals('session_color', this._id) ? "selected" : '';
}
 
// UX event
Template.color_info.events = {
'click' : function() {
console.log('---> 1: ' + this._id);
Session.set('session_color', this._id);
}
}
 
Template.color_list.events = {
'click button' : function() {
// 정보를 업데이트하면 동시에 열려 있는 브라우져 정보가 업데이트 된다
Colors.update(Session.get('session_color'), {$inc: {likes:1}})
}
}
}
 
if (Meteor.isServer) {
// 서버를 시작한다
Meteor.startup(function () {
// code to run on server at startup
});
}


  - webapp.css 수정

.selected {
background-color: yellow;

}


 - 테스트

    + Like! 버튼을 누르면 양쪽의 브라우져로 숫자 증가값이 Multicasting 된다. 

    + 크롬의 Dev Tool에서 직접 insert 하여 테스팅. ex) Colors.insert({ likes : 1, name : 'blue' })



4. 클라우드에 배포하여 테스트하기

  - 클라우드에 배포하기 : 스마트 패키징

// xxx.meteor.com 포멧으로 자신만의 xxx를 지정한다

$ meteor deploy dowon-color.meteor.com

Deploying to dowon-color.meteor.com.  Bundling...

Uploading...

Now serving at dowon-color.meteor.com


  - 브라우져에서 dowon-color.meteor.com을 호출한다 

    + 크롬 DevTools에서 MongoDB  API와 똑같이 insert를 한다. (클라이언트에서 서버의 MongoDB로 저장!!!)

    



<참조>

  - 미티어 한글 번역 : http://docs-ko.meteor.com/

  - 미티어 디렉토리 구분하여 프로젝트 만들기

  - 채팅프로그램 만들기

  - Introduction to Meteor (필독)

  - 미티어는 이미 백본에 대해서 패키지로 통합을 하였다. AngularJS에 대한 통합은 현재 투표중이다.

     + meteor와 angularjs에 대한 통합 시도 소스

     + 미티어 로드맵에서 Wishlist에서 볼 수 있다. (Trello에서 로드맵을 추천받고 있습니다. 저도 한표. 현재 총 52표!)

     

posted by Peter Note
2013. 5. 21. 17:08 Middleware, Cloud/WAS

OOM(OutOfMemory) 에러가 발생하거나 Heap Dump 로그를 떨구고서 WAS가 죽을 경우 메모리설정에 대한 이슈를 어떻게 해결할지 알아보자 


1) JVM 메모리 운영

  - Heap = Young Generation + Old Generation + Permanent Generation(PermSize=MethodArea)

    + Young 에서 신규 생성되어 오래된 객체가 Old로 넘어감

    + Young 에서 바로 사용되지 않으면 Minor GC

    + Old로 넘어간 후 Old에서 더 이상 사용되지 않으면 Full GC

    + Perm 영역은 상수영역으로 GC 대상은 아니나 간혹 일어남


  - Young Generation = Eden + Survivor (2개)  로 구성

    + Eden 에서 사용되어진 것은 Survivor로 넘어가고 다시 Old 영역으로 넘겨진다  



2) jstat 명령을 통한 GC 모니터링

  - $JDK_HOME/bin/jstat 명령어 이용 

  - jstat 옵션들 : 출처 (http://helloworld.naver.com/helloworld/helloworld/6043)

옵션

기능

gc

각 힙(heap) 영역의 현재 크기와 현재 사용량(Eden 영역, Survivor 영역, Old 영역등), 총 GC 수행 횟수, 누적 GC 소요 시간을 보여 준다.

gccapactiy

각 힙 영역의 최소 크기(ms), 최대 크기(mx), 현재 크기, 각 영역별 GC 수행 횟수를 알 수 있는 정보를 보여 준다. 단, 현재 사용량과 누적 GC 소요 시간은 알 수 없다.

gccause

-gcutil 옵션이 제공하는 정보와 함께 마지막 GC 원인과 현재 발생하고 있는 GC의 원인을 알 수 있는 정보를 보여 준다.

gcnew

New 영역에 대한 GC 수행 정보를 보여 준다.

gcnewcapacity

New 영역의 크기에 대한 통계 정보를 보여 준다.

gcold

Old 영역에 대한 GC 수행 정보를 보여 준다.

gcoldcapacity

Old 영역의 크기에 대한 통계 정보를 보여 준다.

gcpermcapacity

Permanent 영역에 대한 통계 정보를 보여 준다.

gcutil

각 힙 영역에 대한 사용 정도를 백분율로 보여 준다. 아울러 총 GC 수행 횟수와 누적 GC 시간을 알 수 있다.


  - gcutil / gccapcity 사용 예

    + gcutil : WAS 기동후 FGC(Full GC 건수)는  230회 발생하였고, FGCT(Full GC 수행시간)은 2302초로 거의 10초가 소요되었다

                 Full GC 수행마다 10초의 시간

    + gccapacity : New 영역 사용크기(NGCMN) 이 2,097,152 (즉 2Gbytes)이고 Old 영역 사용크기(OGCMN)가 3,145,728 (즉 3GBytes) 가량이 된다 

[jboss@dowon ~]$ ps -ef |grep java

jboss    13090 13053  8 Mar27 ?        04:28:28 /usr/java/jdk1.6.0_31/bin/java -Dprogram.name=run.sh -server .. 중략..


[jboss@dowon ~]$ jstat -gcutil 13090

  S0     S1     E        O       P     YGC   YGCT    FGC   FGCT      GCT   

  0.76   0.00  85.57  86.24  26.88   1260  644.013   230   2302.259   2946.273


[jboss@dowon ~]$ jstat -gccapacity 13090

 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC 

2097152.0 2097152.0 2097152.0 430656.0 412096.0 1254400.0  3145728.0  3145728.0  3145728.0  3145728.0 524288.0 524288.0 524288.0 524288.0   1260   230


  - 간단한  GC Check Shell Script 작성해 보았다 

    + weblogic.Server (jboss: org.jboss.Main) 부분을 WAS나 JAVA Process 환경에 맞게 변경하여 사용한다

    + WAS가 기동된 이후 Full GC 평균 시간 = FGCT/FGC  : 만일 3초이상이면 점검 대상으로 지정

#!/bin/sh


# [GC Statistics after WAS started]

# config

#   interval : 3 sec

#   count : 2


echo ""

echo "[GC statistics after WAS is started]"

echo "----------------------------------------"

echo " S0/S1: Survivor 0/1 (KB)"

echo " E    : Eden (KB)"

echo " O    : Old area size (KB)"

echo " P    : Permanent area size (KB)"

echo " YGC  : Young Generation GC Count"

echo " YGCT : Young Generation GC Total Time"

echo " FGC  : Full GC Count"

echo " FGCT : Full GC Total Time"

echo " GCT  : GC Total Time"


echo "----------------------------------------"

echo ""

echo " HostName : " $(hostname)

echo ""

for PID in  `ps -ef | grep java | egrep -v grep | grep weblogic.Server | awk -F" " '{print $2}'`

do

echo " WAS PID  : " $PID

echo "----------------------------------------------------------------------------"

jstat -gcutil $PID 3000 2

echo "----------------------------------------------------------------------------"

echo ""

done

echo ""


결과

===========================================

 HostName :  jupitorDowon


 WAS PID  :  355343

----------------------------------------------------------------------------

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   

  0.00   0.00  52.68  13.52  31.58   3764   30.408  1878 1148.863 1179.271

  0.00   0.00  52.69  13.52  31.58   3764   30.408  1878 1148.863 1179.271

----------------------------------------------------------------------------


  - 컬럼 출력 내용 : 출처 (http://helloworld.naver.com/helloworld/helloworld/6043)

칼럼

설명

jstat 옵션

S0C

Survivor 0 영역의 현재 크기를 KB 단위로 표시

-gc

-gccapacity

-gcnew

-gcnewcapacity

S1C

Survivor 1 영역의 현재 크기를 KB 단위로 표시

-gc

-gccapacity

-gcnew

-gcnewcapacity

S0U

Survivor 0 영역의 현재 사용량을 KB 단위로 표시

-gc

-gcnew

S1U

Survivor 1 영역의 현재 사용량을 KB 단위로 표시

-gc

-gcnew

EC

Eden 영역의 현재 크기를 KB 단위로 표시

-gc

-gccapacity

-gcnew

-gcnewcapacity

EU

Eden 영역의 현재 사용량을KB 단위로 표시

-gc

-gcnew

OC

Old 영역의 현재 크기를 KB 단위로 표시

-gc

-gccapacity

-gcold

-gcoldcapacity

OU

Old 영역의 현재 사용량을KB 단위로 표시

-gc

-gcold

PC

Permanent영역의 현재 크기를 KB 단위로 표시

-gc

-gccapacity

-gcold

-gcoldcapacity

-gcpermcapacity

PU

Permanent영역의 현재 사용량을KB 단위로 표시

-gc

-gcold

YGC

Young Generation의 GC 이벤트 발생 횟수

-gc

-gccapacity

-gcnew

-gcnewcapacity

-gcold

-gcoldcapacity

-gcpermcapacity

-gcutil

-gccause

YGCT

Yong Generation의 GC 수행 누적 시간

-gc

-gcnew

-gcutil

-gccause

FGC

Full GC 이벤트가 발생한 횟수

-gc

-gccapacity

-gcnew

-gcnewcapacity

-gcold

-gcoldcapacity

-gcpermcapacity

-gcutil

-gccause

FGCT

Full GC 수행 누적 시간

-gc

-gcold

-gcoldcapacity

-gcpermcapacity

-gcutil

-gccause

GCT

전체 GC 수행 누적 시간

-gc

-gcold

-gcoldcapacity

-gcpermcapacity

-gcutil

-gccause

NGCMN

New Generation의 최소 크기를 KB단위로 표시

-gccapacity

-gcnewcapacity

NGCMX

New Generation의 최대 크기를 KB단위로 표시

-gccapacity

-gcnewcapacity

NGC

New Generation의 현재 크기를 KB단위로 표시

-gccapacity

-gcnewcapacity

OGCMN

Old Generation의 최소 크기를 KB단위로 표시

-gccapacity

-gcoldcapacity

OGCMX

Old Generation의 최대 크기를 KB단위로 표시

-gccapacity

-gcoldcapacity

OGC

Old Generation의 현재 크기를 KB단위로 표시

-gccapacity

-gcoldcapacity

PGCMN

Permanent Generation의 최소 크기를 KB단위로 표시

-gccapacity

-gcpermcapacity

PGCMX

Permanent Generation의 최대 크기를 KB단위로 표시

-gccapacity

-gcpermcapacity

PGC

현재 Permanent Generation의 크기를 KB단위로 표시

-gccapacity

-gcpermcapacity

PC

Permanent 영역의 현재 크기를 KB단위로 표시

-gccapacity

-gcpermcapacity

PU

Permanent 영역의 현재 사용량을 KB단위로 표시

-gc

-gcold

LGCC

지난 GC의 발생 이유

-gccause

GCC

현재 GC의 발생 이유

-gccause

TT

Tenuring threshold. Young 영역 내에서 이 횟수만큼 복사되었을 경우(S0 ->S1, S1->S0) Old 영역으로 이동

-gcnew

MTT

최대 Tenuring threshold. Yong 영역 내에서 이 횟수만큼 복사되었을 경우 Old 영역으로 이동

-gcnew

DSS

적절한 Survivor 영역의 크기를 KB단위로 표시

-gcnew



3) verbose:gc 옵션을 통한 GC 모니터링

  - WAS 기동 Shell에 verbose:gc 옵션을 준다

    + GC에 대해 자세히 시간을 찍도록 한다

    + 로그위치와 명칭을 지정한다

-verbose:gc 

-Xloggc:/applog/cmsmDomain/gclog/gc.log 

-XX:+PrintGCDetails 

-XX:+PrintGCTimeStamps 

-XX:+PrintHeapAtGC 

-XX:+HeapDumpOnOutOfMemoryError 

-XX:HeapDumpPath=/applog/cmsmDomain/gclog/java_pid.hprof 


  - 로그 출력 예

// Full GC

7210.826: [Full GC (System) [PSYoungGen: 23616K->0K(1947520K)] [PSOldGen: 886563K->856929K(3145728K)] 910179K->856929K(5093248K) [PSPermGen: 138064K->138064K(524288K)], 2.9391980 secs] [Times: user=2.98 sys=0.00, real=2.94 secs]

Heap after GC invocations=52 (full 3):

 PSYoungGen      total 1947520K, used 0K [0x0000000780000000, 0x0000000800000000, 0x0000000800000000)

  eden space 1801536K, 0% used [0x0000000780000000,0x0000000780000000,0x00000007edf50000)

  from space 145984K, 0% used [0x00000007edf50000,0x00000007edf50000,0x00000007f6de0000)

  to   space 141376K, 0% used [0x00000007f75f0000,0x00000007f75f0000,0x0000000800000000)

 PSOldGen        total 3145728K, used 856929K [0x00000006c0000000, 0x0000000780000000, 0x0000000780000000)

  object space 3145728K, 27% used [0x00000006c0000000,0x00000006f44d8428,0x0000000780000000)

 PSPermGen       total 524288K, used 138064K [0x00000006a0000000, 0x00000006c0000000, 0x00000006c0000000)

  object space 524288K, 26% used [0x00000006a0000000,0x00000006a86d41d8,0x00000006c0000000)

}

// Minor GC

10500.769: [GC [PSYoungGen: 1769535K->35007K(1928320K)] 2645761K->912640K(5074048K), 0.0958040 secs] [Times: user=0.17 sys=0.00, real=0.09 secs]

Heap after GC invocations=67 (full 3):

 PSYoungGen      total 1928320K, used 35007K [0x0000000780000000, 0x0000000800000000, 0x0000000800000000)

  eden space 1754816K, 0% used [0x0000000780000000,0x0000000780000000,0x00000007eb1b0000)

  from space 173504K, 20% used [0x00000007f5690000,0x00000007f78bff00,0x0000000800000000)

  to   space 168832K, 0% used [0x00000007eb1b0000,0x00000007eb1b0000,0x00000007f5690000)

 PSOldGen        total 3145728K, used 877632K [0x00000006c0000000, 0x0000000780000000, 0x0000000780000000)

  object space 3145728K, 27% used [0x00000006c0000000,0x00000006f59101d8,0x0000000780000000)

 PSPermGen       total 524288K, used 138386K [0x00000006a0000000, 0x00000006c0000000, 0x00000006c0000000)

  object space 524288K, 26% used [0x00000006a0000000,0x00000006a8724880,0x00000006c0000000)

}



4) 튜닝하기 

  - WAS 기동 Shell의 기본옵션

    + -Xms -Xmx 힙사이즈 지정

    + -server 옵션 지정

    GC 튜닝 시 기본적으로 학인해야 하는 JVM 옵션 (출처: http://helloworld.naver.com/helloworld/37111)

구분

옵션

설명

힙(heap) 영역 크기

-Xms

JVM 시작 시 힙 영역 크기

-Xmx

최대 힙 영역 크기

New 영역의 크기

-XX:NewRatio

New영역과 Old 영역의 비율

-XX:NewSize

New영역의 크기

-XX:SurvivorRatio

Eden 영역과 Survivor 영역의 비율


  - 설정 예 

/usr/java/jdk1.6.0_31/bin/java 

-server 

-Xms5120m -Xmx5120m 

-XX:NewSize=2048m 

-XX:MaxNewSize=2048m 

-XX:PermSize=512m 

-XX:MaxPermSize=512m 


-Xss5m 

-verbose:gc 

-Xloggc:/applog/cmsmDomain/gclog/gc.log 

-XX:+PrintGCDetails 

-XX:+PrintGCTimeStamps 

-XX:+PrintHeapAtGC 

-XX:+HeapDumpOnOutOfMemoryError 

-XX:HeapDumpPath=/applog/cmsmDomain/gclog/java_pid.hprof 


  - 다음의 경우 튜닝이 필요없다. 단 이것은 서비스의 특성에 따라 틀리다. 해당 시간 이상이면 튜닝 대상

  • Minor GC 처리 시간이 빠르다(50ms내외).
  • Minor GC 주기가 빈번하지 않다(10 내외).
  • Full GC 처리 시간이 빠르다(보통1 이내).
  • Full GC 주기가 빈번하지 않다(10분에 1).


  - Full GC 수행 시간과 수행 간격 조사 => Minor GC 수행 시간과 수행 간격 조사 => 전체 평균값 및 수행 횟수등을 조사하여 튠이 필요성을 판단한다 


  - 메모리 설정 옵션을 조정하면서 결정한다

    + 힙사이즈가 크면 GC 시간도 올래 걸린다 : 그만큼 많은 객체가 쌓여 있을 것이므로 

    + 따라서 무조건 크게 잡는다고 해서 좋은 것은 아니므로 적정사이즈를 찾아가는 것이 중요하다 

    + NewRatio=2 는 New Generation:Old Generation = 1:2 비율 사이즈로 사용크기를 지정하는 것임 (-Xmx 사이즈에 대해서)

      즉, NewRatio=4 이면 New:Old=1:4 비율의 크기임


  - 튜닝 예 1)

    + jstat -gccapacity의 New영역 사용크기(NGCMN)과 Old영역 사용크기(OGCMN) 값의 비율을 체크한다 

      NGCMN:OGCMN = 2:3 (Gbytes)

    + NewRatio=2 => 3 => 4 로 바꾸어 가면서 Full/Minor GC 평균응답시간을 구한다 (jstat -gctuil로 구함)


  - 튜닝 예 2)

    + verbose:gc 로그가 남으면 HP JMeter를 통하여 분석한다

    + JMeter를 통하여 Duration 발생 간격을 측정하거나 GC 소요 시간을 그래프 형태로 볼 수 있다. 

    + 여러 옵션을 차례로 처음 몇개에만 적용해 보고 jstat -gcutil 을 통하여 통계값을 얻고 최적치를 측정해 나간다 

  • Case1 : -XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=2
  • Case2 : -XX:+UseParallelGC -Xms1536m -Xmx1536m -XX:NewRatio=3
  • Case3 : -XX:+UseParallelGC -Xms1g -Xmx1g -XX:NewRatio=3
  • Case4 : -XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=2
  • Case5 : -XX:+UseParallelOldGC -Xms1536m -Xmx1536m -XX:NewRatio=3
  • Case6 : -XX:+UseParallelOldGC -Xms1g -Xmx1g -XX:NewRatio=3

 

위의 모든 내용은 HelloWorld의 연재글을 통하여 현재 운영하고 있는 JBoss의 GC 분석을 수행할 예정이다. 이자리를 빌어 이상민님에게 감사를 드린다. 또한 사전 허락없이 옵션 테이블을 인용하였고 만일 문제가 된다면 바로 삭제토록 할 예정이다. 



<참조>

  - GC 에 대한 이해 

    + Young:Old 영역에 대한 이해 : http://helloworld.naver.com/helloworld/1329

    + GC 모니터링 방법 -verbose:gc : http://helloworld.naver.com/helloworld/helloworld/6043


  - GC 튜닝 가이드 : http://helloworld.naver.com/helloworld/37111

  - jstat 사용예제 : https://community.jboss.org/thread/159052

posted by Peter Note
2013. 5. 15. 15:25 Middleware, Cloud/WAS

1. JBoss 5.1 has the following Thread Pools

  • System Thread Pool
  • HTTP Thread Pool
  • AJP Thread Pool
  • JCA Thread Pool(Work Manager Thread Pool)
  • JBoss Messaging Thread Pool (for remote clients)
  • JBoss Messaging Thread Pool (in JVM Clients)
  • EJB (same JVM)
  • EJB (remote Clients)

2. Port 정보 

TCP    10.2.20.156:1090       <--- RMI/JRMP socket for connecting to the JMX MBeanServer
TCP    10.2.20.156:1091       <--- RMI server socket
TCP    10.2.20.156:1099       <--- JNDI Service
TCP    10.2.20.156:1098       <--- RMI Port for JNDI Service
TCP    10.2.20.156:4446       <--- JBoss Remoting Connector
TCP    10.2.20.156:4712       <--- JBossTS Service
TCP    10.2.20.156:4713       <--- JBossTS Service
TCP    10.2.20.156:5445       <--- HornetQ JMS Service
TCP    10.2.20.156:5455       <--- HornetQ Netty port
TCP    10.2.20.156:5500       <--- JBoss Remoting
TCP    10.2.20.156:5501       <--- JBoss Remoting ssl
TCP    10.2.20.156:8009       <--- Web server AjpConnector
TCP    10.2.20.156:8080       <--- Web server HTTP Connector
TCP    10.2.20.156:8083       <--- Web services

 

<참조> 

  - http://zeroproductionincidents.wordpress.com/tag/jboss-thread-pool/

  - http://www.mastertheboss.com/jboss-configuration/jboss-port-configuration

posted by Peter Note
2013. 5. 10. 08:40 Dev Environment/Mac, Dev Tools

크롬 기반으로 개발을 시작할때 개발자라면 Chrome Canary로 시작해 보자. 최신 기능들이 포함되어 있으며 Dev Tool이 좀 더 막강하다. 거의 개발툴 수준이라고 할까?



1. Chrome Canary 설치

  - https://www.google.com/intl/ko/chrome/browser/canary.html

  - Google의 Dev Tools 강좌




2. 오스마니님 강좌

  - google+에 지속적의 자신의 활동을 올리고 있다. 구글러이면서 Yeoman의 개발자이다. 오스마니님 친구추천 ^^

  - 2013년도에는 크롬 개발툴로 생산성을 증진시키자

    + 코드 에디팅 및 로컬 히스토리 저장 

    + 코드 리비젼 기능

    + 코드 에디터에 있는 cmd+o (소스 열기), cmd+shift+o (소스 특정 위치 찾기), cmd+L(특정 라인 이동), cmd+F (특정 키워드 찾기)

    + beakpoint 통한 디버깅 

    + minify 된 코드의 beautify 하기

    + 개발툴 layout 개선 

    + Grunt 툴 통합

    + PageSppeed 툴 통합

    

 


3. 테스팅 및 디버깅

  - 모바일 기기 해상도별 테스트하기 

  - 자바스크립트 디버깅하기



<참조>

  - 오스마니님의 최근 Yeoman 강좌

  - 까나리 액젓된 크롬

posted by Peter Note
2013. 5. 9. 23:19 HTML5, CSS3/CSS

RWD는 Responsive Web Design (반응형 웹 디자인)을 일컸는다. 어떻게 시작해야 할지 경험한 내용을 정리해 본다. 먼저 http://www.unitedpixelworkers.com 사이트를 들어가서 브라우져 사이즈를 모바일 기기 크기 - 스마트폰, 테블릿 - 로 변경하여 본다. 반응형 웹 디자인이 무엇인지 감상해 보시길...



1. 개념잡기 

  - RWD의 기초 개념이해

    + Fluid images  : img{ max-width: 100%, height: auto }

    + Fluid Grid : fluid-container안에서 움직임. 해상도에 따라 floating 

    + Media Queries : @media screen and {max-width: 980px} , 다양한 기기의 해상도에 따른 화면 사이즈 변경

  - Font Responsively : 폰트를 픽셀로 할지 %로할지 em으로 할지에 대한 반응형 폰트. %로 한다 

  - Fluid Layout : Fixed 에서 Fluid(Liquid) 로 변화 이젠 Hybrid layout으로 간다 

  - Custom Grid Layout : div[ float: left, width:200px }, header, content, sidebar, footer의 구분예

  - Responsive Imagery : 모바일 속도 향상을 위하여 이미지도 minify

  - Browser Compatibility : 브라우져 호환도 중요


  반응형 웹 디자인은 각 경우에 충족하는 디자인이 되었는지 살펴 보아야 한다. 



2. 반응형 패턴

  - 반응형으로 만들기 위한 패턴을 익힌다 : Responsive Patterns

    + Layout : 전체 위치 잡기

    + Navigation : 메뉴 구조화 하기 

    + Image : 이미지

    + Media : 비디오

    + Forms : 입력 제출

    + Modules : 기타 위젯들

  - Creating a Mobile-First Responsive Web Design : 실제 간단한 실습을 해본다  



3. 개발자가 사용할 도구 & 소스

  - Twitter Bootstrap

    + 가장 많이 사용하는 CSS, Widget 이면서 Responsive 지원 

    + 부트 스트랩 어떻게 사용하는지 프로토 타입핑해 본다  

    + Wrap Bootstrap 사이트에서 Bootstrap을 어떻게 확장했는지 보자 (상업용 구매 사이트) : 전부 반응형 웹 디자인 템플릿

       외국의 퍼블리셔는 그래픽 작업 및 RWD를 위한 HTML5 & CSS3 그리고 기본 jQuery 자바스크립트 코딩을 한다!!!

       솔루션 개발에 많이 참조하고 있는 사이트이다. 

    + Bootstrap 가지고 서비스를 만드는 회사들이 존재 : http://www.layoutit.com/

  - Zurb Foundation

    + 사이트 제작에 적합하다고 판단 됨

  - Gumby Framework 

    + RWD를 기반의 웹사이트 제작 프레임워크 

  - 그외 RWD를 위한 도구들 (필독)

  - 깃헙에서 rwd 또는 Responsive 로 검색하면 개발자들이 만들어 놓은 간혹 괜찮은 RWD들이 올라와 있다

    + Iacien Collapsible Menu

  - 15개의 신규 CSS Frameworks



<참조> 

  - 반응형 웹 디자인의 이슈 : 우리나라 어느 퍼블리셔 발표 자료 

  - 10 가지 쥑이는 RWD 예제 사이트

  - Responsive Design 프리젠테이션

  - ViewPort에 대한 이해

  - ViewPort와 Media Queries의 적용 예제 및 데모

  - RWD 연재 글 2편 : RWD 어디에 사용할까?

  - SpeckyBoy - RWD 웹사이트 만들기 with Gumby

posted by Peter Note
2013. 5. 7. 09:37 NodeJS/Concept

서비스 또는 솔루션을 만들기 위해 Node.js와 Express.js를 선택하였다면  그 다음 고민은 애플리케이션 개발을 위하여 필요한 스택을 선정하는 일이다. 크게는 로깅, 환경설정, 통신등 기본적인 부분들을 직접 개발하지 말고 이미 만들어진 바퀴를 공짜로 구해서 달아보자 



1. 준비하기 

  - Programming Javascript Application Book 책의 내용을 발췌한 것이다 

  - Node 버전관리 NVM 설치 

    + https://github.com/creationix/nvm

    + 설치 : nvm install [버전]

    + 수행 : nvm run [버전]

    + 확인 : nvm ls  (설치된 버전 목록을 보여줌)

    + 가능 : nvm ls-remote (설치 가능 버전 목록을 보여줌)

  - nvm 설치 명령 : git 사전 설치요구 : 수행시 nvm.sh 에 syntax오류가 나오면 nvm.sh을 copy하고 기존것 삭제후 다시 paste하여 만듦

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


    + 기타 명령들 

$ nvm help


Node Version Manager


Usage:

    nvm help                          Show this message

    nvm install [-s] <version>  Download and install a <version>

    nvm uninstall <version>     Uninstall a version

    nvm use <version>           Modify PATH to use <version>

    nvm run <version> [<args>]  Run <version> with <args> as arguments

    nvm ls                            List installed versions

    nvm ls <version>             List versions matching a given description

    nvm ls-remote                 List remote versions available for install

    nvm deactivate                Undo effects of NVM on current shell

    nvm alias [<pattern>]      Show all aliases beginning with <pattern>

    nvm alias <name> <version>    Set an alias named <name> pointing to <version>

    nvm unalias <name>                Deletes the alias named <name>

    nvm copy-packages <version> Install global NPM packages contained in <version> to current version


Example:

    nvm install v0.4.12            Install a specific version number

    nvm use 0.2                    Use the latest available 0.2.x release

    nvm run 0.4.12 myApp.js   Run myApp.js using node v0.4.12

    nvm alias default 0.4        Auto use the latest installed v0.4.x version


  - 프로젝트 만들고 초기화 하기 

    + 디렉토리 만들고 해당 디렉토리로 이동

    + npm init 수행하여 package.json 파일 만들기 : 이름, 버전, 설명, 키워드, 저장소위치, 라이센스 및 기타 정보등을 입력한다 

$ mkdir basic && cd basic

$ npm init

This utility will walk you through creating a package.json file.

It only covers the most common items, and tries to guess sane defaults.


See `npm help json` for definitive documentation on these fields

and exactly what they do.


Use `npm install <pkg> --save` afterwards to install a package and

save it as a dependency in the package.json file.


Press ^C at any time to quit.

name: (basic) JavaScript-Programming

version: (0.0.0) 0.0.1

description: This is a javascript programming

entry point: (index.js)

test command: grunt test

git repository: https:/github.com/ysyun/javascriptacular

keywords: angularjs

author: yun dowon

license: (BSD) MIT

About to write to /Users/prototyping/express/basic/package.json:


{

  "name": "JavaScript-Programming",

  "version": "0.0.1",

  "description": "This is a javascript programming ",

  "main": "index.js",

  "scripts": {

    "test": "grunt test"

  },

  "repository": {

    "type": "git",

    "url": "https:/github.com/ysyun/javascriptacular"

  },

  "keywords": [

    "angularjs"

  ],

  "author": "yun dowon",

  "license": "MIT"

}



Is this ok? (yes)

npm WARN package.json JavaScript-Programming@0.0.1 No README.md file found!

$ ls -lart

-rw-r--r--  1 nulpulum  staff  360  5  7 09:22 package.json

drwxr-xr-x  3 nulpulum  staff  102  5  7 09:22 .


  - 모듈 설치시에 package.json 파일에 자동 기록을 위하여 npm install --save [module] 처럼 --save 옵션을 준다 



2. 준비할 스택들

  • Mout Like Underscore / LoDash. Stuff that should probably be included in JavaScript.

  • Express Web application framework.

  • Nconf Application config.

  • Hogan Mustache for express. (Jade 또는 EJS 를 써도 됨)

  • Superagent Communicate with APIs.

  • Socket.io Realtime communications (websockets).

  • Q Promises.

  • Async Asynchronous functional utilities.

  • Bunyan Logging. (Winston도 많이 사용)

  • Tape Testing. (Mocha, Karma 도 사용)

  • Cuid Better than guid/uuid for web applications.

  • Derby.js Add realtime, collaborative MVC to express. (Sails.js 또는 Bone.js 도 사용)

  • Node-http-proxy Proxy your service APIs.



3. Express 사용하기 

  - Routing 을 이용한다

  - Middleware를 통하여 중간에 Hooking 하여 처리하고 다음으로 next() 호출 넘기는 use 를 사용한다 

// Add some data to the request object that your other
// midleware and routes can use.
app.use(function (req, res, next) {
  req.foo = 'bar';
  next();

});

    + 전체 예제 

'use strict';
var express = require('express'),
 
  // Create app instance.
  app = express(),
 
  // Use the `PORT` environment variable, or port 44444
  port = process.env.PORT || 44444;
 
// The new middleware adds the property `foo` to the request
// object and sets it to 'bar'.
app.use(function (req, res, next) {
  req.foo = 'bar';
  next();
});
 
app.get('/', function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
 
  // Send the value passed from the middleware, above.
  res.end(req.foo);
});
 
app.listen(port, function () {
  console.log('Listening on port ' + port);

});


// 결과 : use를 설정한 순서대로 처리된다 

$ curl http://localhost:44444/
bar



4. SailsJS

  - 난 sails를 Full Stack Server Side Data-Oriented API Framework 이라고 말하고 싶다.

  - Front-end 단이 SPA로 개발될 경우

  - Back-end를 API 서버로 확장함 

  - Node.js + Express.js + MongoDB 와 연결 및 JSON Memory DB 사용가능

    + sails-angularjs-yeoman 의 로그인 데모

    + sails-mongodb 연결

    + sails-redis 연결



<참조>

   - 원문 : Getting start with Node and Express 

   - middleware의 next() 사용법 : Node.js의 connect 이해하기

   - AngularJS와 MongoDB 연결 Bridge


posted by Peter Note
2013. 4. 27. 16:36 AngularJS/Concept

AngularJS에 구성 요소에 대한 Snippet을 살펴본다. 또한 jQuery와 통합하여 사용하는 방법을 알아보자 



1. 들어가기

  - Angular를 통해서 Client-Side에서 데이터와 애플리케이션 로직을 분리한다

  - 최초에 넣어야 할 라이브러리들 

<script type="text/javascript" src="/path/to/angular/angular.js"></script>

<script type="text/javascript" src="/path/to/angular/angular-resource.js"></script>



2. Module

  - 정의

    + Modules are used to fully encapsulate all the angular code of your application into one entry point

    + 컴포넌트와 같으면 Self living 할 수 있다

    + 큰 프로젝트를 할 때의 모듈 나누는 방법

  - 메인 레이아웃 파일에 다음과 코드를 넣는다

    + <html 태그에 넣거나 <body 에 넣거나 한다 

    + SPA를 한다면 아마도 <body> 태그 밑의 특정 부분이 Dynamic DOM 이 될 것이다 

<html data-ng-app="YOUR_APP_NAME">

또는

<html ng-app="YOUR_APP_NAME">


  - JavaScript에서 사용하기 

    + angular는 글로벌 변수이고, directive/controller/filter/service등을 만들기 위한 App 변수를 만들었다

    + ['ngResource']와 같이 의존하는 라이브러리를 설정한다  

var App = angular.module('YOUR_APP_NAME', ['ngResource']);



3. Binding, Expression

  - 양방향 data binding, 조건문, 반복문

  - {{ expression }} 데이터 표현

// html

<div class="records" data-ng-repeat="record in records | orderBy:orderProp">

  <h5> {{ record.title }} </h5>

</div>


// js 

$scope.records = [{ title : 'one' }, { title : 'two' }, { title : 'three' }]; 



4. Dependency Injection

  - 코드를 조직화 하고 테스트 가능하게 만들어준다

  - controllers, module configuraitons, directives, filters, resources, routes 들을 DI 할 수 있다 

// 메소드 파라미터로 DI를 해준다

var Ctrl = function($scope, $http, $location) {

  //now you can use any of the injected variables


  //to change the URL after something has happened then you can use $location

  $location.path('/path/to/new/page');

}

//and now the injection of the variables

Ctrl.$inject = ['$scope','$http','$location'];


  - DI에 대한 개념을 제대로 잡고 싶다면 보지타님의 동영상 보라



5. Routes

  - 요청 uri path와 controller를 맵핑하는 것이다 

// 모듈의 config 에서 정의한다 

// $routeProvider 서비스를 통하여 정의한다 

// uri path에 대하여 templateUrl 과 controller를 맵핑한다 

App.config(['$routeProvider', function($routes) {


  $route.when('/',{

    templateUrl : '/templates/home.html',

    controller : HomeCtrl

  });


  $route.when('/register',{

    templateUrl : '/templates/register.html',

    controller : RegisterCtrl

  });


  $routes.otherwise({

    redirectTo : '/'

  });


}]);



6. Controller & Scope

  - 컨트롤러는 $scope와 함께하여 데이터를 연동한다 

  - controller 만들기 (ng-app의 명칭 즉, 모듈명이 없을 경우)

    + $scope.title를 변경하면 angular는 데이터 변경을 모른다 

    + 하기와 같은 예제에서는 $scope.$apply() 가 필요하다 

    + $apply() 는 일반 JavaScript Context에서 수행되는 것을 AngularJS Context로 수행 되게 해준다 (필히 참조)

    + $apply, $digest, $$phase 란 무엇인가?

// angularjs 모듈에서 파생되지 않은 컨트롤러 펑션

var SomeCtrl = function($scope, $http, $location) {

  $scope.value = 'some value';

};

// controller에게 서비스를 주입하여 준다 (DI)

SomeCtrl.$inject = ['$scope','$http','$location'];


// html에서 {{ }} 를 설정

<div class="header">{{ title }}</div>


// 하기와 같이 설정을 하면 {{ title }} 이 자동으로 바뀌어야 한다  

$scope.title = 'this is awesome';


//if a scope digestion is already going on then it will get picked up and you won't

//have to call the $scope.$apply() method

// $apply를 호출하면 $digest cycle로 들어가고 model이 변화를 감지하여 $watch 에 등록된 expression의 변경을 수행한다

// 즉, view가 re-rendering 되는 것이다 

if(!$scope.$$phase) { //this is used to prevent an overlap of scope digestion

  $scope.$apply(); //this will kickstart angular to recognize the change

}


  - $scope는 $rootScope 상속한 것이다

    + 만일 전체 애플리케이션에서 $scope를 통하여 어떤 펑션을 사용하고 싶다면 하기와 같이 한다

    + 모듈이 로딩 될 때 config 와 run 이 자동 호출된다. run은 main메소드와 유사하다 (참조

App.run(['$rootScope', function($rootScope) {

  $rootScope.sharedFunction = function() { ... };

}]);


  - controller 사용하기 정식 방법 두가지 

    + html 태그안에서 ng-controller 통하여 설정

    + $routes의 controller 설정

// html

<div data-ng-controller="SomeCtrl">...</div>


// js

$routes.when('/some/path',{

  controller : Ctrl,

  templateUrl : '/templates/controller.html'

});



7. Services

  - 전체 애플리케이션에서 공유하는 것들

  - DI를 통하여 객체를 전달함 

//define the service

// App 모듈에 myService가 정의한 서비스의 명칭

App.factory('myService', ['myOtherService', '$location', function(myOtherService, $location) {

  return function(input) {

    //do something with the input using the myOtherService or the $location objects.

    return input;

  };

}]);


//use the service within the controller

// Controller에서 $scope와 myService DI하여 공유한다 

var HomeCtrl = function($scope, myService) {

  var input = '123';

  input = myService(input);

};

HomeCtrl.$inject = ['$scope','myService'];


//use the service a directive

// App 모듈에 directive를 정의한다. myService 서비스를 DI하여 공유한다 

App.directive('myDirective', ['myService',function(myService) {

  return {

    link: function($scope, element, attrs) {

      var input = '123';

      input = myService(input);

    }

  }

}]);



8. Models

  - RESTful Web Service를 호출을 위하여 7번의 서비스 개념으로 만들어 놓고 사용할 수 있다 

// ModelName이라고 서비스를 만든다

// $resource를 통하여 서버사이드로 호출한다 

App.factory('ModelName', ['$resource', function($resource) {

  $resource.url('/path/to/model/controller/:id',{

    id : '@id', //this binds the ID of the model to the URL param

  },{

    query : { method : 'GET', isArray : true }, //this can also be called index or all

    save : { method : 'PUT' }, //this is the update method

    create : { method : 'POST' },

    destroy : { method : 'DELETE' }

  }

}]);


// Controller 에서 ModelName 서비스를 DI 받아서 호출한다

var SomeCtrl = function($scope, $http, $location, ModelName) {

  //now you can use ModelName to do your business

};

SomeCtrl.$inject = ['$scope','$http','$location','ModelName'];


  - ModelName을 통하여 다음과 같이 사용할 수 있다 (연구필요)

    + 서비스를 CRUD query 형태로 만들어서 사용한다

    + Breeze.js 로 확장할 수도 있겠다 

//list all the records on the page

var results = ModelName.query({ search : 'all' }, onSuccessFn, onFailureFn);


//get a specific record

var record = ModelName.get({ id : 123 }, onSuccessFn, onFailureFn); //onSuccessFn and onFailureFn are optional callback functions where you can further customize the response


//create a new ModelName record

var record = new ModelName();


//update that record

record.someAttr = 'someValue';

record.$save();


//or if you prefer to submit your data in a different way

ModelName.save({

    id : record.id

  },{

  somePostObject : {

    attr1 : 'value',

    attr2 : 'value2'

  }

});


//destroy the record (and include a token)

record.destroy({ token : record.token });



9. Directives

  - HTML 코드를 통하여 만들어 놓은 플러그인과 링크를 설정해 주는 것이다. 애플리케이션내에서 블럭을 격리시켜준다. (그냥 컴포넌트 개념을 생각하며 되겠다. 화면 구성을 위하여 UI 컴포넌트 추가하는 것 처럼)

  - 웹앱을 구조화하는데 도움을 준다 

  - Plugin, Validation(유효성검사), Dynamic text properties 또는 i18n, l10n 에도 활용한다 

// link 는 Controller와 Directive가 $scope 를 통하여 데이터를 공유하는 중요 통로이다 

angular.directive('myDirective',function($compile) {

  return {

    templateUrl : '/path/to/some/template.html', //(optional) the contents of this template can be downloaded and constructed into the element

    replace : true, //whether or not to replace the inner data within the element

    link : function($scope, $element, attributes) { //this is where your magic happens

      $scope.title = '...';

    }

  };

});



10. Filters

  - 필터는 재사용 가능한 오퍼레이션이다 

  - binding operation에 내장되어 함께 수행된다 예) 정렬, 문자변형, Pagination 등

// App 모듈에서 myUppercase 명칭의 filter 정의  

App.filter('myUppercase', function(data) {

  for(var i=0; i < data.length; i++) {

    data[i].title = data[i].title.toUpperCase();

  }

  return data;

});


// html에서 사용하기 

<div data-ng-repeat="for record in records | filter:myUppercase">...</div>


// 또는 javascript 코드에서 호출가능

//be sure to inject the $filter object

var values = ['one','two','three'];

values = $filter('myUppercase')(values);



11. HTML5 Mode

  - angular app이 angular의 routing system 안에서 HTML5 history방식으로 관리되게 해준다 

  - 해당 코드만 넣으면 된다 

App.config(['$locationProvider', function($location) {

  $location.html5Mode(true); //now there won't be a hashbang within URLs for browers that support HTML5 history

}]);



12. jQuery 사용

  - 가장 간단하게 angular.js 스크립트 태그 전에 jQuery 태그를 먼저 위치시키면 된다

  - Angular.js는 jqLite를 기본 사용하나 jQuery가 먼저 설정되면 jQuery로 대체되어 사용한다 



<참조>

  - 원문 : use angularjs to power your web application

  - AngularJS 소개 ppt


posted by Peter Note
2013. 4. 25. 11:45 Dev Environment/Build System

구글 플러스 보다가 여맨 개발자인 오스마니님의 Generator 문서 정리했다는 글을 보고 얼른 들어와 봤다. AngularJS를 하면서 Yeoman을 필수로 상요하고 있어서 필요한 모듈이나 라이브러리를 스케폴딩하도록 수정하고 있기 때문에 어째 잘 정리되었는지 살펴본다 



1. 소개

  - 제너레이터의 종류는 두가지이다 

    + Boilerplate : 프로젝트 껍데기를 만들어준다. 프로젝트 구조화에 도움 예) HTML5 boilerplate, Twitter Bootstrap boilerplate 등 

    + Scaffolder : boilerplate외에 빌드시스템, sub-generator, 의존성관리, 자동화 업무수행(workflow)을 한다 

  - 공식적인 제너레이터들을 사용하거나 fork해서 수정 사용해도 된다 예) AngularJS+Express 연동



2. Boilerplate  Generator 만들기 

  - awesome 이란 걸 만들어 보자 

    + 원문은 사실 왜 이렇게 명령을 하는지 친절하게 설명은 하지 않고 있다. 기본은 알고 있다는 전제로 간단히 설명했다 

    + html5 boilerplate generator를 만들어 본다 

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

// yeoman의  boilerplate generator를 가장 먼저 클론한다

$ git clone git://github.com/addyosmani/generator-boilerplate.git

Cloning into 'generator-boilerplate'...

.. 중략..

Resolving deltas: 100% (20/20), done.


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

// git submodule add 명령(참조) 을 통하여 html5 bp 클론

// 여기서 중요한 것은 app/templates 으로 반드시 지정

// app/templates은 yeoman의 복제 템플릿이 놓이는 위치

// 다른 방법 : yo boilerplate https://github.com/h5bp/html5-boilerplate/archive/master.tar.gz

$ cd generator-boilerplate/

$ generator-boilerplate> git submodule add git://github.com/h5bp/html5-boilerplate.git app/templates

Cloning into 'app/templates'...

remote: Counting objects: 4955, done.

..중략...

warning: LF will be replaced by CRLF in .gitmodules.

The file will have its original line endings in your working directory.


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

// templates 밑으로 html5-boilerplate 코드가 들어감

$ tree

.

├── README.md

├── app

│   ├── index.js

│   └── templates

│       ├── 404.html

│       ├── CHANGELOG.md

│       ├── CONTRIBUTING.md

│       ├── LICENSE.md

│       ├── README.md

│       ├── apple-touch-icon-114x114-precomposed.png

│       ├── apple-touch-icon-144x144-precomposed.png

│       ├── apple-touch-icon-57x57-precomposed.png

│       ├── apple-touch-icon-72x72-precomposed.png

│       ├── apple-touch-icon-precomposed.png

│       ├── apple-touch-icon.png

│       ├── crossdomain.xml

│       ├── css

│       │   ├── main.css

│       │   └── normalize.css

│       ├── doc

│       │   ├── TOC.md

│       │   ├── crossdomain.md

│       │   ├── css.md

│       │   ├── extend.md

│       │   ├── faq.md

│       │   ├── html.md

│       │   ├── js.md

│       │   ├── misc.md

│       │   └── usage.md

│       ├── favicon.ico

│       ├── humans.txt

│       ├── img

│       ├── index.html

│       ├── js

│       │   ├── main.js

│       │   ├── plugins.js

│       │   └── vendor

│       │       ├── jquery-1.9.1.min.js

│       │       └── modernizr-2.6.2.min.js

│       └── robots.txt

└── package.json


7 directories, 34 files


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

// git 상태정보 .gitmodule 모듈 환경파일 자동 생성됨 

$ git status

warning: LF will be replaced by CRLF in .gitmodules.

The file will have its original line endings in your working directory.

# On branch master

# Changes to be committed:

#   (use "git reset HEAD <file>..." to unstage)

#

# modified:   .gitmodules

# new file:   app/templates

#


$ cat .gitmodules

[submodule "app/templates"]

path = app/templates

url = git://github.com/h5bp/html5-boilerplate.git


$ cat .git/config

[core]

repositoryformatversion = 0

filemode = true

bare = false

logallrefupdates = true

ignorecase = true

precomposeunicode = false

[remote "origin"]

url = git://github.com/addyosmani/generator-boilerplate.git

fetch = +refs/heads/*:refs/remotes/origin/*

[branch "master"]

remote = origin

merge = refs/heads/master

[submodule "app/templates"]

url = git://github.com/h5bp/html5-boilerplate.git


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

// Node.js는 기본 설치되어 있어야 한다

// node package manager를 통하여 yeoman관련 모듈설치

$ npm install


  - 원문에서 다음으로 자신이 원하는 프로젝트를 만들라고 하는데, 중간과정이 생략되었다. 이제 만든 generator-boilerplate  사용법을 보자 

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

// awesome이라는 명칭으로 변경한다

// yeoman 명명규칙으로 generator- prefix는 꼭 붙인다

// package.json 과 README.md 파일 내역을 수정한다 

$ mv generator-boilerplate generator-awesome

$ cd generator-awesome

$ vi package-json  // 이름과 버전 및 설명을 수정

$ vi README.md   // 내용 수정


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

// yo 명령은 node를 기반으로 한다. 

// 따라서 global하게 찾을 수 있게 node_modules 밑에

// symbolic link을 걸어주었다

$ cd /usr/local/lib/node_modules

$ sudo ln -s <Your Directory Full Path>/generator-awesome  generator-awesome

Password:

/usr/local/lib/node_modules> ls -alrt

 ..중략..

drwxr-xr-x  13 nobody  staff   442  4 12 13:45 generator-karma

drwxr-xr-x  18 nobody  staff   612  4 12 14:30 npm

drwxr-xr-x  15 nobody  staff   510  4 12 14:31 bower

drwxr-xr-x  13 nobody  staff   442  4 12 15:03 grunt-cli

drwxr-xr-x   7 nobody  staff   238  4 18 09:57 yo

drwxr-xr-x  26 nobody  staff   884  4 18 10:42 generator-angular

drwxr-xr-x  16 nobody  staff   544  4 18 16:59 grunt-init

drwxr-xr-x  10 nobody  staff   340  4 19 23:46 grunt-express

drwxr-xr-x  16 nobody  staff   544  4 19 23:46 grunt

drwxr-xr-x  16 nobody  staff   544  4 22 11:04 generator-express

drwxr-xr-x  14 nobody  staff   476  4 22 11:31 generator-generator

drwxr-xr-x  13 nobody  staff   442  4 22 11:44 generator-bootstrap

lrwxr-xr-x   1 root    wheel    48  4 22 17:08 generator-angular-sd -> /Users/development/generator-angular-sd

drwxr-xr-x  16 nobody  staff   544  4 24 15:15 jshint

lrwxr-xr-x   1 root    wheel    52  4 25 10:40 generator-awesome -> /Users/prototyping/yeoman/generator-awesome


$ yo -h

Please choose a generator below.

Awesome

  awesome:app


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

// 자신의 프로젝트 디렉토리를 만든다 

// 프로젝트 디렉토리로 이동하여 yo awesome 수행! 

$ mkdir  dowonProject 

$ cd dowonProject

 yo awesome  (또는 yo awesome:app)

Generating from Generator Boilerplate v0.1.4...

   create .gitattributes

 .. 중략 ..

   create js/vendor/jquery-1.9.1.min.js

   create js/vendor/modernizr-2.6.2.min.js

   create robots.txt



3. Scaffolding Generator 만들기 

  - generator-generator 를 사용하여 만든다 

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

// 사실 yo, bower, grunt-cli를 설치해야 한다 (참조)

// 스케폴딩 제너레이터를 만들어 주는 제너레이터 설치

$ sudo npm install -g yo

$ sudo npm install -g generator-generator


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

// 사용할 수 있는 yeoman generator list를 보자 

$ yo -h 

Generator

  generator

  generator:app

  generator:subgenerator


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

// 스케폴딩 제너레이터 디렉토리를 만들고 명령수행

// generator- 는 반드시 붙인다. 뒤에 오는 이름에는 

// 절대로 - 를 사용하지 않는다. underbar 사용함!

$ mkdir generator-angularjs_express

$ cd generator-angularjs-express

$ yo generator:app

     _-----_

    |       |

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

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

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

    /___A___\   '__________________________'

     |  ~  |

   __'.___.'__

 ´   `  |° ´ Y `


Would you mind telling me your username on Github? (someuser) ysyun

What's the base name of your generator? (generator-angularjs_express)

   create package.json

   create .editorconfig

   ..중략..

   create app/templates/_component.json

npm http GET https://registry.npmjs.org/yeoman-generator


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

// app 밑으로 index.js 파일과 templates 폴더 생성

// yo 는 generator 밑의 폴더(여기선 app하나) 밑에 기본

// index.js 를 찾고 해당 파일을 수행한다 

// 즉, app가 있으므로 향후 명령은 yo angularjs-express:app 가 된다 

//

// mocha와 yeoman-generator가 설치됨

tree

.

├── LICENSE

├── README.md

├── app

│   ├── index.js

│   └── templates

│       ├── _component.json

│       ├── _package.json

│       ├── editorconfig

│       ├── jshintrc

│       └── travis.yml

├── node_modules

│   ├── mocha

│   └── yeoman-generator

├── package.json

└── test

    ├── test-creation.js

    └── test-load.js


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

// app이외의 다른 generator를 만들고 싶다면 subgenerator 이용

$ yo generator:subgenerator dowon

   create dowon/index.js

   create dowon/templates/somefile.js


$ cat index.js

'use strict';

var util = require('util');

var yeoman = require('yeoman-generator');


var DowonGenerator = module.exports = function DowonGenerator(args, options, config) {

  // By calling `NamedBase` here, we get the argument to the subgenerator call

  // as `this.name`.

  yeoman.generators.NamedBase.apply(this, arguments);


  console.log('You called the dowon subgenerator with the argument ' + this.name + '.');

};


util.inherits(DowonGenerator, yeoman.generators.NamedBase);


DowonGenerator.prototype.files = function files() {

  this.copy('somefile.js', 'somefile.js');

};


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

// angularjs-express라고 만든 Scaffoliding generator 사용하기 

/usr/local/lib/node_modules> sudo ln -s <your full path>/generator-angularjs_express generator-angularjs_express

/usr/local/lib/node_modules> yo -h


Angularjs_express

  angularjs_express:app

  angularjs_express:dowon


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

// 이제 명령어를 사용할 수 있다

$ yo angularjs_express:app 또는 dowon


다음에는 index.js 확장하는 방법을 알아보자 



<참조> 

  - 원문 : http://yeoman.io/generators.html

posted by Peter Note
2013. 4. 23. 22:08 Git, GitHub

Dogfeet 이분이 Git 전문가라는 생각이 든다. 번역본도 충실하며 끊임없이 노력하는 모습이 마음에 든다. 본받고 싶은분~~~



Git의 성공적인 Branching 전략

  - 성공적인 브랜칭 전략 한글 번역본 읽자

  - 일하는 flow (Workflow) 형태를 이해하고 싶다면 정리한  보자 (Pro Git 한글 번역본중 일부를 정리한 것임)



GitFlow 설치하여 Branching 전략에 맞는 Branch 생성하여 작업하기 

  - 설치 : 다양한 OS 설치 가이드

< 1단계 > 

$ git clone --recursive git://github.com/nvie/gitflow.git

$ sudo make install  (mac 경우 /usr/local/bin 에 설치된다)


 만일 /opt/local/bin에 설치를 원하면 하기와 같이 수행

$ sudo make prefix=/opt/local install


< 2단계 >

$ sudo chmod 755 /usr/local/bin/gitflow* (git-flow*)  

  또는 /opt/local/bin에 설치되었다면 

$ sudo chmod 755 /opt/local/bin/gitflow* (git-flow*)  


< 3단계 > 

/bin/sh^M 오류시 dos2unix 수행 (명령어 없으면 설치)

$ dos2unix /usr/local/bin/gitflow* 


  - 사용법 : 설명 원문

< 1단계 > 

최초 git flow 방식의 branch 전략을 사용할 계획인 git repository로 이동하여 한번만 셋업하기 


$ git flow init

No branches exist yet. Base branches must be created now.

Branch name for production releases: [master]

Branch name for "next release" development: [develop]


How to name your supporting branch prefixes?

Feature branches? [feature/]

Release branches? [release/]

Hotfix branches? [hotfix/]

Support branches? [support/]

Version tag prefix? []   <= 요건 주지 말자. 주게되면 git tag 시에 명칭의 앞에 항상 따라 붙는다. 


< 2단계 > 

feature 디렉토리 밑으로 login 브랜치 생성 

$ git flow feature start login


login commit 하고 develop 브랜치에 merge 하고 login 브랜치 삭제하고 develop 브랜치로 돌아옴 

$ git flow feature finish login


release v0.1.0 브랜치 생성 

$ git flow release start v0.1.0


release v0.1.0 브랜치를 태깅하고 master를 develop에 merge 해준다. 따라서 git checkout develop으로 이동해서 작업가능하다 

$ git flow release finish v0.1.0

  

  - 그래픽컬한 설명 (강추)



그림 보면서 Git 이해하기

  - 비쥬얼 Git 레퍼런스 한글 : 자주 사용하는 명령을 그림과 함께 설명

  - 왜 Git을 사용하는가? : 이제 Git으로 소스, 문서작업을 하자 



Dogfeet 님의 블로그 포스팅 참조

  - http://dogfeet.github.io/ : Git 과 GitHub 그리고 JavaScript, Node.js 에 대한 다양한 주제를 다루고 있다





<참조>

  - GitFlow 적용하기 

posted by Peter Note
2013. 4. 22. 23:42 Dev Environment/Build System

Yeoman은 generator-* 를 통하여 스케폴딩 코드 껍데기를 만들어준다. 이중 angular를 위해서 generator-angular와 테스트를 위한 generator-karma등 다양한 generator가 있고, 사용자가 원하는 generator를 만들 수가 있다. generator-angular안에는 클라이언트단만을 고려한 스케폴딩만 존하여 generator-angular를 GitHub에서 forking하여 ExpressJS를 붙여 프로젝트에 실제 필요한 스케폴딩을 만들어 본다



1) generator-angular forking

  - https://github.com/yeoman/generator-angular 에서 fork를 했다


  - 로컬로 복제한다 

    + git clone https://github.com/ysyun/generator-angular 

  - yeoman 1.0 beta 부터는 명령이 yo 로 바뀌었다. 포스팅 보고서 설치를 한다

  - yo 로 수행할 수 있는 generator 목록을 보자 

    + 만일 generator-angular 를 설치했다면 Angular 라고 나온다

    + Naming convention 규칙에 따라서 generator-[Name] 으로 generator가 만들어지고 [Name]만을 취한다

    + generator들은 npm install -g 옵션으로 설치하여 맥(Mac) 기준으로 /usr/local/lib/node_modules/* 밑에 설치된다 

$ yo --help

 Usage: yo GENERATOR [args] [options]


General options:

  -h, --help     # Print generator's options and usage

  -f, --force    # Overwrite files that already exist


Please choose a generator below.


Angular  <<=== generator-angular 

  angular:app

  angular:common

  angular:controller

  angular:directive

  angular:filter

  angular:main

  angular:route

  angular:service

  angular:view


Bootstrap

  bootstrap:app


Express

  express:app

  express:basic

  express:common


Generator

  generator

  generator:app

  generator:subgenerator


Karma

  karma:app


Mocha

  mocha:app

  mocha:generator


Webapp

  webapp:app


$ cd /usr/local/lib/node_modules && ls -alrt

drwxr-xr-x  13 nobody  staff   442  4 12 13:45 generator-karma

drwxr-xr-x  18 nobody  staff   612  4 12 14:30 npm

drwxr-xr-x  15 nobody  staff   510  4 12 14:31 bower

drwxr-xr-x  13 nobody  staff   442  4 12 15:03 grunt-cli

drwxr-xr-x   7 nobody  staff   238  4 18 09:57 yo

drwxr-xr-x  26 nobody  staff   884  4 18 10:42 generator-angular

drwxr-xr-x  16 nobody  staff   544  4 18 16:59 grunt-init

drwxr-xr-x  10 nobody  staff   340  4 19 23:46 grunt-express

drwxr-xr-x  16 nobody  staff   544  4 19 23:46 grunt

drwxr-xr-x  12 nobody  staff   408  4 22 10:20 coffee-script

drwxr-xr-x  16 nobody  staff   544  4 22 11:04 generator-express

drwxr-xr-x  14 nobody  staff   476  4 22 11:31 generator-generator

drwxr-xr-x  13 nobody  staff   442  4 22 11:44 generator-bootstrap

drwxr-xr-x  29 root    wheel   986  4 22 15:53 generator-angular_dowon

lrwxr-xr-x   1 root    wheel    48  4 22 17:08 generator-angular-sd -> /Users/nulpulum/development/generator-angular-sd


  - fork한 generator-angular를 로컬머신에서 generator-angular-sd 라는 별도 디렉토리에 받고, /usr/local/lib/node_modules/밑에 symbolic link 를 걸어주었다. 

  - 다시 yo --help를 해보면 하기와 같이 angular-sd가 나온다.

    + 앞으로 명령을 yo angular-sd:app 또는 yo angular-sd:express 명령을 치면 스케폴딩 소스가 생기는 것이다. 

Angular-sd

  angular-sd:app

  angular-sd:common

  angular-sd:controller

  angular-sd:directive

  angular-sd:express  <<=== 만들 대상 

  angular-sd:filter

  angular-sd:main

  angular-sd:route

  angular-sd:service

  angular-sd:view



2) Angular Express Generator 만들기 

  - https://github.com/hmalphettes/yeoman-angular-express-example  샘플을 참조해서 작성을 시도해 보았다 

  - 일단 Yeoman 스케폴딩 방식에 대해서 알아보자 (Yeoman Wiki 설명문)

    + Yeoman은 디렉토리별로 index.js 파일을 기본으로 참조한다 

    + 디폴트 디렉토리는 app 이다

    + 그렇다면 다음과 같은 구조가 될 것이다. 즉, yo --help 했을 때 최상위 generator-angular-sd 밑의 디렉토리명이 옵션이 된다

    + 초기 generator를 만드는 도구는 npm install -g generator-generator로 설치한다 (직접 만들고 싶다면 설치,우선 참조만)

angular-sd/

    app/index.js

    common/index.js

    controller/index.js

    ... 중략 ...

    view/index.js


  - yo angular-sd:express 를 수행하려면  generator-angular-sd/express/  디렉토리를 만들고, index.js를 만든다

    + 코드는 yeoman-generator 를 사용한다 

    + 파란색 부분이 중요하다. 모든 스케폴딩 코드 템플릿을 generator-angular-sd/templates/ 밑에 관리하는 것이 일반적이다

    + templates 디렉토리 밑에 express 디렉토리를 만든다  

// index.js

'use strict';

var path = require('path');

var util = require('util');

var yeoman = require('yeoman-generator');


module.exports = ExpressGenerator;


function ExpressGenerator() {

  yeoman.generators.Base.apply(this, arguments);

}


util.inherits(ExpressGenerator, yeoman.generators.Base);


ExpressGenerator.prototype.setupEnv = function setupEnv() {

  this.sourceRoot(path.join(__dirname, '../templates/express'));

  this.directory('.', '.', true);

};


  - templates/express/ 디렉토리 밑에 express 관련 views, routes, public 등을 놓아도 되지만 여기서는 app.js 만들 놓는다. 

    + yo angular-sd를 먼저 수행하면 app 디렉토리가 express의 public 정적 디렉토리 파일 역할을 해준다. 

    + Angular를 사용한다는 것은 SPA이기 때문에 index.html 하나만 두고 전부 partial html로 사용할 것이다.

    + 따라서 Express의 jade는 사용하지 않을 것이다. app.js 파일 하나만 만듦

    + 정적 파일 디렉토리를 app로 지정하고, '/' 요청은 '/app/index.html'로 보냄. index.html 은 angular 파일이다 

var express = require('express')

  , routes = require('./server/routes')

  , http = require('http')

  , path = require('path')

  , fs = require('fs');


var app = express();


app.configure(function(){

  app.set('port', process.env.PORT || 3000);

  // angular /app/views

  // app.set('views', __dirname + '/server/views');

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

  app.use(express.favicon());

  app.use(express.logger('dev'));

  app.use(express.bodyParser());

  app.use(express.methodOverride());

  app.use(app.router);

  // angular app == public dir

  app.use(express.static(path.join(__dirname, 'app')));

});


app.configure('development', function(){

  app.use(express.errorHandler());

});


app.get('/', function(req, res) {

  res.sendfile(__dirname + '/app/index.html');

});

// app.get('/', routes.index);

// app.get('/users', user.list);


http.createServer(app).listen(app.get('port'), function(){

  console.log("Express server listening on port " + app.get('port'));


  - package.json 내역에 express 포함시킴 

    + 스케폴딩 위치는 generator-angular-sd/templates/common 밑에 package.json 파일이 존재한다 (수정할 파일)

    + package.json의 내역을 참조하여 node_modules에 필요 모듈을 다운로드 한다 

    + 맨 마지막에 fork 하였던 https://github.com/ysyun/generator-angular 을 travis ci에 연동하기 위해 scripts{ test:...} 넣음

    + grunt express-server를 위하여 grunt-express를 넣음 

{

  "name": "anulgar-express",

  "description": "Grunt task for running an Express Server for Smart Dashboard",

  "homepage": "http://mobincon.tistory.com",

  "author": {

    "name": "Yun Young Sik",

    "email": "ysyun@yuwin.co.kr"

  },

  "repository": {

    "type": "git",

    "url": "https://github.com/ysyun/generator-angular"

  },

  "version": "0.0.1",

  "scripts": {

    "test": "grunt travis --verbose"

  },

  "dependencies": {

    "express": "~3.2.0",

    "jade": "~0.29.0"

  },

  "devDependencies": {

    "grunt": "~0.4.1",

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

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

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

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

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

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

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

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

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

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

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

    "grunt-contrib-livereload": "~0.1.2",

    "grunt-bower-requirejs": "~0.4.1",

    "grunt-usemin": "~0.1.10",

    "grunt-regarde": "~0.1.1",

    "grunt-rev": "~0.1.0",

    "grunt-karma": "~0.3.0",

    "grunt-open": "~0.2.0",

    "matchdep": "~0.1.1",

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

    "grunt-ngmin": "~0.0.2",

    "grunt-express": "git://github.com/hmalphettes/grunt-express.git",

    "socket.io": "*"

  },

  "engines": {

    "node": ">=0.8.0"

  }

}


  - 명령을 수행해 본다

    + yo angular-sd  : angular-sd:app 와 동일하고 generator-angular-sd/app/index.js 설정한 내역을 수행한다 

    + yo angular-sd:express : express 관련 파일을 스케폴딩한다. 초기에 jade도 넣었다가 그냥 app.js 만 놔두었다 

$ mkdir angular-express

$ cd angular-express

$ yo angular-sd

  ... 쭉 엔터치고 한참 의존관계있는 파일을 받는다 ...

$ ls -alrt

drwxr-xr-x   4 nulpulum  staff   136  4 22 23:15 ..

drwxr-xr-x   4 nulpulum  staff   136  4 22 23:16 test

-rw-r--r--   1 nulpulum  staff  1491  4 22 23:16 package.json

-rw-r--r--   1 nulpulum  staff  1273  4 22 23:16 karma.conf.js

-rw-r--r--   1 nulpulum  staff  1134  4 22 23:16 karma-e2e.conf.js

-rw-r--r--   1 nulpulum  staff   360  4 22 23:16 component.json

-rw-r--r--   1 nulpulum  staff  8189  4 22 23:16 Gruntfile.js

-rw-r--r--   1 nulpulum  staff   409  4 22 23:16 .jshintrc

-rw-r--r--   1 nulpulum  staff    50  4 22 23:16 .gitignore

-rw-r--r--   1 nulpulum  staff    11  4 22 23:16 .gitattributes

-rw-r--r--   1 nulpulum  staff   415  4 22 23:16 .editorconfig

-rw-r--r--   1 nulpulum  staff    38  4 22 23:16 .bowerrc

drwxr-xr-x  12 nulpulum  staff   408  4 22 23:16 app

drwxr-xr-x  15 nulpulum  staff   510  4 22 23:16 .

drwxr-xr-x  30 nulpulum  staff  1020  4 22 23:17 node_modules


$ yo angular-sd:express

   create app.js



3) Grunt file 만들기

  - Express에 대해서 grunt를 통하여 test, build, preview를 수행하기 위하여 Gruntfile.js를 수정한다

     + generator-angular-sd/templates/common/Gruntfile.js 가 수정파일이다 

     + package.json 파일 에서  "grunt-express": "git://github.com/hmalphettes/grunt-express.git" 꼭 들어가야 함

  - Gruntfile.js : 기존 generator-angular의 Gruntfile.js에서 express 관련 내역을 첨부한다 (파일참조)

'use strict';

var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

var mountFolder = function (connect, dir) {

  return connect.static(require('path').resolve(dir));

};

var path = require('path');


module.exports = function (grunt) {

  // load all grunt tasks

  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);


  // configurable paths

  var yeomanConfig = {

    app: 'app',

    dist: 'dist',

    server: 'server'

  };


  try {

    yeomanConfig.app = require('./component.json').appPath || yeomanConfig.app;

  } catch (e) {}


  grunt.initConfig({

    yeoman: yeomanConfig,

    watch: {

      coffee: {

        files: ['<%%= yeoman.app %>/scripts/{,*/}*.coffee'],

        tasks: ['coffee:dist']

      },

      coffeeTest: {

        files: ['test/spec/{,*/}*.coffee'],

        tasks: ['coffee:test']

      },

      compass: {

        files: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],

        tasks: ['compass']

      },

      livereload: {

        files: [

          '<%%= yeoman.app %>/{,*/}*.html',

          '{.tmp,<%%= yeoman.app %>}/styles/{,*/}*.css',

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

          '<%%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',

          '<%%= yeoman.server %>'

        ],

        tasks: ['livereload']

"Gruntfile.js" [dos] 349L, 8192C

        ],

        tasks: ['livereload']

      }

    },

    connect: {

      options: {

        port: 9000,

        // Change this to '0.0.0.0' to access the server from outside.

        hostname: 'localhost'

      },

      livereload: {

        options: {

          middleware: function (connect) {

            return [

              lrSnippet,

              mountFolder(connect, '.tmp'),

              mountFolder(connect, yeomanConfig.app)

            ];

          }

        }

      },

      test: {

        options: {

          middleware: function (connect) {

            return [

              mountFolder(connect, '.tmp'),

              mountFolder(connect, 'test')

            ];

          }

        }

      }

    },

    express: {

      livereload: {

        options: {

          port: 9000,

          bases: [ path.resolve('.tmp'), path.resolve(yeomanConfig.app) ],

          monitor: {},

          debug: true //,

          // server: path.resolve('/app')

        }

      },

      test: {

        options: {

          port: 9000,

          bases: [ path.resolve('.tmp'), path.resolve(yeomanConfig.app) ],

          port: 9000,

          bases: [ path.resolve('.tmp'), path.resolve(yeomanConfig.app) ],

          monitor: {},

          debug: true //,

          // server: path.resolve('/app')

        }

      }

    },


  ... 중략 ...

  grunt.registerTask('default', ['build']);



  // for express

  grunt.registerTask('express-server', [

    'clean:server',

    'coffee:dist',

    'compass:server',

    'livereload-start',

    'express:livereload',

    'open',

    'watch'

  ]);


  grunt.registerTask('express-test', [

    'clean:server',

    'coffee',

    'compass',

    'connect:test',

    'karma'

  ]);


  grunt.registerTask('travis', ['jshint', 'test']);


  - 명령 수행하기 

    + grunt express-test : 테스트 

    + grunt : 빌드

    + grunt express-server : 미리보기 수행


    + 명령을 수행하면 자동으로 브라우져가 뜨면 성공



모든 것이 성공했다면 Remote Repository로 push한다. 그리고 Travis-ci에 forking한 프로젝트를 연결한다. 해당 부분은 다음에 보도록 하자.


결과물 : https://github.com/ysyun/generator-angular



<참조>

  - Travis CI 연동하기

  - 2013.11 Monthly Digest for Yeoman

  - Yeoman : generator-fullstack with angular and express

  - Yeoman : generator-mean with angular and express, mongodb, node

posted by Peter Note
2013. 4. 20. 13:11 HTML5, CSS3/CSS

Sass의 반복 작업을 더욱 깔금하게 만들어주는 Compass에 대해서 알아보자



1) 개요

  - Compass에 대한 전반적인 개요

  

  - Ruby로 개발되어진 툴이기 때문에 Ruby 설치가 필요하다 

2) 설치 및 사용법
  - 설치 : gem install compass
  - 생성 : compass create <MyProject>  
    + 프로젝트 밑으로 .sass-cache 폴더와 sass/.sass-cache 폴더가 생성된다 
    + config.rb : 환경설정 내경이 반영되어 있다 
$ tree
.
├── config.rb
├── sass
│   ├── ie.scss
│   ├── print.scss
│   └── screen.scss
└── stylesheets
    ├── ie.css
    ├── print.css
    └── screen.css

2 directories, 7 files

////////////////////////////////////////////////////////////
// config.rb
$ cat config.rb
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
.. 중략..


   + 생성시의 옵션 : --help

$ compass create sass-bootstrap --help


Usage: compass create path/to/project [options]


Description:

Create a new compass project at the path specified.


Options:

        --using PATTERN              A framework's pattern to use when creating the project.

    -x, --syntax SYNTAX           Specify the syntax to use when generating stylesheets.

                                              One of sass or scss. Defaults to scss.

        --prepare                         Prepare the project by only creating configuration files.

    -r, --require LIBRARY            Require the given ruby LIBRARY before running commands.

                                              This is used to access compass plugins without having a

                                              project configuration file.

    -l, --load FRAMEWORK_DIR         Load the framework or extensions found in the FRAMEWORK directory.

    -L, --load-all FRAMEWORKS_DIR    Load all the frameworks or extensions found in the FRAMEWORKS_DIR directory.

    -I IMPORT_PATH                   Makes files under the IMPORT_PATH folder findable by Sass's @import directive.

    -q, --quiet                           Quiet mode.

        --trace                            Show a full stacktrace on error

        --force                            Allows compass to overwrite existing files.

        --dry-run                        Dry Run. Tells you what it plans to do.

        --boring                          Turn off colorized output.

    -c, --config CONFIG_FILE     Specify the location of the configuration file explicitly.

        --app APP                      Tell compass what kind of application it is integrating with. E.g. rails

        --sass-dir SRC_DIR          The source directory where you keep your sass stylesheets.

        --css-dir CSS_DIR            The target directory where you keep your css stylesheets.

        --images-dir IMAGES_DIR  The directory where you keep your images.

        --javascripts-dir JS_DIR     The directory where you keep your javascripts.

        --fonts-dir FONTS_DIR      The directory where you keep your fonts.

    -e, --environment ENV          Use sensible defaults for your current environment.

                                              One of: development (default), production

    -s, --output-style STYLE       Select a CSS output mode.

                                             One of: nested, expanded, compact, compressed

        --relative-assets              Make compass asset helpers generate relative urls to assets.

        --no-line-comments         Disable line comments.

        --bare                            Don't generate any Sass or CSS files.

    -?, -h, --help                       Show this message


posted by Peter Note
2013. 4. 20. 12:19 HTML5, CSS3/CSS

Sass는 CSS를 재미있게 만들어준다. 개발자에겐 접근하기 쉽겠지만 디자이너에겐 개발에 대한 고민을 하게 만드는 것같다. 하지만 현대적인 웹개발을 위하여 이제는 피할 수 없는 대세(?)인 Sass를 익혀야 한다.



1) 개요

  - 만들어진 배경에 대해서 이해하자 

  


  - 여러 기능들의 본질은 간결하고 반복작업을 없애주는 웹 개발 흐름을(Web Development Workflow) 만들어준다

    + Nested Rules : 들여쓰기 가능 - 상위 개체에 대한 정의를 줄인다 

// CSS

table.hl {

  margin: 2em 0;

}

table.hl td.ln {

  text-align: right;

}


// SCSS (Sassy CSS)

table.hl {

  margin: 2em 0;

  td.ln {

    text-align: right;

  }

}


// SASS

table.hl

  margin: 2em 0

  td.ln

    text-align: right


    + Variables : 변수를 사용하여 반복적인 상수를 줄인다 ($를 사용)

// CSS

.content-navigation {

  border-color: #3bbfce;

  color: #2b9eab;

}


// SCSS

$blue: #3bbfce;

$margin: 16px;


.content-navigation {

  border-color: $blue;

  color:

    darken($blue, 9%);

}


// SASS

$blue: #3bbfce

$margin: 16px


.content-navigation

  border-color: $blue

  color: darken($blue, 9%)


    + Mixins : 반복적인 입력을 함수화하는 것처럼 이용하여 코드를 줄인다 (@mixin @include 이용)

// CSS

#data {

  float: left;

  margin-left: 10px;

}

#data th {

  text-align: center;

  font-weight: bold;

}

#data td, #data th {

  padding: 2px;

}


// SCSS

@mixin table-base {

  th {

    text-align: center;

    font-weight: bold;

  }

  td, th {padding: 2px}

}


@mixin left($dist) {

  float: left;

  margin-left: $dist;

}


#data {

  @include left(10px);

  @include table-base;

}


// SASS

@mixin table-base

  th

    text-align: center

    font-weight: bold

  td, th

    padding: 2px


@mixin left($dist)

  float: left

  margin-left: $dist


#data

  @include left(10px)

  @include table-base


    + Selector Inheritance : 상속 개념으로 기존 코드를 줄인다 (@extend 사용)

// CSS

.error, .badError {

  border: 1px #f00;

  background: #fdd;

}


.error.intrusion,

.badError.intrusion {

  font-size: 1.3em;

  font-weight: bold;

}


.badError {

  border-width: 3px;

}


// SCSS

.error {

  border: 1px #f00;

  background: #fdd;

}

.error.intrusion {

  font-size: 1.3em;

  font-weight: bold;

}


.badError {

  @extend .error;

  border-width: 3px;

}


// SASS

.error

  border: 1px #f00

  background: #fdd


.error.intrusion

  font-size: 1.3em

  font-weight: bold


.badError

  @extend .error

  border-width: 3px


  - Sass는 두가지 문법으로 작성을 할 수 있다 

    + Scss : .scss 이고 {} 와 ; 가 존재, CSS3 의 확장자이다 (Sassy CSS)

    + Sass : .sass 이고 {} 와 ; 가 없고 대신 들여쓰기로 구분을 하여 간결함을 추구한다 (Haml 영향을 받음)

   


  - Sass는 색에 대한 Functions을 제공한다 (참조)

   예) 

   



2) 설치 및 사용법

  - gem install sass

  - 예제 코드 : dowon.scss

#dowon {

  width : 20%;

  height : 120px;

}

  - css 파일 변환하기 : sass --watch dowon.scss:dowon.css


  - Partials & Concatenation : @import 를 사용하고 분할된 파일의 컨벤션은 _partialFile.scss 즉 앞에 _ (underbar)를 붙여서 import 되는 파일을 따로 관리한다 그리고 컴파일을 하게 되면 지정한 하나의 파일 .css로 합쳐진다 


<참조>

  - Sass Tutorial

  - Sass References

  - Sass 온라인 테스트

  - Sass 개요 설명 - 한글

  - Sass 기능 설명 - 한글

posted by Peter Note
2013. 4. 20. 00:46 HTML5, CSS3/CSS

JavaScript에 CoffeeScript가 있다면 CSS에는 Stylus같은 CSS-Preprocessor가 있다고 할까? DRY(Don't Repeat Yourself)를 통하여 반복되는 구문을 없애주고 , {} 의 사용이 필요없다. 그외 다양한 기능이 있으니 자신에게 맞는 것을 선택하여 쓰자. 



1. Stylus 

  - Stylus 만든 분의 소개 동영상


  - 하지만 Stylus말고도 Less, Sass등이 있었으니 이제 결정할 때가 된것 같다



2. Sass

  - Sass 와 Compass에 대해 자세히 알아보자 


  - 이젠 Modern Web Development Workflow에 CoffeeScript + Sass 를 접목하자 



3. Less 

  - 좀 더 간단하게 사용할 수 있다 
  - 사용방법과 문법 소개 



<참조>

  - CSS에 대한 기초

  - Sass & Compass 배우기 35개 리소스 목록

posted by Peter Note
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 Peter Note

AngularJS의 테스트툴로 Testacular를 사용하는데 명칭이 Karma로 바뀌었다. WebStorm에 설정하고 사용하는 방법을 알아보자 



1) Karma 설치하기

  - 홈페이지 : http://karma-runner.github.io/0.8/index.html

  - 선조건 : WebStorm 설치 및 Node.js 설치

  - Karma를 global로 설치 : npm install -g karma



2) Yeoman을 통한 Karma 환경설정 

  - 일반적으로 Yeoman을 통하여 스케폴딩 코드를 만들어 사용하는 것이 좋다 : Yeoman 홈페이지

  - yeoman 설치 : npm install -g yo grunt-cli bower

  - angular 프로젝트 만들기 : yo angular 또는 yo angular:app

    

    <자동 생성된 파일 및 디렉토리 구조>


  - 자동 생성된 karma 테스트 환경파일 : karma.conf.js

/ Karma configuration
 
// base path, that will be used to resolve files and exclude
basePath = '';
 
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
'app/components/angular/angular.js',
'app/components/angular-mocks/angular-mocks.js',
'app/scripts/*.js',
'app/scripts/**/*.js',
'test/mock/**/*.js',
'test/spec/**/*.js'
];
 
// list of files to exclude
exclude = [];
 
// test results reporter to use
// possible values: dots || progress || growl
reporters = ['progress'];
 
// web server port
port = 8080;
 
// cli runner port
runnerPort = 9100;
 
// enable / disable colors in the output (reporters and logs)
colors = true;
 
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;
 
// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;
 
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers = ['Chrome'];
 
// If browser does not capture in given timeout [ms], kill it
captureTimeout = 5000;
 
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;



3) WebStorm 환경설정

  - Server 설정하기 

    + 웹스톰 상단의 메뉴에서 Edit Configurations... 클릭

    

   + Node.js로 "Karma Server" 생성 : node.js, karma 설치 위치와 프로젝트 위치, 파라미터로 start 입력

      카르마의 테스트 서버 역할을 수행


    + Karma Run 생성 : 파라미터로 run 입력, 테스트를 수행한다 


    + Karma Debug : JavaScript Debug의 Remote로 생성 

       Remote URL 로 "http://localhost:8080/" 입력 



4) 테스트 수행하기 

  - Karma Server 시작하기 

    + Karma Server 선택하고 > 시작 버튼 클릭

    + 하단에 localhost:8080 으로 Listen하는 서버 구동됨 

    + 브라우져가 자동 실행 : 자동 실행안되면 브라우져 띄워서 8080 호출 



  - Karma Run 테스트 하기 

    + 테스트 수행하기 

    + 테스트가 정상 수행되면 SUCCESS가 나온다. 비정상이면 FAILED 메세지


  - Karma Debug

    + 소스 코드에 Break point를 만들고 디버그 수행

    + 테스트 해본 결과 잘 안되는데 향후 다시 한번 체크해 봐야 겠다



5) 테스트 코드 

  - BDD 방식의 테스트 코드를 짠다 

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

// 업무 코드 

'use strict';
 
var app = angular.module('eggheadioApp');
 
app.controller('MainCtrl', function ($scope) {
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
}) ;
 
app.factory('Data', function() {
return {message: 'shared data'}
});
 
app.filter('reverse', function(Data) {
return function(text) {
return text.split("").reverse().join("");
}
});


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

// 필터에 대한 테스트 코드 

describe('filter', function() {
beforeEach(module('eggheadioApp'));
 
describe('reverse', function() {
it('should reverse a string', inject(function(reverseFilter){ //reverse라는 Filte 파라미터
expect(reverseFilter('ABCD')).toEqual('DCBA');
}))
})
})



<참조>

  - 원본 : 유튜브 동영상

posted by Peter Note