2015년 2월 26일 목요일

[난해한 Javascript 개념] async caller와 callee간 callback을 통한 결과 전달 방식

async 함수를 호출하고 응답을 받기 위해 asynchronous function인 callback을 argument로 넘기고 그 function에서는 결과를 처리하는 로직이 담긴다.
이해하기 어려운 아래 코드를 이해함으로써 async function간의 메시지 전달을 하는 방식에 대한 개념을 잡아보자.


FileObject.file_exists function을 실행하고, 그 결과를 출력하는 function이다.

일반적인 synchronous flow라면 다음과 같이 수행할 것이다.


하지만, asynchronous flow에서 file_exist는 즉시 return하고, 결과는 나중에 알려줘야 하고, foo()함수는 그 결과를 나중에 처리할 수 있어야 한다.
그렇게 하기 위해 async caller와 callee는 callback을 통해 그 결과를 전달한다.

아래가 맨 위 코드와 구조가 같다.

webstorm에서 gruntfile.js의 task load가 실패하는 문제 해결하기

앞선 글에서 다룬 바와 같이 node.js를 'sudo' permission이 아닌 일반 사용자 계정으로 설치하여 사용하고 있다.
(참고: http://dakoostech.blogspot.kr/2015/02/nodejs-yeoman-bower-grunt-permission.html)
그런데, webstorm에서 gruntfile.js의 task load가 계속 실패하는 문제가 발생했다. 외부 console에서는 'grunt serve''grunt test'가 잘 실행되는데 webstorm의 GUI로는 task load가 실패했다. 알고 보니 원인은 매우 단순한 것이다.
webstorm.sh를 바로가기로 만들어 Desktop 폴더에 놓고 마우스로 클릭하여 webstorm을 실행시켰는데 그것이 문제였다. '.bashrc'내의 nvm use v0.10.35이 activation되지 못하여 node.js가 설치 안된 것으로 인식하고, 그로 인해 당연히 grunt도 실행이 안된 것이였다.

그래서 '.bashrc'내에 아래와 같이 alias를 추가하였다.
alias webstorm='/home/user_account/[webstorm 설치 folder]/bin/WebStorm.sh'

그런 뒤에 . .bashrc를 실행하고 console에서 webstorm을 실행시켜서 사용하면 된다.
/home/user_account# . .bashrc
/home/user_account# webstorm



참고로, node.js를 일반 사용자 계정으로 설치하니, webstorm에서 node.js interpreter와 package 정보를 찾지 못하는 현상이 있었다.
이를 해결하는 방법은 WebStorm의 File>Setting에서 Languages and NPM을 선택하여 'Node Interpreter'의 위치를 잡아 주는 것이다.
nvm에 의해 설치된 node.js는 /home/user_account/.nvm아래에 설치된다. 'Node Interpreter'로 node 실행파일을 선택해 주면 자동적으로 package가 갱신된다.

yeoman 설치 순서와 bower 관련 문제 발생시 해결하기

yeoman을 Windows와 Linux에 설치할 때 모두 중간에 실패하는 현상이 발생했다. 이는 bower가 git서버에 접근할 때 생긴 문제로 인한 것이였다. 구글링으로는 그 해결책을 쉽게 찾아 내지 못하고 시간을 많이 허비했는데 나중에 비슷한 문제가 발생할 가능성을 대비하여 방법을 남겨둔다.

node.js가 sudo permission이 아닌 일반 사용자 계정으로 설치되어야 한다. 그것은 아래 글을 참고하자.
(http://dakoostech.blogspot.kr/2015/02/nodejs-yeoman-bower-grunt-permission.html)

아래와 같이 Yeoman 설치 를 수행한다.
/home/user_account# npm install yo bower grunt-cli -g
/home/user_account# npm install generator-angular -g
/home/user_account# mkdir myprj
/home/user_account# cd myprj
/home/user_account/myprj# yo angular


'yo angular'를 수행 중 문제가 발생하면, 내 경험으로는 bower가 github에 접근을 못하여 생기는 경우였다.

다음과 같이 확인해 그 원인이 맞는지 확인한다.
/home/user_account/myprj# bower install

결과가 github에 접근이 실패하는 것으로 나오면 아래와 같이 URL을 변경하는 명령을 입력하고 다시 'bower install'을 실행한다.
/home/user_account/myprj# git config --global url:"https://".insteadOf git://
/home/user_account/myprj# bower install

'git://'이 아닌 'https://'로 변경하여 접근해 본 결과가 성공이면 'yo angular'를 다시 실행한다.

모두 성공이면, 아래와 같이 grunt가 정상적으로 실행되는지 확인해 본다.

/home/user_account/myprj# grunt serve


참조
1. http://yeoman.io/learning/
2. http://stackoverflow.com/questions/21789683/howto-fix-bower-ecmderr

node.js를 제대로 설치해서 yeoman, bower, grunt 설치시 발생하는 permission 문제 해결하기(ubuntu)

node.js를 sudo permission으로 설치하면, 나중에 Yeoman, Bower, Grunt등을 설치할 때 permission 문제가 발생하여 곤란을 겪을 수 있다.
여러 가지 방법을 찾아보고 실행해 본 결과, 가장 좋은 방법은 node.js를 설치 시에 'sudo' permission이 아니라 일반 계정의 permission으로 설치를 하는 것이다. 그 방법은 아래의 순서와 같다.

1. 기존에 이미 node.js가 설치되어 있는 경우 제거를 먼저한다.
1.1 기존 npm module들의 제거
/home/user_account# pm ls -gp | awk -F/ '/node_modules/ && !/node_modules.*node_modules/ {print $NF}' | xargs npm -g rm

1.2 기존 node.js 제거
/home/user_account# cd /usr/local
/usr/local# sudo rm -r bin/node bin/npm include/node lib/node_modules share/man/man/node.1
/usr/local# cd ~
/home/user_account# rm -r .npm

2. node.js를 사용자 계정으로 설치하기
2.1 nvm 설치
/home/user_account# curl https://raw.githubusercontent.com/creationix/nvm/v0.23.3/install.sh | bash
또는
/home/user_account# wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.23.3/install.sh | bash

<참고: Windows의 경우>
1. curl windows버전 설치: curl 다운로드 사이트에서 windows-generic 중 SSL과 SSH를 지원하는 것을 선택하여 link된 사이트를 통해 다운 받기, 이후 시스템 변수 PATH에 curl.exe 위치를 추가해야 함
2. nvm windows 버전 설치: https://github.com/coreybutler/nvm-windows를 통해 설치


2.2 nvm을 이용하여 sudo permission없이 node.js 설치 (node.js version이 0.10.35라고 가정 - 2015.2.26 최신 버전)
/home/user_account# nvm install 0.10.35
프로세서의 architecture로 32 bit나 64 bit를 명시하려면 아래와 같이 추가한다. (64bit의 예)
/home/user_account# nvm install 0.10.35 64


2.3. 사용자 계정이 activation될 때 node.js도 activation되도록 설정하기
사용자 계정의 .bashrc 파일에 nvm use v0.10.35를 추가하고 아래와 같이 .bashrc를 실행시킨다.
/home/user_account# . .bashrc


Reference
1. http://stackoverflow.com/questions/16151018/npm-throws-error-without-sudo
2. http://achinth.com/post/58262164061/uninstalling-node-js-from-ubuntu
3. http://askubuntu.com/questions/507684/trying-to-install-yeoman-on-ubuntu-to-use-with-nodejs-and-npm

포스팅 시 text를 콘솔 입력처럼 표시하기

기술 블로그를 작성하다보니, 소스코드 외에 콘솔에 타이핑한 것을 표시할 일이 있다.
이를 위한 간단한 html tag는 다음과 같다.

간단한 console 명령을 표시할 때는 <span style="background-color: lightgray">npm install 0.10.35 </span> 과 같이 입력하면, npm install 0.10.35로 표시된다.

실제 console에 입력하는 듯한 효과는 아래처럼 입력하면 된다.

<div style="background-color: lightgray; margin-left: 20px; margin-right: 20px; padding-bottom: 8px; padding-left: 8px; padding-right: 8px; padding-top: 8px;">

/home/dark# mkdir myprj 
/home/dark# cd myprj 
/home/dark#myprj npm install 0.10.35 

</div>


그러면 아래와 같이 보인다.

/home/dark# mkdir myprj 
/home/dark# cd myprj 
/home/dark/myprj# npm install 0.10.35 

2015년 2월 24일 화요일

[난해한 Javascript 개념] Asynchronous loop

C/C++/Java에 익숙한 나에게 낯선 것들이 Javascript에는 너무나 많다. 지금까지 다루어 본 언어들과는 너무나 다른 functional 프로그래밍 언어인 Javascript의 핵심 요소를 살펴보고 '내 나름대로의 이해'를 시도해 본다.

낯선 것들:
  • first-class function

  • 변수의 scope

  • this 키워드의 의미

  • closure의 개념

  • Asynchronous loop





  • Asynchronous loop
    이건 문제와 해결책을 보면 이해가 용이하다. 단지 해결 방식이 복잡하다는 것이 문제다.

    files array의 element(file이름)를 하나씩 빼서 "albums/" 폴더 아래에 존재하는 지 확인 후 directory라면 only_dirs array에 추가하고자 한다.
    우리는 file 하나씩 하나씩 하고자 한다.

    하지만, 위의 코드로는 그것이 불가능하다. for loop은 위의 동작을 하나씩 순차적으로 하는 것이 아니라 nonblocking 함수인 fs.stat를 순식간에 호출하여 callback을 등록하고는 종료되어 버린다.

    우리가 원하는 대로 asynchronous 동작이 순차적으로 실행되기 위해서는 아래와 같은 pattern으로 loop을 작성하면 된다.



    맨 위의 코드를 위의 pattern을 사용하여 작성하면 아래와 같다.


    정리
    1. Asynchronous iteration을 위해서는 위의 pattern을 사용하자.



    [난해한 Javascript 개념] closure의 개념

    C/C++/Java에 익숙한 나에게 낯선 것들이 Javascript에는 너무나 많다. 지금까지 다루어 본 언어들과는 너무나 다른 functional 프로그래밍 언어인 Javascript의 핵심 요소를 살펴보고 '내 나름대로의 이해'를 시도해 본다.

    낯선 것들:
  • first-class function


  • 변수의 scope


  • this 키워드의 의미


  • closure의 개념


  • Asynchronous Loop








  • closure
    개인적으로 Closure는 상당히 이해하기 어려운 개념인데, 나름 이해한 것은 timer 예제를 통해서이다. 개념적인 부분은 아직 모르는 부분이 많다는 것을 명심하고 나의 방식으로 한번 이해를 해보자.

    일반적은 for loop은 아래와 같다.

    위 코드의 출력은 다음과 같다.
    출력: 1, 2, 3, 4, 5, end


    그리고 조금 복잡해 보이는 아래 코드를 보자

    함수를 선언하고 즉시 실행했기에 위 코드의 출력도 동일하다.
    출력: 1, 2, 3, 4, 5, end


    1, 2, 3, 4, 5초 Timer를 실행시킨 아래의 코드를 보자.

    출력: end, 6, 6, 6, 6, 6 (end는 즉시, 6은 1초 간격으로 출력)

    function()이 실행되는 시점에는 이미 loop은 끝난 뒤로 setTimeout의 callback함수가 실행되는 환경은 for loop이 실행되는 환경과 다르게 된다.
    이때 callback함수내에서 선언되지 않은 변수 i는 외부에 선언된 i의 reference를 가지게 되어, callback이 실행되는 시점의 i값을 읽어오게 된다.
    loop이 종료된 시점이므로 i의 값은 6이 되는 것이다.

    callback을 시스템에 등록하는 시점과 실행되는 시점의 차이로 인해 의도하지 않은 결과가 나타나는 것이다.
    이것을 해결하기 위해서는 callback을 등록하는 시점의 변수값을 실행 시점에서 그대로 읽을 수 있도록, callback 등록 시에 변수 값을 저장하면 된다. 그것이 closure이다.


    출력: end, 1, 2, 3, 4, 5

    위의 코드는 기존의 callback(inner)을 다른 함수(outer)가 감싼 것처럼 보이는 형태이다. 이것을 해석해보자.
    function(x){}(함수 선언 형태)가 아니라 (function(x){})(i)(함수 실행 형태 = 함수 object + (argument))이므로 즉시 실행되는 (immedidate anonymous) function이다. 그리고 그 함수의 argument로 i가 passing된다.
    그런데, outer function이 즉시 실행이 되면, inner function(원래의 callback)의 object가 return되어 setTimeout의 callback으로 등록되는 것이다. 실행 시점의 inner function object내의 변수가 참조하는 값을 저장하기 위해, inner function과 쌍으로 존재하는 outer function을 정의하고, 참조할 값을 그 내부 변수(또는 argument)에 할당하는 것이다.


    위의 개념으로 아래 코드를 분석해 보면 더욱 이해가 용이할 것이다.






    정리
    1. Closure의 필요성: callback을 시스템에 등록하는 시점과 실행되는 시점의 차이로 인해 참조할 변수값이 변해 버릴 수 있다.
    2. Closure의 형태: 함수 object를 return하는 immediate anonymous 형태의 outer function을 만들고, 사용할 변수를 outer function에서 argument로 passing하라.






    2015년 2월 19일 목요일

    [난해한 Javascript 개념] 'this' 키워드의 의미

    C/C++/Java에 익숙한 나에게 낯선 것들이 Javascript에는 너무나 많다. 지금까지 다루어 본 언어들과는 너무나 다른 functional 프로그래밍 언어인 Javascript의 핵심 요소를 살펴보고 '내 나름대로의 이해'를 시도해 본다.

    낯선 것들:
  • first-class function

  • 변수의 scope

  • this 키워드의 의미

  • closure의 개념

  • 비동기적 프로그래밍과 callback





  • this 키워드의 의미
    C++/Java와 Javascript의 this의 의미는 엄밀히 말하면 똑같다(C에는 this 키워드가 없다). 'Owner'(또는 'Context'라고 생각해도 된다)를 가리킨다는 의미적인 측면에서는 같다. 하지만, 통상적인 Owner가 누구냐는 면에서는 조금 다르다. C++/Java의 Owner는 변수나 함수를 가지고 있는 instance이다.

    Java의 경우:

    class Foo {
      private int i;
      public Foo(int input){
       this.setValue(input); //instance f의 setValue() method
      }
      public void setValue(int input){
       this.i = input;       //instance f의 i 변수
      }
      public static void main (String[] args) {
       Foo f = new Foo(10); 
      }
    }
    

    Javascript의 this는 C++/Java에 비해 Owner로 누구를 가리키느냐가 조금 더 복잡하다.
    root scope에서의 this는 (Javascript를 구동하는) window를 Owner로 가리킨다.
    console.log(this); //출력: window
    

    아래 코드는 좀 더 이를 설명한 것이다.

    var a = 100;
      console.log(this == window) //출력: true
      console.log(this.a); //출력: 100
      console.log(window.a); //출력: 100
    

    root scope에서의 function의 Owner는 어떨까? 이때도 Owner는 window이다.
    function foo(){
       console.log(this); //출력: window
     }
     foo();  // window.foo();로 대체가능 - foo() 함수의 owner가 foo라는 것이 명백함
    

    Object내에 정의된 function은 어떨까? 이런 function의 Owner는 그 Object이다.
    var goo = {
      foo: function(){
        console.log(this); //출력: goo 
        console.log(this == goo); //출력: true
        console.log(this == window); //출력: false
      }
     }
     goo.foo();
    

    그런데, Javascript에서는 그 Owner를 명시적으로 바꾸어 줄 수 있다. 즉, this가 가리키는 대상을 명시적으로 교체 가능하다. 이와 관련된 함수가 call(), apply(), bind() 함수이다.
    call()과 apply() 함수는 거의 동일한 기능을 하며, 아래와 같이 원래 function호출의 맨 뒤에 call(대상)이나 apply(대상)을 붙임으로써 this가 가리키는 대상을 바꾼다.
    var goo = {
      foo: function(){
        console.log(this); //출력: window 
        console.log(this == goo); //출력: false
        console.log(this == window); //출력: true
      }
     }
     goo.foo.call(window);
     
    call()과 apply의 차이는 추가적인 argument를 passing해야 할 경우 방식이 다르다는 것이다. call은 바꾸려는 대상외의 argument를 나열하는 방식이고, apply는 바꾸려는 대상외의 argument를 array로 넘기는 방식이다. 아래의 예를 보면 이해가 쉽다.
    var goo = {
      foo: function(one, two, three){ //apply() 경우 array를 받는 변수 1개만 필요
        console.log(this); //출력: window 
        console.log(one+two+three); 
      }
     }
     goo.foo.call(window, 1, 2, 3);  // == goo.foo.apply(window, [1,2,3]);
     

    bind()는 Owner를 바꾼 함수를 return하는 것이다. 아래 예를 보자.
    var goo = {
      foo: function(){
        console.log(this); //출력: goo.foo() 호출 시 goo, fixed()호출 시 window
      }
     }
     var fixed = goo.foo.bind(window);  
     goo.foo(); 
     fixed(); 
     

    callback의 경우에는 this가 생각한 경우와 달라서 오류가 많이 발생하게 된다.
    var goo = {
     foo: function(){
       console.log(this);    //Owner는 goo
       setTimeout(function(err){
         console.log(this);  //Owner는?
       }, 2000);
     }
    };
    goo.foo();
    
    출력은 아래와 같다.

    setTimeout의 callback으로 등록된 function의 owner는 goo가 아니라 window이다. 객체 정의와 실행간 불일치로 인해 Owner가 바뀐 것이다. 이런 문제를 해결하기 위해 closure라는 개념이 Javascript에 있으므로 이를 반드시 확실히 이해해야만 한다. 그것은 다음 글에서 좀 더 자세히 다루어 보자.


    정리

    1. Javascript의 this 키워드는 Owner를 가리키는데 Object 내에 있으면 Object, 그렇지 않으면 window(root)를 가리킨다.
    2. call(), apply(), bind()를 통해 this가 가리키는 Owner를 바꿀 수 있다.
    3. callback의 경우에는 this를 착각하기 쉽다. 주의해야 한다.




    2015년 2월 17일 화요일

    [난해한 Javascript 개념] 변수의 scope

    C/C++/Java에 익숙한 나에게 낯선 것들이 Javascript에는 너무나 많다. 지금까지 다루어 본 언어들과는 너무나 다른 functional 프로그래밍 언어인 Javascript의 핵심 요소를 살펴보고 '내 나름대로의 이해'를 시도해 본다.

    낯선 것들:
  • first-class function

  • 변수의 scope

  • this 키워드의 의미

  • closure의 개념

  • 비동기적 프로그래밍과 callback






  • 변수의 scope
    C/C++/Java의 변수 scope은 (내가 이해하기엔) 매우 단순하다. {}의 바깥에서 선언하면 {}의 내부까지 영향을 끼치고, 반대로 {}내에 선언하면 바깥에는 영향을 주지 못한다는 것이다. 그리고 {}의 바깥에 변수를 선언하고 {}의 내부에 같은 이름으로 변수를 재선언하면 변수의 scope은 내부/외부로 나뉜다는 것이다. 말이 어렵지 아주 당연한 것이다.
    void foo(){
     int i = 0;
     {
      printf("%d", i); //0 출력
     } 
    }
    void goo(){
      {
       int i = 0;
      }
      printf("%d", i); //error: 'i' undeclared - 변수의 scope이 선언된 {}로 한정
    }
    void hoo(){
      int i = 0;
      {
        int i= 100;
        printf("%d", i); //100 출력 
      }
      i = i+1;
      printf("%d", i); //1 출력  - 동일 변수명 사용시 scope이 분리
    }
    


    Javascript는 C/C++/Java의 규칙과는 조금 다르다. Javascript에서는 function으로 인한 {}가 아닌 경우에는 scope을 구분하지 않는다. 이것은 build를 모두 마치고 실행되는 방식이 아니라 line 순으로 즉시 실행되는 script 언어의 특징으로 인한 것으로 이해가 된다.
    { 
     var i = 100;
     console.log(i); //100 출력
    }
    i = i+1;
    console.log(i);  //101 출력 - {} 내부에 선언된 변수가 {}의 바깥까지 영향을 끼침
    


    함수 외부에 변수를 선언한 경우 '당연하게도' 함수 내까지 영향을 끼친다.
    var foo = function(){ 
     i = 100;
     console.log(i);  
    }
    var i = 0;
    foo();           //100 출력 - function 외부에 선언된 변수가 function 내부에 영향을 끼침
    i = i+1;
    console.log(i);  //101 출력 - function 내부에서 변경된 값이 function 외부에 영향을 끼침
    

    그리고, 함수의 경우엔, 다른 {}와 달리 함수 내에 선언한 변수는 함수내로 scope이 제한된다.
    var foo = function(){ 
     var i = 100;
     console.log(i); //100 출력
    }
    foo();
    i = i+1;   //ReferenceError: i is not defined - 함수 내에 선언된 변수는 그 함수내로 scope이 제약
    console.log(i);  
    


    {} 내부와 외부에 중복된 이름의 변수를 선언한 경우 두 개를 구분하여 scoping하지 않고 마치 같은 변수처럼 사용한다. (값은 갱신된다.)
    var i = 0;
    console.log(i);  // 0 출력
    if(true){ 
     var i = 100;
     console.log(i); //100 출력
    }
    i = i+1;
    console.log(i);  //101 출력  - 동일 변수명 사용시에도 scope이 분리되지 않음 ( C/C++/Java와 다름)
    


    함수의 경우에는 내부에 동일한 이름의 변수를 선언한 경우 C/C++/Java와 동일하게 scope이 구분된다.(이것도 너무나 당연해 보인다)
    var foo = function(){ 
     var i = 100;
     console.log(i); 
    }
    var i = 0;
    foo();           //100 출력
    i = i+1;
    console.log(i);  //1 출력 - 함수의 경우 동일 변수명 사용시 scope이 분리
    


    특이한 점은 var 키워드 없는 변수가 존재할 수 있다는 것이다. 이 경우 변수의 scope은 전역이다. Javascript가 var가 없으면 그 변수는 그것의 parent 또는 grand parent scope에서 그 변수가 선언되어 있다고 '가정'하는 것이다. 이로 인해 그 변수는 전역이 되어 다른 코드에서의 똑같은 이름의 변수와 의도치 않게 혼용되어 있을 수 있다.
    var foo = function(){
     i = 100; //var 없이 정의
    }
    foo(); 
    console.log(i); //100 출력 - var 키워드 없는 변수는 함수 내부에 선언되어도 외부에서 접근 가능 (만약 x()를 실행하지 않은 경우 sss is not defined  Error발생)
    
    Javascript에서는 이를 피하기 위해 선언되지 않은 변수 사용을 막는 모드를 지원하고 있다. "use strict"라는 구문을 사용하여 그 모드로 진입가능하다.
    이 모드는 Javascript 1.8.5 버전부터 추가된 것이라서 지원이 안되는 경우가 있을 수 있다.
    "use strict"
    i = 100; //undefined error 발생
    



    이해한 것을 정리하자면, Javascript의 변수는 함수 안에 선언한 것이 아닌 이상 모두 전역 변수처럼 동작한다. 심지어는 {}안에 선언된 경우도 마찬가지다.
    함수 내에 선언된 변수는 함수 내에만 영향을 끼친다는 점에서 C/C++/Java와 동일하다. 하지만, var없이 선언된 변수는 함수 안에 존재하더라도 함수가 실행이 될 경우 전역으로 동작한다.

    실제 프로그래밍을 할 때는 대부분 함수 내에서 변수를 선언하여 사용할 것이다. 위의 이해를 바탕으로 생각하자면, Javascript에서는 함수 내부에 같은 변수 이름으로 여러 개의 변수을 선언하는 것을 피하는 것이 좋다. 예를 들어 함수 내에서 지역 변수와 for loop 인덱스 변수를 같은 이름으로 선언하여 사용하지 말라. 이로 인해 문제가 발생한다면, 문제가 어디서 발생했는지 찾기가 매우 어려우므로 조심해야 한다.
    위험한 예:
    var foo = function(){
     var i = 100;
     goo(i);
     for(var i = 0; i< array.length; i++) {
      ...
     }
     hoo(i); //어떤 i를 의도한 것인가?
    }
    

    정리

    1. Javascript에서 변수의 scope이 C/C++/Java와 다르므로 실수할 가능성이 높다.

    2. 하나의 함수 내에서는 용도마다의 변수를 각기 다른 이름으로 선언해서 사용하자.

    [난해한 Javascript 개념] first-class function

    C/C++/Java에 익숙한 나에게 낯선 것들이 Javascript에는 너무나 많다. 지금까지 다루어 본 언어들과는 너무나 다른 functional 프로그래밍 언어인 Javascript의 핵심 요소를 살펴보고 '내 나름대로의 이해'를 시도해 본다.

    낯선 것들:
  • first-class function

  • 변수의 scope

  • this 키워드의 의미

  • closure의 개념

  • 비동기적 프로그래밍과 callback






  • first-class function란?
    javascript의 함수는 first-class function라고 한다. first-class function은 C/C++/Java에서 들어본 적이 없는 용어인데, 함수가 다른 함수의 argument로 사용되거나, 다른 함수의 return으로 사용될 수 있다는 의미이다.
    function add(a, b, callback){ 
     var out = a + b;
     callback(out); //실행
    }
    add(1,2,function(o){ //anonymous function을  argument로 넘기기
     console.log(o);
    });
    

    아래와 같이 함수는 변수에 대입되는 것도 가능하다.
    function add(a, b, callback){ 
     var out = a + b;
     callback(out);//실행
    }
    var logf = function(o){ //변수에 대입
     console.log(o);
    });
    
    add(1,2,logf); //argument로 넘기기 
    

    아래와 같이 validation의 대상이 되는 것도 가능하다.
    function add(a, b, callback){ 
     var out = a + b;
     if(callback) //validate
      callback(out); //실행
    }
    var logf = function(o){
     console.log(o);
    });
    
    add(1,2,logf); //argument로 넘기기 
    add(4,5);
    

    함수를 return하여 실행하는 것도 가능하다.
    var foo = function (errorcode){ 
     var make_error = function(){
       console.log('error code: ' + errorcode);
     };
     return make_error; //함수를 return
    }
    var goo = foo('300'); //return된 함수를 goo에 대입
    goo(); // 'error code: 300' 출력 
    

    위에서 살펴본 바와 같이 Javascript의 함수는 C/C++/Java 언어와는 달리 하나의 객체로써 처리된다고 생각하는 것이 좋다. 생성도 되고, 변수에 대입도 되고, argument나 return으로 넘겨질 수 있다. ()를 붙임으로써 실행이 된다라는 것도 다른 언어와 다른 점이다. 즉, 객체로써 취급되다가 ()를 붙여야만 비로소 C/C++/Java의 함수처럼 'execute'된다는 것이다.

    위와 같이, 객체처럼 정의(생성?)되는 시점과 실행 시점의 차이로 인해 this 키워드의 의미가 C++/Java와 다르며, closure라는 개념이 필요하다.(내 방식대로 이해한 내용이므로 정확하지 않을 수 있다.)

    정리

    1. Javascript의 함수는 객체로써 취급된다. (생성, 변수에 대입, 다른 함수의 argument나 return으로 사용 가능)

    2. ()가 붙지 않은 function은 객체라는 의미이며 ()를 붙이면 실행하는 것이다.

    소스 코드를 이쁘게 포스팅하기

    소프트웨어 관련 블로그를 시작하려니 소스코드를 이쁘게 보여주는 기능(Syntax Highlighting)이 왠지 필요할 것 같다.
    별로 중요하지 않은 이런 것에 집착을 해서 장시간 검색 돌입... 그리고 마침내 Syntaxhighlighter라는 툴을 설치한 후, 글을 올릴때 태그를 소스 코드 앞뒤로 붙여 주면 된다는 것을 확인했다.

    사용법은 매우 단순하다. Syntaxhighlighter를 설치(참조: http://anshnote.blogspot.kr/2011/07/syntax-highlighter-blogger.html) 한 이후에, 포스팅 할 때 아래와 같이 소스코드 앞뒤를 pre 태그로 감싸주면 된다.

    예: Javascript의 경우

    참고로 textarea 태그와 pre 태그의 사용 방법이 똑같은데, textarea 태그를 사용하면 불필요한 라인이 코드사이사이에 추가되는 현상이 발생했다. 그러므로 textarea 태그보다는 pre 태그를 사용하는 것이 좋다.


    우리나라 블로그 중에는 추천을 받아야만 가입할 수 있는 티스토리 만이 Syntaxhighlighter 기능을 잘 지원하기에 눈물을 머금고 blogspot.com에 정착한다. 인간관계가 헬름 협곡과 같은 나에게 추천이라니...ㅋ

    정리

    1. 소스 코드를 이쁘게 해주는 Syntaxhighlighter는 블로그 사이트마다 지원 여부가 다른데, 국내는 티스토리, 국외는 blogspot에서 잘 지원된다.

    2. Syntaxhighlighter 설치 후 글 작성시 소스 코드 앞뒤를 pre 태그로 싸주면 소스 코드가 이쁘게 출력된다.