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

Publication

06-25 02:49

Category

Recent Comment

2013. 1. 27. 21:14 Languages/CoffeeScript

객체의 function으로 호출될 때 this. 값을 어떻게 줄여서 표현 하는지와 prototype 도 알아보자. 또한 extends를 어떻게 사용하는지도 알아본다


1) this.name = name 표현하기 

  - this. 을 @ 로 표현한다 

// prototype.coffee
###
function Dog (name) {
	this.name = name;
}
Dog.prototype.growl = function() {
	console.log("*growl*");
}
r = new Dog("Dowon");
r.growl();
###

Dog = (name) -> 
	@name = name # this.name = name

d = new Dog 'Dowon'
console.log d.name

console.log '----same thing----'

Dog2 = (@name) ->  # 파라미터로 @name을 쓰면 위와 같은 표현임 

d2 = new Dog2 'Dowon'

console.log d2.name 

// 결과 
D:\Development\coffeescript\3>coffee prototype
Dowon
----same thing----
Dowon

// prototype.js 컴파일 내역
(function() {
  var Dog, Dog2, d, d2;
  Dog = function(name) {
    return this.name = name;
  };
  d = new Dog('Dowon');
  console.log(d.name);

  console.log('----same thing----');

  Dog2 = function(name) {
    this.name = name;
  };
  d2 = new Dog2('Dowon');
  console.log(d2.name);
}).call(this);


  - Tip : 만일 (function(){ 코딩내역 }).call(this)  을 없애고 싶다면 --bare 옵션을 사용하면 됨



2) prototype. 표현하기

  - prototype. 을 :: 로 표현한다  

// prototype2.coffee
Dog = (@name) ->

Dog.prototype.growl = ->
	console.log '*growl*'

d = new Dog 'Dowon'
d.growl()

console.log '----same thing----'

Dog2 = (@name) ->
	
Dog2::growl = ->   # :: 로 표현한다 
	console.log '*growl*'

d2 = new Dog2 'Dowon'
d2.growl()

//결과 
D:\Development\coffeescript\3>coffee prototype2
*growl*
----same thing----
*growl*

// 컴파일 내역 : prototype2.js
// Generated by CoffeeScript 1.4.0
(function() {
  var Dog, Dog2, d, d2;
  Dog = function(name) {
    this.name = name;
  };
  Dog.prototype.growl = function() {
    return console.log('*growl*');
  };
  d = new Dog('Dowon');
  d.growl();

  console.log('----same thing----');

  Dog2 = function(name) {
    this.name = name;
  };
  Dog2.prototype.growl = function() {
    return console.log('*growl*');
  };
  d2 = new Dog2('Dowon');
  d2.growl();
}).call(this);


3) 상속에 대한 표현

  - extends 를 통하여 상속받기

// extend.coffee
Dog = (@name) ->

Dog.prototype.growl = ->
	console.log '*growl*'

BorderCollie = (@name, @tricks) ->

BorderCollie extends Dog

BorderCollie::perform = (trick) ->
	if trick in @tricks
		console.log "#{@name} is #{trick}"
	else
		console.log '*whine*'

dowon = new BorderCollie 'Dowon', ['playing dead', 'catching', 'rolling']

dowon.perform 'catching'
dowon.growl()	

// 결과 
D:\Development\coffeescript\3>coffee extend
Dowon is catching
*growl*

// 컴파일 내역 : extend.js
// Generated by CoffeeScript 1.4.0
(function() {
  var BorderCollie, Dog, dowon,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  Dog = function(name) {
    this.name = name;
  };
  Dog.prototype.growl = function() {
    return console.log('*growl*');
  };

  BorderCollie = function(name, tricks) {
    this.name = name;
    this.tricks = tricks;
  };

  __extends(BorderCollie, Dog);

  BorderCollie.prototype.perform = function(trick) {
    if (__indexOf.call(this.tricks, trick) >= 0) {
      return console.log("" + this.name + " is " + trick);
    } else {
      return console.log('*whine*');
    }
  };
  dowon = new BorderCollie('Dowon', ['playing dead', 'catching', 'rolling']);
  dowon.perform('catching');
  dowon.growl();
}).call(this);

 @ :: extends 를 익히자 ^^

coffeescript-3.zip


posted by peter yun 윤영식
2013. 1. 27. 20:10 Languages/JavaScript

this를 자바스크립트에서 만나게 되면 이게 어느 인스턴스의 this인지 파악하기가 난해하다. this는 context(Execute Context)와 Scope(유효범위)에 대한 부분을 잘 알아야 한다. 


1) function안에서 변수 접근 권한

function someFunc() {
    var _this = this;
    something.on("click", function() {
        console.log(_this);
    });
};

  - var _this = this; 문구는 왜 사용하는 것일까?

  - 첫번재 유효범위(First Scope)는 Global Scope 이다

    + 모든 변수(Variable)과 함수(Function)은 global이다. 

    + Global Scope는 window 객체이다 

    + window.x = 9; 라고 property를 설정하면 어디서나 접근이 가능하다 


function myFunc() {
    var x = 5;
});
console.log(x); // undefined

  - x 는 myFunc()안에서 초기화 되었고, myFunc()안에서만 접근이 가능하다 

  - var 키워드를 사용하지 않으면 자동으로 global 유효범위로 만들어진다 

  - var 키워드를 사용하면 function이 호출 될때 생성되는 context에 지역변수로(local variable) 포함된다

function myFunc() {
    x = 5;
});
console.log(x); // 5


  - Outer Function에 정의된 모든 변수는 다른 Inner Function에서 접근을 할 수 있다

function outer() {
   var x = 5;
   function inner() {
      console.log(x); // 5
   }
   inner();
}


  - Outer Function에서는 Inner Function의 변수를 접근 할 수 없다 

function outer() {
    var x = 5;
    function inner() {
        console.log(x); //5 
        var y = 10;
    }
    inner();
    console.log(y); //undefined
}


2) this의 유효범위 

  - this는 function이 호출될 때 자동으로 설정되는 변수이다 

  - 변수의 값은 function이 어떻게 호출되냐에 따라 틀려진다

  - 자바스크립트에서 함수를 호출하는 주된 몇가지 방법을 가지고 있다. (주로 사용하는 3가지 방법)

    + function이 method처럼 호출하기 : when a function is called as a method === 오브젝트.function은 메소드라 칭함

    + 자기자신위에 호출하기  : when a function is called on it's own === function 자체가 호출 오브젝트.function이 아닐 경우

    + event handler로서 호출하기 : when a function is called as an event handler == 이벤트 핸들러 수행시 호출되는 function

function foo() {
   console.log(this); //global object
};

myapp = {};
myapp.foo = function() {
   console.log(this); //points to myapp object
또는 (같은 내용)
myapp = {
   foo: function() {
     console.log(this); //points to myapp object
   }
}

var link = document.getElmentById("myId");
link.addEventListener("click", function() {
   console.log(this); //points to link
}, false);

  - addEventLister를 사용하여 function을 붙이면 this의 값이 변경된다 : this값은 caller로 부터 function에 전달된다 



$("myLink").on("click", function() {
    console.log(this); //points to myLink (as expected)
    var _this = this;  //store reference
    $.ajax({
        //ajax set up
        success: function() {
            console.log(this); //points to the global object. Huh?
            console.log(_this); //better!
        }
    });
});

  - myLink을 click하면 function이 수행된다. 이때 이벤트 핸들러로서 펑션의 this는 myLink DOM element의 참조로 설정된다

  - 그러나 ajax 정규호출의 this는 global object로 this 값을 설정한다. 이는 "event handler"도 "오브젝트 method"도 아닌 function이기 때문이다

  - 위와 같이 하는 것이 function을 호출하는 곳에서 this에 대한 값을 정확히 사용하기 위한 방법이다



3) Crockford on JavaScrpt

  - 백박의 중년 신사분이 JavaScript 언어에 대해 설명을 하고 있다. 우리나라에선 상상할 수 없는 일이겠지, 큰 세미나에 가봐야 젊은 친구들의 열정만을 엿볼 수 있는 부분을 생각해 보면 그들의 환경이 참 부럽다.

  - 15분경의 동영상에서 this의 호출에 대해서 보자 

  - 31분경에서 정확한 Closure 사용법 설명



<참조> 

  - 원문 : Scope and this in JavaScript

  - Scope 한글 블로깅 연재

  - Naver Dev JavaScript 클로져, 유효범위

posted by peter yun 윤영식
2013. 1. 24. 21:53 Languages/CoffeeScript

if, switch, for loop 구문등을 사용해 보자 


1) 조건문

  - yes : true, no : false, if not : unless 

  - if not 과 yes no 사용하기 : if2.coffee

machine = 
	running: no
	turnOn: -> this.running = yes
	turnOff: -> this.running = no

###
if not === unless
###
if not machine.running
	machine.turnOn()

machine.turnOne() if not machine.running
console.log machine.running

unless machine.running
	machine.turnOn()
else
	machine.turnOff()

// Generated by CoffeeScript 1.4.0
(function() {
  var machine;
  machine = {
    running: false,
    turnOn: function() {
      return this.running = true;
    },
    turnOff: function() {
      return this.running = false;
    }
  };

  /*
  if not === unless
  */
  if (!machine.running) {
    machine.turnOn();
  }
  if (!machine.running) {
    machine.turnOne();
  }
  console.log(machine.running);

  if (!machine.running) {
    machine.turnOn();
  } else {
    machine.turnOff();
  }
}).call(this);

// 결과 : 9번째 줄과 12번째 줄은 같은 구문이다 

D:\Development\coffeescript>coffee if2

true



  - switch ~ then 구문 사용하기 : switch.coffee

person = 
	name: "dowon"
	job: "programmer"

giveWork = (person) ->	
	switch person.job
	  when "programmer"
	  	console.log "1> Here's your code work, #{person.name}"
	  when "designer"
	  	console.log "1> Here's your design work, #{person.name}"
	  else 
	  	console.log "1> Um, do you work here?"	  	
giveWork person	  	

# or
person.job = "designer"
giveWork2 = (person) ->	
	switch person.job 
	  when "programmer" then console.log "2> Here's your code work, #{person.name}"
	  when "designer" then console.log "2> Here's your design work, #{person.name}"
	  else console.log "2> Um, do you work here?"
giveWork2 person

// Generated by CoffeeScript 1.4.0
var giveWork, giveWork2, person;
person = {
  name: "dowon",
  job: "programmer"
};

giveWork = function(person) {
  switch (person.job) {
    case "programmer":
      return console.log("1> Here's your code work, " + person.name);
    case "designer":
      return console.log("1> Here's your design work, " + person.name);
    default:
      return console.log("1> Um, do you work here?");
  }
};
giveWork(person);

person.job = "designer";
giveWork2 = function(person) {
  switch (person.job) {
    case "programmer":
      return console.log("2> Here's your code work, " + person.name);
    case "designer":
      return console.log("2> Here's your design work, " + person.name);
    default:
      return console.log("2> Um, do you work here?");
  }
};
giveWork2(person);

// 결과 

D:\Development\coffeescript>coffee switch

1> Here's your code work, dowon

2> Here's your design work, dowon



  - if 문 console.log를 앞으로 뽑아내기 : member.coffee

     + 컴파일 내역

     + 결과는 같지만 구문 코드는 틀리다 

     + 2번과 3번 구문이 제일 짧다 

person1 = 
	name: "dowon"
	relationship: "friend"
person2 = 
	name: "youngsik"
	relationship: "boss"

greet = (person) ->
	if person.relationship is "friend"
		console.log "1> hi, #{person.name}!"
	else if person.relationship is "boss"
		console.log "1> hello, papa!"
greet person1
greet person2
# or
greet2 = (person) ->
	msg = if person.relationship is "friend"
		"2> hi, #{person.name}!"
	else if person.relationship is "boss"
		"2> hello, papa!"
	console.log msg
greet2 person1
greet2 person2
# or
greet3 = (person) ->
	console.log if person.relationship is "friend"
		"3> hi, #{person.name}!"
	else if person.relationship is "boss"
		"3> hello, papa!"
greet3 person1
greet3 person2
# or
greet4 = (person) ->
	msg = switch person.relationship 
		when "friend" then "4> hi, #{person.name}!"
		when "boss" then "4> hello, papa!"
	console.log msg
greet4 person1
greet4 person2

// Generated by CoffeeScript 1.4.0
(function() {
  var greet, greet2, greet3, greet4, person1, person2;
  person1 = {
    name: "dowon",
    relationship: "friend"
  };
  person2 = {
    name: "youngsik",
    relationship: "boss"
  };

  greet = function(person) {
    if (person.relationship === "friend") {
      return console.log("1> hi, " + person.name + "!");
    } else if (person.relationship === "boss") {
      return console.log("1> hello, papa!");
    }
  };
  greet(person1);
  greet(person2);

  greet2 = function(person) {
    var msg;
    msg = person.relationship === "friend" ? "2> hi, " + person.name + "!" : person.relationship === "boss" ? "2> hello, papa!" : void 0;
    return console.log(msg);
  };
  greet2(person1);
  greet2(person2);

  greet3 = function(person) {
    return console.log(person.relationship === "friend" ? "3> hi, " + person.name + "!" : person.relationship === "boss" ? "3> hello, papa!" : void 0);
  };
  greet3(person1);
  greet3(person2);

  greet4 = function(person) {
    var msg;
    msg = (function() {
      switch (person.relationship) {
        case "friend":
          return "4> hi, " + person.name + "!";
        case "boss":
          return "4> hello, papa!";
      }
    })();
    return console.log(msg);
  };
  greet4(person1);
  greet4(person2);
}).call(this);

// 결과 : 전부 동일한 결과를 출력한다 

D:\Development\coffeescript>coffee member

1> hi, dowon!

1> hello, papa!

2> hi, dowon!

2> hello, papa!

3> hi, dowon!

3> hello, papa!

4> hi, dowon!

4> hello, papa!



2) for 구문 

  - for 구문을 다양하게 사용하는 방법

  - 5가지 for loop 문 사용방법 : loop.coffee

arr = ["Net", "Aet", "Photo", "Psd", "Cgt"]

obj = 
	name: "dowon"
	topic: "web development"
	editor: "yun"

###
for ( var i = 0; i < arr.length; i++) {
	console.log(arr[i]);
}	
###
console.log "---1---"
for siteName in arr
	console.log siteName

console.log "---2---"
console.log siteName for siteName in arr

console.log "---3---return array---"
console.log (siteName for siteName in arr)	

console.log "---4---"
for siteName, i in arr
	console.log "#{i}: #{siteName}"	

console.log "----5--"
for siteName, i in arr when siteName.indexOf("P") is 0	
	console.log "#{i}: #{siteName}"	

console.log "---6---"
###
by 2 ===  when i % 2 is 0
###
for siteName, i in arr by 2
	console.log "#{i}: #{siteName}"	


// Generated by CoffeeScript 1.4.0
(function() {
  var arr, i, obj, siteName, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _step;
  arr = ["Net", "Aet", "Photo", "Psd", "Cgt"];

  obj = {
    name: "dowon",
    topic: "web development",
    editor: "yun"
  };

  /*
  for ( var i = 0; i < arr.length; i++) {
  	console.log(arr[i]);
  }
  */
  console.log("---1---");
  for (_i = 0, _len = arr.length; _i < _len; _i++) {
    siteName = arr[_i];
    console.log(siteName);
  }

  console.log("---2---");
  for (_j = 0, _len1 = arr.length; _j < _len1; _j++) {
    siteName = arr[_j];
    console.log(siteName);
  }

  console.log("---3---return array---");
  console.log((function() {
    var _k, _len2, _results;
    _results = [];
    for (_k = 0, _len2 = arr.length; _k < _len2; _k++) {
      siteName = arr[_k];
      _results.push(siteName);
    }
    return _results;
  })());

  console.log("---4---");
  for (i = _k = 0, _len2 = arr.length; _k < _len2; i = ++_k) {
    siteName = arr[i];
    console.log("" + i + ": " + siteName);
  }

  console.log("----5--");
  for (i = _l = 0, _len3 = arr.length; _l < _len3; i = ++_l) {
    siteName = arr[i];
    if (siteName.indexOf("P") === 0) {
      console.log("" + i + ": " + siteName);
    }
  }

  console.log("---6---");
  /*
  by 2 ===  when i % 2 is 0
  */
  for (i = _m = 0, _len4 = arr.length, _step = 2; _m < _len4; i = _m += _step) {
    siteName = arr[i];
    console.log("" + i + ": " + siteName);
  }
}).call(this);	

// 결과

D:\Development\coffeescript\2>coffee loop

---1---

Net

Aet

Photo

Psd

Cgt

---2---

Net

Aet

Photo

Psd

Cgt

---3---return array---

[ 'Net', 'Aet', 'Photo', 'Psd', 'Cgt' ]

---4---

0: Net

1: Aet

2: Photo

3: Psd

4: Cgt

----5--

2: Photo

3: Psd

---6---

0: Net

2: Photo

4: Cgt



3) Scope 알아보기 

  - this 에 대한 유효범위(scope)를 보았을 때 object의 method로 사용되지 않는 단순 function 호출의 this는 global object (즉, UI에서는 window객체)를 가르킨다 (참조)

var classroom = {
	students: ["Jonh", "Jane", "Jill", "Joe"],
	print: function() {
		var thiz = this;
		function getName(i) {
			return thiz.students[i];
		}
		for(var i=0; i < this.students.length; i++) {
			console.log(getName(i));
		}
	}
}
classroom.print();


  - 위의 경우를 coffee로 표현하고자 할 경우 다음과 같이 => 사용하면 "var thiz = this;" 를 표현할 수 있다

classroom = 
	students: ["Jonh", "Jane", "Jill", "Joe"]
	print: ->
		getName = (i) =>    // =>를 사용하면 var thiz = this; 동일 효과가 가능하다 
			this.students[i]

		for s,i in this.students
			console.log getName i 

classroom.print()

// Generated by CoffeeScript 1.4.0
(function() {
  var classroom;
  classroom = {
    students: ["Jonh", "Jane", "Jill", "Joe"],
    print: function() {
      var getName, i, s, _i, _len, _ref, _results,
        _this = this;
      getName = function(i) {
        return _this.students[i];
      };
      _ref = this.students;
      _results = [];
      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
        s = _ref[i];
        _results.push(console.log(getName(i)));
      }
      return _results;
    }
  };
  classroom.print();
}).call(this);


* 파일 

coffeescript-2.zip


posted by peter yun 윤영식
2013. 1. 24. 21:52 Languages/CoffeeScript

CoffeeScript는 ; { 등을 가급적 배제하고 휴먼리더블하게 작성하게 해준다. 한줄띄기, 스페이스, 탭 등으로 구분하여 작문(코딩)을 한다 


1) 기본적인 작성법

  - 문자, 오브젝트, 범위, 변수

  - 문자 다루기 : #{} 을 통하여 변수 맵핑 : hi.coffee

name = "dowon"
greeting = "hi, #{name}!"
multi = """
this is a greeting:
	#{greeting}

"""
console.log multi

// 결과 : """ 를 사용했을 때 내부의 띄워쓰기 그대로 적용됨 <pre> 태그 유사 

D:\Development\coffeescript>coffee hi


this is a greeting:

        hi, dowon!


D:\Development\coffeescript>



  - 범위 다루기 : ..과 ... 의 차이는 끝수 포함/미포함 : range.coffe

range = [0..10]
console.log range

range = [0...10]
console.log range

range = [15...10]
console.log range

// 결과

D:\Development\coffeescript>coffee range

[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

[ 15, 14, 13, 12, 11 ]


  

  - 오브젝트 다루기 : obj.coffee

obj = name: "dowon", job: "Programmer"
console.log obj
obj = 
	name: "dowon-01" 
	job: "Programmer-01"
console.log obj

name = "dowon-02"
job = "Programmer-02"
obj = name: name, job: job
console.log obj

obj = {name, job}
console.log obj

 - key:value 같은 줄에 쓰면 콤마(,) 구분

 - 한줄 띠기 하면 콤마 필요없음

 - {name} 하면 명칭을 그대로 key 명칭을 활용


// 결과 

D:\Development\coffeescript>coffee obj

{ name: 'dowon', job: 'Programmer' }

{ name: 'dowon-01', job: 'Programmer-01' }

{ name: 'dowon-02', job: 'Programmer-02' }

{ name: 'dowon-02', job: 'Programmer-02' }



  - 변수 다루기 : variable.coffee

[one, two, three] = ["1", "2", "3"]
console.log two
console.log three
name = "dowon"
obj = {name, job:"Programm er", other: {name}}
console.log obj

// Generated by CoffeeScript 1.4.0
(function() {
  var name, obj, one, three, two, _ref;
  _ref = ["1", "2", "3"], one = _ref[0], two = _ref[1], three = _ref[2];

  console.log(two);
  console.log(three);
  name = "dowon";
  obj = {
    name: name,
    job: "Programmer",
    other: {
      name: name
    }
  };
  console.log(obj);
}).call(this);

// 결과 

D:\Development\coffeescript>coffee variable

2

3

{ name: 'dowon', job: 'Programmer', other: { name: 'dowon' } }



2) Function 다루기 

  - 주석, 함수, 아규먼트 배열, Math.random 

  - 주석 : # 무시되는 문장 (컴파일시 주석문도 안남음), ### 주석 /* */ 으로 변환 : comment.coffee

one = 1 # comment
###
comment 2
###
two = 2


  - 함수 만들기 : -> 사용 : greet.coffee

###
function greet (name) {
	console.log("hi" + name +"!");
}
greet = function(name) {
}
###

greet = (name) -> console.log "hi #{name}!"
greet "Greeting" 
greet2 = (name = "friend") -> "hi #{name}"
console.log greet2
console.log greet2()

// 결과

D:\Development\coffeescript>coffee greet

hi Greeting!

[Function]

hi friend       <=== () 를 붙여서 함수 호출한다 



  - 배열 아규먼트 만들기 : ... 사용 : array.coffee

test = (x, y, z...) -> 
	console.log x
	console.log y
	console.log z

test "one", "two", "three"
console.log "---------------------"
test "one", "two", "three", "four", "five"	


test2 = (x..., y, z) -> 
	console.log x
	console.log y
	console.log z

test2 "one", "two", "three"
console.log "---------------------"
test2 "one", "two", "three", "four", "five"	

test3 = (x, y..., z) -> 
	console.log x
	console.log y
	console.log z

test3 "one", "two", "three"
console.log "---------------------"
test3 "one", "two", "three", "four", "five"	

// 결과 

D:\Development\coffeescript>coffee array

one

two

[ 'three' ]   

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

one

two

[ 'three', 'four', 'five' ]


// test2 호출 

[ 'one' ]

two

three

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

[ 'one', 'two', 'three' ]

four

five


// test3 호출 

one

[ 'two' ]

three

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

one

[ 'two', 'three', 'four' ]

five



  - 자동 실행 함수 : do 사용하여 자동 실행토록 만들어준다 : anon.coffee

###
(() -> console.log())()
###

###
automatically invoke function
###
do (message = "hi dowon") ->
	console.log message

// Generated by CoffeeScript 1.4.0
/*
(() -> console.log())()
*/

/*
automatically invoke function
*/

(function() {
  (function(message) {
    return console.log(message);
  })("hi dowon");

}).call(this);

// 결과 : 만일 do를 넣지 않으면 수행되지 않음

D:\Development\coffeescript>coffee anon

hi dowon



  - Math.random 사용하기 : random.coffee

###
Math.random()
###

rand = (max = 10, min = 0) -> Math.floor(Math.random() * (max - min + 1)) + min

console.log rand()
console.log rand 100
console.log rand 60, 50

// 결과 : 수행때 마다 틀린 random값이 지정 범위내에서 출력됨 

D:\Development\coffeescript>coffee random

5

100

53


D:\Development\coffeescript>coffee random

1

32

53



3) 비교연산

  - ===, !== 사용하기 

  - if 문 사용하기 

  - ===, !== 를 사용하는 대신 is, isnt  문장으로 사용하기 : operator.coffee

###
is ===
isnt !==
###
name = "dowon"
if name is "dowon"
	console.log "great"

if name isnt "Dowon"
	console.log "poor"	

### if( !false ) ###
if not false
	console.log "cool"

###
var name = "dowon",
	job = "programmer";

if(name === "dowon" || job === "programmer") {
	console.log("right")
}	
###
name = "dowon"
job = "programmer"

if name is "dowon" and job is "programmer"
	console.log "right"

// 결과

D:\Development\coffeescript>coffee operator

great

poor

cool

right



  - ? 연산자를 통하여 null 체크 하기 : operator2.coffee

name = "dowon"
if name?
	console.log "hi"
person = 
	name: "dowon"
	job: "programmer"

console.log person?.name
name = name || "youngsik"
name ||= "youngsik"
name ?= "youngsik"
console.log name

// Generated by CoffeeScript 1.4.0
(function() {
  var name, person;
  name = "dowon";
  if (name != null) {
    console.log("hi");
  }
  person = {
    name: "dowon",
    job: "programmer"
  };

  console.log(person != null ? person.name : void 0);
  name = name || "youngsik";
  name || (name = "youngsik");
  if (name == null) {
    name = "youngsik";
  }
  console.log(name);
}).call(this);

// 결과

D:\Development\coffeescript>coffee operator2

hi

dowon

dowon



  - if 문을 재구성한다 : if.coffee

# x = 4
# if( x >= 0 && x <= 10) {}
x = 4
if 0 <= x <= 10
	console.log "true"

// Generated by CoffeeScript 1.4.0
(function() {
  var x;
  x = 4;
  if ((0 <= x && x <= 10)) {
    console.log("true");
  }
}).call(this);

// 결과

D:\Development\coffeescript>coffee if

true


* 테스트 파일 다운로드



4) CoffeeScript 문법 & 장/단점

  - if 문을 한줄로 사용할 때 조건 뒤에 then 구문 붙이기 

    예) if name is "dowon" then console.log "right"

posted by peter yun 윤영식
2013. 1. 24. 21:51 Languages/CoffeeScript

CoffeeScript를 설치하고 사용해 보자 


1. 설치하기

  - Node.js 설치함

  - NPM(Node Package Manager) 설치함 : npm을 통하여 coffe-script 를 설치한다 

  - 참조 : http://coffeescript.org

D:\Development\javascript>npm install -g coffee-script

npm http GET https://registry.npmjs.org/coffee-script

npm http 200 https://registry.npmjs.org/coffee-script

C:\Documents and Settings\UserXP\Application Data\npm\cake -> C:\Documents and Settings\UserXP\Application Data\npm\node_modules\coffee-script\bin\cake

C:\Documents and Settings\UserXP\Application Data\npm\coffee -> C:\Documents and Settings\UserXP\Application Data\npm\node_modules\coffee-script\bin\coffee

coffee-script@1.4.0 C:\Documents and Settings\UserXP\Application Data\npm\node_m

odules\coffee-script


D:\Development\javascript>coffee -v

CoffeeScript version 1.4.0



2. Coffee 사용하기 

  - 확장자 .coffee 파일을 만든다

  - coffee 명령으로 수행할 수도 있고, js 파일로 컴파일 할 수도 있다


  - 일반적인 js 코딩 : arr.js

function makeArray(dimension) {
        var arr = [], i = 0, j = 0;
	for(; i < dimension; i++) {
		arr[i] = [];
		for( j=0; j < dimension; j++) {
			arr[i][j] = '1111';
		}
	}
	return arr;
}

var myArr = makeArray(4);

console.log(myArr);

// 결과 

D:\coffeescript>node arr

[ [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ] ]



- CoffeeScript 코딩 방식 : arr.coffee (coffee 확장자)

makeArray = (dimension) ->
	arr = []
	for i in [0...dimension]
		arr[i] = []
		arr[i][j] = '1111' for j in [0...dimension]
	arr
	
myArr = makeArray 4

console.log myArr	

console.log 'dowon hi'

// 결과 

D:\coffeescript>coffee arr.coffee

[ [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ],

  [ '1111', '1111', '1111', '1111' ] ]



- CoffeeScript js를 일반 js 파일로 컴파일 하기 

D:\coffeescript>coffee -c arr.coffee


// 컴파일로 생성된 arr.js 소스 파일 

// Generated by CoffeeScript 1.4.0
(function() {
  var makeArray, myArr;

  makeArray = function(dimension) {
    var arr, i, j, _i, _j;
    arr = [];
    for (i = _i = 0; 0 <= dimension ? _i < dimension : _i > dimension; i = 0 <= dimension ? ++_i : --_i) {
      arr[i] = [];
      for (j = _j = 0; 0 <= dimension ? _j < dimension : _j > dimension; j = 0 <= dimension ? ++_j : --_j) {
        arr[i][j] = '1111';
      }
    }
    return arr;
  };

  myArr = makeArray(4);

  console.log(myArr);

  console.log('dowon hi');

}).call(this);



3. Coffee Watching & REPL(레플) 사용하기

  - coffee 파일이 변경되어 저장되는 시점에 자동으로 컴파일 되도록 한다 : watch

  - w 옵션을 준다 

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

// watch 옵션 주기

D:\Development\coffeescript>coffee -cw arr.coffee

17:51:59 - compiled arr.coffee

17:52:29 - compiled arr.coffee   <--- arr.coffee 파일 마지막에 새로운 내용을 넣고 저장하면 자동으로 compile 됨


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

// REPL을 통하여 coffee 수행해 보기

D:\Development\coffeescript>coffee

coffee> 1 + 1

2

coffee> arr = []

[]

coffee> arr[0] = 'dowon'

'dowon'

coffee> arr

[ 'dowon' ]

coffee> arr.push 'hi'

2

coffee> arr

[ 'dowon', 'hi' ]

coffee> arr[1]

'hi'

coffee>



4. Single Page Application (SPA : 스파) 를 만들때 CoffeeScript를 사용하자

  - 코딩을 간결하게 해준다

  - global variable등의 사소한 문법오류를 잡아준다 

  - 그러나 compile된 코드는 좀 긴것 같아서 byte 수의 증가를 초래하는 듯하다

  - BackboneJS와도 잘 어울린다 


<참조>

posted by peter yun 윤영식
2013. 1. 11. 09:52 Languages/Java

1) Korea Spring User Group의 세미나 자료  


1. Spring MVC를 손쉽게 테스트하기 (백기선) : 동영상 , 발표 자료

2. RESTful API(including Mobile) with Spring 3.1 (윤성준) : 동영상발표 자료

3. Spring 3.1에서 Ehcache 활용전략  (김흥래) : 동영상발표 자료

4. SpringFramework in Scala (석종일) : 동영상발표 자료

5. Type-safe querying using Querydsl (김영한) : 동영상발표 자료



2) 내 관심 사항

  - 테스트하기 

  - RESTful API 만들기 

  - Ehcache 활용전략

posted by peter yun 윤영식
2012. 12. 27. 17:31 Languages/Java

Java 클래스의 bytecode instrument 프레임워크인 ASM Guide 문서를 읽고 간단히 정리해 보자 


* 참조 파일


> Object Based Model

  - ASM 라이브러리는 컴파일된 클래스의 generating 과 transforming API를 제공한다.

  - DOM(예)의 경우 : event 기반 모델로 클래스를 이벤트 시퀀스로 표현한다. (Event Based Model)

  - ASM의 경우 : object 기반 모델로 클래스를 오브젝트 트리로 표현한다. (Object Based Model)

 

> 구성

  - asm.jar : class parster 와 writer  (core API)

  - asm-util.jar : 개발, 디버깅시에 사용 (core 의존)

  - asm-commons.jar : 미리 정의한 class 변환기 (core 의존)

  - asm-tree.jar : object 표현을 event 표현으로 변환

  - asm-analysis.jar : 미리 정의한 분석기와 분석 프레임워크 (tree 의존)


> Core API

  - class methods, annotations, generics에 대한 generate 과 transform을 Core API 활용하여 어떻게 하는지 알아본다

  - 컴파일된 클래스 구조(Structure) : 간단히 3가지로 나뉨

    + modifier 영역 : public, private

    + field 영역 : modifier, type이나 annotation of a field, name 선언

    + method, constructor 영역 : modifier, name, return, parameter type, annotation of a method

  - 컴파일 클래스와 소스의 차이

    + 소스는 여러 클래스를 포함한다 : inner class

    + 컴파일 클래스는 하나 클래스로 표현하고 comment 제거하고 package, import도 포함하지 않는다. 

    + 컴파일 클래스는 "constant pool"가 있다. constant pool은 배열(Array)이다. 한번만 생성이 도고 index로 참조되어 진다. 

      >>> 컴파일 클래스의 전체 구조

    


    + 컴파일 클래스는 타입표현 명명이 틀리다. internal name 은 클래스의 전체 이름을 사용한다. 

       java/lang/String같이 slash(/)로 구분한다.

    + Internal name은 type에도 적용된다. (type descriptor)

      >>> type descriptor 맵핑

     


    + method descriptor는 type descriptor의 목록이다.

      >>> 메소드 예

    


  - ClassVisitor 추상 클래스가 컴파일된 클래스의 생성/변환을 담당한다. AnnotationVisitor, FieldVisitor, MethodVisitor 리턴

   

  - FieldVisitor 추상 클래스 

   


  - Core API는 ClassVisitor API에 기반하여 클래스 generate 와 transform 할 수 있게 3가지 core 컴포넌트를 제공한다

    + ClassReader : byte array 주어진 컴파일된 클래스를 파싱한다. ClassVisitor를 accept 메소드 파라미터로 주면 

                            visitXxx 메소드를 호출한다 (event producer)

    + ClassWriter : ClassVisitor의 subclass이고 컴파일된 클래스를 바이너리로 만든다. toByteArray메소드롤 얻을 수 있는 

                            byte array로 결과물을 생산한다 (event consumer) 

    + ClassVisitor : 다른 ClassVisitor를 받으면 메소드 호출을 위임한다 (event filter)

posted by peter yun 윤영식
2012. 12. 25. 23:55 Languages/Java

그루비도 Closure를 지원한다. 그렇다면 Closure에 대하여 알아보자. (좀 더 정리할 필요가 있겠음)


> 클로저의 가치

  - 함수 객체(function objects) 또는 익명 함수(anonymous function)로서 작용한다.

  - 유형 시스템(type system)이 데이터뿐만 아니라 코드도 나타낼 수 있어야 한다는 점에 유형 시스템에 대한 결과도 갖는다 (음 무슨 말인지 이해안감ㅜㅠ)

  - 함수들을 퍼스트-클래스 객체들로서 지원한다. 

  - 함수들은 변수에 저장될 수 있고, 매개변수로서 다른 함수에 저장된다.

  - 동적으로 생성되고, 함수들에서 리턴된다. 

  - 클러저는 Scheme, Common Lisp, Smalltalk, Groovy, JavaScript, Ruby, Python에서 찾아 볼 수 있다.


<참조>

  - 클로저 논의 IBM 번역

  - JavaScript에서의 클로저

posted by peter yun 윤영식
2012. 12. 25. 23:33 Languages/Java

IntelliJ IDE 에서 그루비를 실행하고 테스트해보자. 우선 Eclipse에서 어떻게 수행되는지 동영상을 보고 따라해 보도록 한다. 


> 이클립스에서 그루비 실행하기 

  - 그루비 한글번역 튜토리얼

  - IntelliJ IDE에서 JUnit 4 테스트를 생성하고 구동시키는 방법 



> IntelliJ IDE에서 그루비 생성하고 클래스 테스트하기 


위의 eclipse 기준 동영상을 IntelliJ IDE에 맞추어 테스트 해본다 

1) 새로운 프로젝트 생성

  - New Project 생성

  - step-01 : Java Module 선택


  - step-02 : src 디렉토리 선택

  - step-03 : Groovy 선택 (사전에 Groovy는 설치되어 있어야 한다)


2) 그루비 테스트 하기  

// collection & closure

def coll = ["groovy", "java", "ruby"]  // javascript처럼 컬렉션을 만들 수 있다

assert  coll instanceof Collection // assert 결과가 true이면 다음 문장으로 계속 수행함 

assert coll instanceof ArrayList

println coll.class

println coll


coll << "perl"  // 추가하기 


println coll


coll[4] = 'python'  // 배열처럼 직접 삽입

println coll


println coll - ['java'] // 값 빼기 


// closure 1

coll.each{  value ->    // 파라미터 명을 value로 설정함 

    println '> ' + value

}

// closure 2

def excite = { word ->

    return "${word}!!"

}

assert 'Dowon!!' == excite('Dowon')

println excite('Dowon')


// key=value의 map 객체를 만듦 

def hash = [name:'yun', 'age':27]

assert hash.getClass() == java.util.LinkedHashMap

println hash


hash.height = 177   // key=value 추가하기 

println hash


hash.put('height', 190)  // put 이용

println hash


3) Song 클래스 만들기

// set, get 메소드가 자동으로 만들어 진다. 

// getGenre() 메소드를 재정의한다

class Song {

    def name

    def artist

    def genre


    String toString() {

        "${name}, ${artist}, ${getGenre()}"

    }


    def getGenre() {

        genre.toUpperCase()

    }

}


4) SongExample로 Song 클래스 수행 : ctrl + shift + F10 으로 수행한다 

class SongExample {

    static void main(args) {

       // 생성자는 그루비가 자동으로 생성해 준다 

        Song sng = new Song(name: "tear's heaven", artist: "singer", genre: "rock")

        sng.name = "hi"

        sng.setArtist("dowon")   // set, get 메소드가 이미 있으므로 호출 가능하다 

        println sng


        Song sng2 = new Song()

        // name 지정을 하지 않았으므로 null이다. ?를 하면 null safety 체크한다  

        // 즉 name 이 null 이면 toUpperCase() 를 수행하지 않는다 

        println sng2.name?.toUpperCase()  

    }

}


5)  테스트 코드를 작성한다 : java의 junit 코드로 짜된다 어차피 그루비도 수행시 컴파일 되면 java와 같이 bytecode로 변경된다

  - ctrl + shift + t 클릭하면 "Create New Test..." 메뉴를 선택한다
   


  - JUnit4를 선택하고 OK 클릭한다
   


  - Test 코드를 작성한다 : Groovy 스타일 Test 케이스를 만들 수도 있고, Java 스타일 Test 케이스도 가능하다 (Bi-direction)

import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Test;

public class SongTest  {
    @Test
    public void testToString() {
        Song song = new Song();
        song.setName("Smells like teen spirits");
        song.setArtist("youngsik");
        song.setGenre("hard rock");

        Assert.assertEquals("Smells like teen spirits, youngsik, HARD ROCK", song.toString());
    }
}


posted by peter yun 윤영식
2012. 12. 25. 02:04 Languages/Java

Groovy를 통해 많은 생태계가 만들어지고 있다. 그중 Gradle이라는 Build Automation 툴을 사용하려 한다. Groovy의 생태계와 DSL에 대해 알아보자 


> Groovy가 만들고 있는 생태계

  • Grails와 같은 Framework 에 사용
  • Easyb(BDD)와 같은 Testing 에 사용
  • Gradle 과 같은 Build Automation Tool 에 사용
  • 기타등등

> Groovy 기본 개념과 DSL 그리고 생태계

  • Groovy는 Dynamic 언어 (2003년 시작)
  • SpringSource, JBoss 등 많은 오픈소스진영에서 사용중
  • Fully Object-Oriented, Closures, Properties, Optional typing, wrapper APIs, authoring DSLs, lively ecosystem


> Groovy DSL 배우기 


posted by peter yun 윤영식
2012. 12. 23. 22:02 Languages/JavaScript

Java의 Spring과 같이 확장성이 높은 JavaScript 프레임워크를 만들기 위한 아키텍쳐에 대하여 알아보자 


  - Module Layer를 두어 모듈 단위로 모든것을 개발한다.

  - SandBox Layer 를 두어 Module이 상호 통신하는 인터페이스와 보안, 가이드 역할을 한다.

  - Core Layer 를 두어 Module의 LifeCycle을 책임진다. 모듈간 통신과 에러 핸들링, 확장을 수행. 

  - Base Library Layer 를 두어 기본 함수와 유틸을 제공한다. : JQuery, YUI 같은 것


> 유지보수 가능한 JavaScript 전략


> 고성능을 내기위한 JavaScript 전략 (Responsive JavaScript 코딩 전략)


  - UI Thread 작업시에는 Queue를 이용하라

  - JavaScript Execution 시간을 50ms 이상으로 하지 마라

  - JavaScript 다운로드하고 파싱하고 실행할때까지 HTML Rendering이 멈춘다. JavaScript은 무조건 HTML 맨 밑에 배치함

  - JavaScript를 쪼개 놓지 말고 합쳐서 다운로드 타임으로 조금이라도 줄여라 

  - 필요한 시점에 동적으로 스크립트 파일을 로딩한다

  - Reflow와 Repaint 횟수를 줄이는 것이 성능 최적화에 중요함

posted by peter yun 윤영식
2012. 12. 23. 21:51 Languages/JavaScript

Java에서 할 수 있다면 ECMAScript에서도 할 수 있지 않을까? 테스트를 어떻게 하는지 알아보자 


  - named function을 사용하라 (가급적 anonymous function 사용 배제)

  - namespace를 사용한다

  - 속성, 펑션은 return {key:value} 클로저 객체로 리턴한다

  - 펑션 내부 계산로직에 대해 return 하여 검증할 수 있게 한다

  - Functional Testing

    + gebish.org

    + zombie.labnotes.org

    + phantomjs.org


  - 단위 테스트 

    + QUnit ( docs.jquery.com/QUnit )

    + sinonjs.org

    + mocha

    + JsTestDriver

    + YUITest


> JsTestDriver를 통한 효율적인 JavaScript 테스팅하기



  - JsTestDriver와 Maven 연결 테스트하기

  - JsTestDriver 설정을 통하여 Jenkins에 xUnit Plugin 연동하여 테스트

  - 여러 브라우저에 대하여 테스트하기 

  - http://tddjs.com 참조


> BDD(Behavior Driven Development) JavaScript 


posted by peter yun 윤영식
2012. 12. 21. 16:18 Languages/JavaScript

렌더링 과정에 대하여 알아보고, 렌더링시 성능 최적화할 수 있는 방법들을 살펴보자 (책. 4장 렌더링)



▶ 전체 브라우저 렌더링 처리 과정


  - 전체 브라우저 처리과정 : HTML DOM 트리 + CSS 스타일 구조체 = 렌더 트리 생성 (레이아웃 처리) -> 페인트 (화면에 표현)

  - DOM 트리 생성 : HTML을 DOM 요소 노드 트리 형태로 구성.

  - 스타일 구조체 생성 : CSS 정보를 스타일 구조체(Style Struct)로 생성한다. 

  - 렌더 트리 생성 : DOM 트리와 각 노드에 스타일 정보를 설정하여 화면에 표현할 노드로 구성한다. DOM 트리와 렌더 트리는 1:1 대응하지 않는다.

  - 레이아웃 처리 : 렌더 트리의 각 노드 크기가 계산되어 위치계산한다.

  - 페인트(Paint) : 렌더 트리를 순회하면서 페인트 함수를 호출해 노드를 화면에 표현한다.



▶ 리플로와 페인트


  - 리플로(Reflow) : Ajax와 같은 데이터를 가져와서 화면에 뿌릴라 치면 변경이 필요한 렌더 트리에 대한 유효성 확인 작업과 함께 노드의 크기와 위치를 다시 계산한다. 이과정을 리플로 = 레이아웃(Layout) = 레이아웃팅(Layouting)  이라 한다. (부모 노드의 변경은 자식 노드 변경 리플로도 야기한다)

  - 리페인트(Repaint) : 변경 영역의 결과를 표현하기 위해 화면이 업데이트 되는 것을 의미한다. 리페인트 = 리드로(Redraw) 

  - 리플로 와 리페인트는 비용이 높다. 발생하는 원인을 살펴보자 

    + DOM 노드의 변경 : 추가, 삭제

    + DOM 노드 노출 속성을 통한 변경 : 추가, 삭제, 특성 변경

    + 스크립트 애니메이션 : 애니메이션은 DOM, 스타일 등이 짧은 시간에 수차례 변경되는 것임

    + 스타일 : 추가, 변경

    + 사용자 액션 : 브라우저 크기 변경, 글꼴 크기 변경등 



▶ 리플로 & 페인트 최소화 방법


  - 작업 그룹핑 : DOM 요소 변경시 같은 형태끼리 그룹으로 묶어서 실행한다. 

  - 실행 사이클 : 루핑 구문 즉 setTimeOut같은 구문에서 DOM 요소 핸들링을 배제한다.

  - display 속성 : 루핑이 어쩔 수 없다면 

element.style.display="none"; 

<looping구문> 

element.style.display="block";  


  - 이렇게 하면 루핑구문에서 "리플로+페인트"가 계속 발생하지 않고, none과 block 할때 딱 두번만 발생한다.

  - 노드 복제 : 루핑도는 구문에서 노드 핸들링시 원복 노드를 복제하여 사용함 

var clone = element.cloneNode(true);

<looping 구문>

parentNode.replaceChild(clone, element);


  - createDocumentFragment() 사용 : DOM 객체와 별개의 새로운 DOM 객체를 생성하여 사용하면 렌더링 성능 향상 가능함.

var fragment = document.createDocumentFragment(); 

<looping 구문안에서 fragment.appendChile(elems[e]); 호출 > 


  - 캐싱 : 별도의 변수에 자주 사용하는 속성값 또는 메소드값을 저장하여 사용한다. 

  - 하드웨어 가속 렌더링 : GPU를 이용한다. 브라우져 마다 설정값이 틀림. (크롬 :  chrome://flags 로 GPU 설정 확인 가능)


posted by peter yun 윤영식
2012. 12. 13. 16:48 Languages/JavaScript

NHN의 자바스크립트 성능 이야기 Chapter 3을 간략히 정리한다. jsMatch 도구를 통한 성능 측정 수치를 제공하여 신뢰를 준다.



▶ 성능우위 문법


  - 배열 생성시 : var arr = new Array(); 보다 var arr = []; 를 사용한다

  - 배열 접근시 : arr.push(i) 보다 arr[i] = value 를 사용한다

  - 객체 생성시 : var obj = new Object(); 보다 var obj = {}; 를 사용한다

  - 객체 접근시 : obj["a"] = 1 보다 obj.a = 1; 를 사용한다 

  - 문자열 생성시 : var str = new String("aaa"); 보다 var str = "aaa"; 를 사용한다 

  - 문자열 연산시 : loop문에서 문자열 조작시에 str += "test"; 보다 arr=[]; loop{ arr[i]="test"; } arr.join(""); 을 사용한다 (String과 StringBuffer개념과 유사)

  - 정규표현식 : 탐색 대상을 축소한다. loop 문 안에 정규표현식 넣지 말고 밖에 놓아 한번만 컴파일 처리되게 한다. loop문에 있으면 계속 컴파일됨 



▶ 스코프 체인 탐색 줄이기

  - 스코프 체인 : 탐색 성능을 높이는 것이 본질 (자바스크립트 실행성능 저하는 변수, 객체, 함수의 메모리상 위치 탐색 작업임)

  - 스코프 체인 구성 = 활성화 객체(Activate Object) + 전역 객체(Global Object)

  - 활성화 객체 : 함수 내부 접근시 생성 (지역변수, this, arguments 객체) -> 함수 빠져 나오면 활성화 객체 제거 됨 

  - 실행 문맥(Execution Context) -> 스코프 체인 (1, 2) -> 활성화 객체 (1) -> 전역 객체 (2) 로 프로그램 수행됨 

  - 함수가 전역 속성 참조 순서 : 실행문맥 > 스코프 체인 > 활성화 객체 (함수) > 스코프 체인 > 전역 객체의 속성 참조 

  - 활성화 객체에서 전역 변수 사용시 : 함수 내부에 var LocalVariable = GlobalVariable;  식을 첨부 (전역속성 탐색을 제거함)



▶ 프로토타입 체인 탐색 줄이기

  - new 연산자로 생성된 인스턴스 객체는 생성자의 프로토타입을 참조하게 된다

  - var obj = new Object(); obj는 Object의 프로토타입 속성에 접근 할 수 있다

  - 자신의 객체만 접근하고 할 경우는 hasOwnProperty를 이요한다 (추가)



▶ 반복문 & 조건문


  - for~in 문은 가급적 쓰지 말라

  - for(~) 문안에 Array.length 구하는 함수등을 호출하지 말고, 외부에서 var length = Array.length를 설정한다. 스코프체인의 활성화 객체를 찾아가는 탐색 경로를 거치게 되므로 응답성능이 느려진다. 

  - 조건절을 빠른 탐색을 위한 알고리즘을 적절히 적용한다 : quick-sort, merge-sort, breadth first search, depth first search등 

posted by peter yun 윤영식
2012. 12. 12. 18:01 Languages/JavaScript

웹에플리케이션을 개발할 때 JavaScript 와 CSS 사용이 많다. 특히 요즘음 JavaScript Module화 패턴을 이용하여 JS파일이 기하 급수적으로 늘어나고 있으므로 네트워크 비용을 줄여야하는 문제에 놓인다. 성능을 향상 시킬 수 있는 NHN의 비법을 요약한다. (Chapter 2. 기본적인 웹사이트 최적화 방법)


  - 이미지 파일이 많을 경우 -> CSS Sprite를 이용한다 (N-MET OSS 이용)

    + 성능에 전송 파일의 사이즈보다 개수가 중요하다. 이는 크기보다 네트워크 전송 비용이 더 크기때문이다 

  - HTTP 헤더에 정적 파일 만료날짜를 추가 -> Client PC에 Caching토록 한다 

    + 캐싱여부 판단 기준은 "이름"과 "인터넷 주소" : src="aa_20111231.js" or src="aa.js?20111231" 로 표현 

    + 만료날짜를 서버에 설정 : Apache의 mod_expires 모듈 설정

  - JavaScript 파일 통합 -> 파일의 개수를 최소화하여 네트워크 비용을 줄임

  - 파일 크기 최소화 -> Gzip압축을 사용한다 (파일크기 1~2KB 이상일 때 압축 권장. 이보다 크기가 작으면 압축해제시 CPU 비용이 더 큼)

  - 쿠키 크기 최소화 -> 헤더 정보에 쿠키가 들어가면 데이터 크기가 커진다

    + 사용하지 않는 쿠키 삭제

    + 최상위 도메인 설정 되도록 사용하지 말자

    + 만료날짜 최대한 짧게 한다

    + 쿠키 정보 필요없는 정적 파일(이미지, js, css)는 별도 도메인으로 서비스한다

  - 렌더링 성능 향상 -> DOM Tree - Render Tree - 좌표 배치 - 브라우져 화면 그리기 시작

    + CSS는 <head> </head> 사이에 넣는다 

    + JavaScript는 </body> 위에 넣는다 : js 수행시 렌더링이 멈추어 하얀 페이지 보일 수 있음

    + 최초 페이지에서 AJAX 통신하면 화면 렌더링이 두번 되므로 최초 호출시 AJAX 배제하자 

    + 태그 중첩을 최소화 한다 : <table> 되도록 쓰지 말고, <div>와 CSS로 Layout을 잡는다 (중첩이 많으면 렌더링 느려짐)

posted by peter yun 윤영식
2012. 11. 27. 16:54 Languages

Apache, PHP, MySQL을 가장 편하게 설치할 수 있는 방법을 제공하는 사이트 소개


  - APM 일반사항을 설치 : start, stop UI 제공

  - HongPD : 문서파일 검색 사이트 구축

  - WowIP : wifi 환경의 유동아피를 고정아이피화하여 내 PC를 서버로 만들 수 있게 해줌 


설정 관련 부분을 bitnami 처럼 패키징화하여 install wizard를 통하여 설치토록 해준다. Go~~~~od!


'Languages' 카테고리의 다른 글

[문서화 도구] Groc 사용하기  (0) 2013.03.09
APM 설치하기  (0) 2012.11.27
posted by peter yun 윤영식
2012. 11. 26. 18:07 Languages/JavaScript

서버단에서 페이지별로 사용하는 템플릿 엔진들(FreeMaker, Velocity) 같은것이 있다면 클라이언트 화면단에서 AJAX를 통하여 받는 데이터를 통해 화면을 변경시켜주는 템플릿 엔진도 있다. JQuery에 jquery template 엔진(소개)이 있지만, 다른 것도 검토해 볼 필요가 있겠다. 


  - 추천 javascript template engine 

    + Pure : loop 단점 존재 

    + TrimPath : google code project (강력 추천)

  - 더 극적으로 socketstream을 이용하여 HTML rendering 방법 : Node.js에서 구동되는 bi-direction 통신가능 (GitHub 설명


Single Page Application(wikipedia)을 만들기 위해서는 javascript template engine이 필수 일듯 하다. 


posted by peter yun 윤영식
2012. 11. 21. 15:12 Languages/Java

Java란 무엇인가? 그 본질은 무엇인가라는 궁금증에 대하여 심도있고, 상세한 설명과 함께 쓰여진 블로깅이 있어서 링크한다. 엑셈의 WAS성능 관리 솔루션을 만드는 분이 아닐까 추측을 해본다. 


[JVM Internal]Java Performance Fundamental 교재를 공유합니다.

  - JVM = Runtime Data Area + Execution Engine + ClassLoader + Garbage Collection + Native Code (JVM 위키피디아)

  - Runtime Data Area = Java Stack(Frame Data = Operand Stack + Local Variable) + Method Area + Method Area

    + istore : Operand Stack -> Local Variable

    + iload : Local Variable -> Operand Stack

  - ClassLoader = Bootstrap (rt.jar) + Extension (jdk/ext directory) + System ClassLoader (application)

  - ClassLoader Work = Loading -> Linking -> Initializing

  - Execution Engine : byte code를 interpreting 하여 수행

    + JIT (Just In Time) Compiler : 많이 수행되는 것 일부를 Native Code로 Compile 하여 수행

    + HotSpot Compiler = Client or Server Compiler

      + Profile을 이용하여  Native Code Compiler 코드를 결정

      + Native -> Interpet로 돌아갈 수도 있음



> JVM 과 JavaScript Engine의 차이


posted by peter yun 윤영식
2012. 11. 12. 16:26 Languages/JavaScript

JavaScript를 하면서 어려웠던 새로운 개념이 Closure이다. 이참에 조금 정리해 보도록 하자 


▶ Closure 개념

  - 로컬 변수를 참조하고 있는 함수 내의 함수 (JavaScript 마스터북, Jpub출판, p180)

  - 즉, 클로저는 자신의 범위(Scope) 밖에 있는 변수들에 접근할 수 있는 함수를 의미한다 

  - inner function을 return 할때 closure가 된다 (원문)

function outerFn() {

var count=1;

return function (cnt) {

      count += cnt;

console.log(count);

}

}


var func = outerFn();

func(10); // 결과 값 11

func(10); // 결과 값 21

  1) func가 closure가 됨 : 내부 변수들 closure, private 변수 생성됨

  2) func(parameter) 호출해 줘도 내부 변수들은 다시 생성되는 것이 아니라 상태를 유지시켜서 참조 됨 

  3) 즉, 클로저가 만들어 지면서 내부 변수들은 별도로 유지되면서 상태값을 유지함

  4) 클로저의 참조를 제거하고 GC할려면 명시적으로 func=null; 함



다른 예제를 보자 
예) closure가 아님 
function foo(x) {
  var tmp = 3;
  function bar(y) {
    console.log(x + y + (++tmp));
  }
  bar(10);
}
foo(2); // 결과 값 16
foo(2); // 결과 값 16
foo(2); // 결과 값 16

예) closure 임
function foo(x) {
  var tmp = 3;
  return function (y) {
    console.log(x + y + (++tmp));
  }
}
var bar = foo(2); // bar is now a closure.
bar(10); // 결과 값 16
bar(10); // 결과 값 17
bar(10); // 결과 값 18

var bar2 = foo(2);
bar2(10); // 결과 값 16
bar2(10); // 결과 값 17

  - 로컬 변수를 계속 생성하지 않고 상태를 유지하면 사용할 수 있다 (마치 객체처럼 var bar2 = foo(2); 하면 또 다른 closure가 생성되면서 bar와 별도의 상태공유 변수 x와 tmp가 생성된다. 마치 클래스에서 객체생성하는 것 처럼 된다. closure 생성시에 arguement와 var로 선언된 variable 에 대한 참조가 가능해 진다. 결국 참조자들-x, tmp-가 일정 메모리에 저장되어 상태를 유지한다)


  - 위의 예에서 var bar = foo(2);를 하는 순간 foo function 객체의 x, tmp 변수의 레퍼런스를 closure 가 가진다 (즉, x, tmp 에 대한 변수 상태값이 유지되고, y 값은 bar(10)을 호출할 때 넘겨주는 값이 된다)


  - 클로저는 간단한 객체이다 (엄밀히 따져서 객체는 아니지만 객체식으로 치환해서 살펴보면 다음과 같다)

    + 클로저 : 객체 = 클로저를 감싸고 있는 부모 함수 foo : 생성자

    + 클로저 : 객체 = 클로저로 부터 참조되는 로컬 변수 tmp :  프로퍼티

    + 클로저 : 객체 = 클로저 자신 bar, bar2 : 메소드

    + 클로저 : 객체 = var bar = foo(2) 함수 호출 : 인스턴스화

    + 클로저 : 객체 = 클로저를 대입하는 변수 bar(10), bar2(10) : 인스턴스 <-- 요거 애매함


  - function 내부에 for문을 돌면서 function을 호출하여 callback 을 셋팅하는 오류 제거 (원문1, 원문2)


실제 사용해 보면서 좀 더 이해를 해나가야 겠다. JavaScript Master북의 글이 좀 더 쉽게 이해가 가니, 햇갈릴 때 책을 다시 정독해 보자. 


<참조>

  - 소스니 코브 : Closure 이해하기

  - Closure 정리 : 한글이라 이해하기 쉬울것임

  - Inside.JS : 한글 정리 예제 포함

posted by peter yun 윤영식
2012. 11. 12. 11:34 Languages/JavaScript

자바스크립트의 Function에는 Expression (FE) 과 Declaration (FD) 가 있다고 한다. 이에 대한 차이를 연구해 보자. 우선 존경해 맞이하는 소스니코브의 정리 내역과 구글링한 사이트를 읽고 정리한다 



▶ Function Declaration


  - 변수 할당 없는 이름있는 함수를 정의

  - "var"로 시작하지 않고 "function"으로 시작해야 한다(must)

- 명확한 이름을 가져야 한다
- 소스코드중에 오고 function body를 가지면 다른 function 안에도 위치한다
- entering the context stage에서 생성된다 (즉, function 안에 FD 존재않음)
- variable object(VO)에 영향을 준다 
function bar() {
return 3;

}


or


// 1) directly int the global context

function globalFD() {

// inside the body of another function

function innerFD() {}

}




▶ Function Expression


  - 변수 할당이 있는 표현식으로서 함수를 정의

  - 이름있는 또는 익명(anonymous) 함수 가능

  - FE는 "function"으로 시작하지 않아야 한다(must)

- 소스중에 expression position에 정의된다 
- 함수명은 optional 이다 
- variable object(VO)에 저장되지 않는다 
- code execution stage에서 생성된다 
// anonymous function expression
var a = function() {
return 3;
}

// named function expression
var a = function bar() {
return 3;
}

//self invoking function expression or immediately invoked function expression (IIFE, 즉시실행함수)
(function sayHello() {
alert("dowon hi");
})();

// in parentheses (grouping operator) can be only an expression
(function foo() {});

// in the array initialiser - also only expressions
[function bar() {}];

// comma also operators with expressions
1, function baz() {};


// FE is not available neither before the defintion

// because it is created at code execution phase.

alert(foo); // foo is not defined

(function foo() {});

// nor after, because it is not in the VO

alert(foo); // foo is not defined


// parentheses로 grouping 하기 

(function {}) ();

(function {}());


* Name Fuction Expression (NFE)

  - 재귀 호출을 위해 이름으로 자기자신을 호출할 수 있다 (이때 함수를 Variable Object에 저장할 필요가 있을까? 없다!)

  - 부모 context에서 생성할까? 노우!

  - FE로 하면 VO에 영향을 미치지 않는다 

(function foo(bar) {
if(bar) {
return;
}
foo(true); //foo name is available
})();

// but from the outside, correctly, is not  
// 즉, foo는 부모 scope에 없고 function의 [[Scope]]안에 specialObject에 저장한다 (하기 설명 참조)
foo(); // foo is not defined


위 소스 해석 (원문)

  - Interpreter가 code execution stage에서 FE를 만나면 FE를 생성하기 전에 special object를 만들고 현재 scope chain 앞에 놓는다 

  - FE 자신을 생성하고, 자신의 scope 프로퍼티에 scope chain 을 한다 (referencing)

  - special object에 unique 프로퍼티로 FE를 추가한다

  - 마지막에 parent scope chain으로 부터 special object를 제거 한다 

specialObject = {};

Scope = specialObject + Scope;

foo = new FunctionExpression;
foo.__scope__ = Scope;  // or foo.[[Scope]] = Scope;
specialObject.foo = foo; // [DontDelete], {ReadOnly}

delete Scope[0]; // remove specialObject from the front of scope chain



* FE의 특징

  - Variable Object (VO)에 속하지 않다 (스크립트 수행시 Execution Context-EC- 에 한 부분 = VO)

  - 따라서 FE는 Hoist안되고 FD만 Hoist 된다 (원문)

  - 그리고 FE는 자신의 내부 Scope에만 의미가 있지 외부(Outside)에는 의미가 전혀 없다 

  - VO = Function Declaration + Variable Declaration(var) + Arguments 들이 속한다 (FD가 최우선 순위 -> VD 순서로 Hoist됨)

  - FE로 하면 VO를 오염시키지 않기에 사용이 늘어나고 있다

예1)

bar(); // hoist 되어 정상 처리됨 

foo(); // error 발생 


function bar() { .... } // FD 

var foo = function() { .... }; // FE


예2)

var myFunction = function sameFunction() {

return myFunction === sameFunction; // true

};

console.log(myFunction()); // true 

console.log(sameFunction());  // [ReferenceError: contents is not defined] 에러 발생 



* FE에 사용하는 Grouping Operator 와 Immediately Invoked Fuction Expression (IIFE) 특징 

  - Grouping Operator인 () 은 variable과 function을 global scope와 격리된 private scope로 만드는 방법을 제공한다

  - IIFE는 jQuery, Underscore, Prototype, Dojo 등에서 global  scope을 깔끔하게 유지키 위해 private scope로 캡슐화, 모듈화에 중요하게 사용된다

  - 하기 예제는 외부세계로 부터 숨겨진 코드를 정의할 수 있고, private scope에서 동작하는 library variable을 만드는 것이다.

var Box = (function () {
    var contents = [];
    return {
        insert: function (thing) {
            contents.push(thing);
            return this;
        },
        count: function () {
            return contents.length;
        }
    };
})();

console.log(Box.insert('abc').insert(123).insert({
    width: 640, height: 360
}).insert(function () {
    return 'Hello!';
}).count()); // 4 를 출력

// This throws a ReferenceError since the JavaScript engine can't
// resolve the `contents` identifier.
// [ReferenceError: contents is not defined] 를 출력 
try {
    console.log(contents);  
} catch(err) { 
    console.log(err); 


  - IIFE는 function 호출처럼 arguements를 받고, 실행시간에 in-scope에 있는 모든 데이터에 대한 access가 가능한 Closure를 반환할 수 있다 (variable 상태 저장 가능)

var d, Saved, testSubject, i, l, x;

// Capture a start time.
d = new Date().getTime();

// `Saved` exposes a single API method `get` which returns that
// start time: the variable `d` is supplied as the argument
// identified within the function definition as `start`.
// 최기의  시작시간값을 저장하고 있다 
Saved = (function (start) {
    return {
        get: function () {
            return start;
        }
    };
})(d);

testSubject = {
    level1: {
        level2: {
            level3: {
                level4: {
                    val: 'value'
                }
            }
        }
    }
};

for (i = 0, l = 1000000; i < l; i++) {
    x = testSubject.level1.level2.level3.level4.val;
}

// Capture the time after diving five levels into the `testSubject`
// object literal one million times.
// 현재 시간을 구한다 
d = new Date().getTime();

// Output the current value of `d`.
// 현재 시간이 찍힘 
console.log(d); 

// Output the original value of `d`.
// 초기 IIFE의 시간이 찍힘
console.log(Saved.get());

// Output the difference which indicates how many seconds it took
// to do that object crawl.
console.log(d - Saved.get());

//------ 결과 
1352699019341 // d 현재 시간 
1352699019322 // Saved.get() IIFE 시간 
19  // 차이 값 



<참조>

  - javascript 블로그 : 간단하고 명확하게 정의내림 (표현형식만 설명)

  - 소스니 코브 : 너무 심도 있게 설명해서 집중하지 않으면 놓치기 쉬움 (왜 구별해서 사용하는지 설명)

  - 예제로 보는 javascript : Function Expression을 사용하는 이유를 가장 잘 설명함

posted by peter yun 윤영식
prev 1 2 3 next