Async



node.js의 장점으로 꼽는 점 중 하나가 non-Blocking으로써 비동기적으로 작동한다는 점이다.


그렇기 때문에 node.js의 대부분의 기능들은 콜백 패턴을 이용한 비동기 처리를 사용는데, 이러한 점 때문에 실제 개발에 콜백 지옥으로 인해 난관을 겪곤 한다.


콜백 지옥이란 콜백 패턴을 이용하는 함수에, 연달아 추가 기능을 사용할 경우 콜백이 계속해서 중첩되는 상태를 말한다.


task1(a, function(err, result1){     task2(b, function(err, result2){         task3(c, function(err, result3){             task4(d, function(err, result4){                 //함수 실행             });         });     }); });


위 예제는 err에 대한 처리와 각 파라미터에 대한 알고리즘을 베재한 코드이다. 

4중첩이지만 실제 코드를 node.js로 코딩할땐 흔히 4중첩이상은 흔히 볼 수 있다.


이러한 콜백 지옥을 해결하기 위해서 다양한 모듈이 있다. 

자바스크립트의 Promise 패턴을 이용한 방법(대부분의 모듈은 Promise를 지원한다.), 혹은 Async나 Step이라는 모듈로 흐름을 제어하는 방법이다.


여기서는 Async모듈을 사용하는 방법을 정리하고자 한다.


async : https://github.com/caolan/async

docs : http://caolan.github.io/async/

설치 : npm install async --save



async 모듈의 메소드는 크게 콜렉션, 흐름제어, 유틸 3종류로 나뉘어진다. 주로 사용하는건 콜렉션과 흐름제어이고, 이 포스팅 자체는 흐름제어가 주제이므로 이를 주로 다루겠다.



흐름 제어 메서드


async의 흐름 제어 메서드는 정말 다양한 종류가 있지만, 내가 주로 사용한 메서드는 다음과 같다.


- 순차 실행 : series, waterfall

- 병렬 실행 : parallels



순차 실행

순차 실행은 이름 그대로 메서드들을 순차적으로 실행하는 메서드이다. 여기엔 인자를 전달하지 않고 순차적으로만 실행하는 메서드인 series와, 

다음 메서드에 인자를 전달할 수 있는 waterfall 메서드가 있다.


1. series


시리즈 메서드는 다음과 같은 형태를 가진다.

async.series([task1,task2,task3], function(err, results){ // series 완료 콜백 });

첫번째 파라미터는 실행할 함수들을 순서대로 배열에 넣어 삽입한다, 두번째 메서드는 이 serise가 완료되었을때 실행되는 콜백 함수를 넣는데,


이 콜백에는 실행 메서드들 중 실패하는 경우 err에 인자를 전달하며 그 뒤 테스크들의 실행을 중단하고 콜백 함수를 호출한다.


모두 성공할 경우 콜백 함수의 results에 배열에 있는 각 테스크들의 실행 결과를 배열로 전달받는다.


배열에 들어가는 메서드들은 callback을 인자로 가지는 함수 형태로 만들어야 한다.




function task1(callback){     //실패시     if(err){         callback(err);     }     //성공시     callback(null, '성공1'); }


성공 시에는 callback인자를 함수로 호출하는데, 첫 인자를 null로 전달하면 되고


실패 시에는 첫 null에 err를 전달하면 된다.


async.series([
    function (callback) {
        if (err) {
            callback('실패1');
        }
        callback(null, '성공1');
    }, 
    function (callback) {
        if (err) {
            callback('실패2');
        }
        callback(null, '성공2');
    },
    function (callback) {
        if (err) {
            callback('실패3');
        }
        callback(null, '성공3');
    }],
    function(err, results) {
        // serise 완료 콜백
        if(err){
            //err시 err난 테스크에서 전달한 err값을 전달받는다
            console.log(err);
        }
        //모두 성공시, 성공 값들을 전달받는다
        //예) ['성공1','성공2','성공3']
        console.log(reuslts);
});



2. waterfall


serise와 waterfall은 둘다 순차 실행이지만

serise는 테스크들이 독립적으로 실행되어 모든 결과를 모아 배열로 콜백에 전달하는 반면에, 

waterfall은 각 테스크들의 값을 다음 인자로 전달한다는 점에서 다르다.


async.waterfall([task1,task2,task3], function(err, result){ // waterfall 완료 콜백 });

메서드의 형태는 searise와 얼핏 비슷하나, task에서 다음 콜백을 호출 할 때 인자를 전달 할 수 있다.



function task1(callback){ //실패 시 if(err){ callback(err); } //성공 시 callback(null, '성공', '1'); } function task2(arg1, arg2, callback){ //실패 시 if(err){ callback(err); } //성공 시 callback(null,'성공2'); }

async.waterfall([ function (callback) { if (err) { callback('실패1'); } callback(null, '성공','1'); }, function (arg1, arg2, callback) { if (err) { callback('실패2'); } //arg1 : '성공', arg2 : 1 console.log(arg1, arg2); callback(null, '성공2'); }, function (arg1, callback) { if (err) { callback('실패3'); } //arg1 : '성공2' console.log(arg1); callback(null, '성공3'); }], function(err, result) { // waterfall 완료 콜백 if(err){ //err시 err난 테스크에서 전달한 err값을 전달받는다 console.log(err); } //모두 성공시, 마지막에 결과 값을 전달 받는다. //result : '성공3' console.log(reuslt); });




병렬 실행


parallel


parallel도 앞서 본 메서드들과 같이 task의 배열과 콜백을 인자로 받는다. 다만 순차 실행이 아닌 전달 받은 task들을 병렬, 즉 동시에 실행한다.


그리고 모든 테스크들이 전부 다 끝난 다음에서야 콜백 함수가 실행된다.

async.parallel([task1,task2,task3], function(err, results){
// parallel 완료 콜백
});


동시 실행이기 때문에 각 task들은 serise와 같이 독립적으로 실행되며, results에는 모든 함수의 결과가 저장된다.


메서드의 형태는 serise와 비슷하다.

async.parallel([
    function (callback) {
        if (err) {
            callback('실패1');
        }
        callback(null, '성공1');
    }, 
    function (callback) {
        if (err) {
            callback('실패2');
        }
        callback(null, '성공2');
    },
    function (callback) {
        if (err) {
            callback('실패3');
        }
        callback(null, '성공3');
    }],
    function(err, results) {
        // parallel 완료 콜백
        if(err){
            //err시 err난 테스크에서 전달한 err값을 전달받는다
            console.log(err);
        }
        //모두 성공시, 성공 값들을 전달받는다
        //예) ['성공1','성공2','성공3']
        console.log(reuslts);
});







node.js를 이용한 프로젝트를 진행하면서 비동기 처리에 따른 콜백 지옥을 벗어나고자 많은 고민이 있었다. 


async 모듈, 그리고 promise 만으로도 대부분의 콜백 지옥을 해소 할 수 있다고 하므로 반복해서 숙지하도록 노력해야겠다.

'Javascript > node.js' 카테고리의 다른 글

node.js 모듈  (0) 2016.03.30
node.js 시작하기  (0) 2016.03.01

모듈은 다른 언어에서 사용하는 라이브러리, API와 같다.

node.js에서는 global 모듈 외에 모든 필요한 기능을 사용하고자 할 때는 모듈(라이브러리)를 로딩하여 사용해야 한다.


모듈은 기본적으로 require함수를 이용하여 로딩한다.

(require은 global 모듈에 있는 함수이기 때문에, 어디서든지 사용 가능한 함수이다.)

만약 http 모듈을 로딩한다면 다음과 같이 입력하면 된다.

var http = require('http');

http 변수 내에 http 모듈이 로딩된다.


node.js에서 설치 시 자동적으로 기본 모듈이 설치된다.

기본적으로 제공되는 모듈은 node.js의 공식 홈페이지에서 제공하는 문서에서 확인 할 수 있다.


node.js api 문서 : https://nodejs.org/dist/latest-v5.x/docs/api/


기본 모듈을 제외한 모듈들은 (ex, nodeman, formidable, multer 등등) npm이라는 패키지 관리자 도구를 이용해 설치해야 한다.


기본적으로 제공되는 모듈은 다음과 같다.


process : 프로세스에 대한 정보를 담고 있는 전역 객체

utility : 타입 검사, 포메팅 등의 유틸리티 함수 제공

events : 이벤트 관련 함수 제공

buffers : 바이너리 데이터의 옥텟 스트림(octet stream)을 다루는 모듈  streams :스트림을 다루기 위한 추상 인터페이스

crypto : 암호화에 대한 함수 제공

TLS/SSL : 공개키, 개인키 기반인 TLS/SSL 에 대한 함수 제공

File System : 파일을 다루는 함수 제공

Path : 파일 경로를 다루는 함수 제공

Net : 비동기 네트워크 통신 기능 제공

UDP : UDP의 데이터그램 소켓 (Datagram Sockets) 통신 기능 제공

DNS : 도메인 네임 서버를 다루는 함수 제공

TTP : HTTP 서버 및 클라이언트 기능 제공

HTTPS : HTTPS 서버 및 클라이언트 기능 제공

URL : URL을 다루는 함수 제공

Query Strings : URL의 쿼리 문자열을 다루는 함수 제공

Readline : 스트림에서 라인 단위로 읽는 기능을 제공

Vm : 자바스크립트 실행 기능 제공

Child Processes : 자식 프로세스 생성과 관련된 함수 제공

Assert : 유닛 테스트를 위한 단언문을 제공

TTY : 터미널이나 콘솔 관련 기능을 제공

Zlib : zlib 압축, 해제 함수 제공

OS : 운영체제에 대한 정보를 구하는 함수 제공

Cluster : 여러 노드 프로세스를 실행하는 클러스터 기능을 제공 

(출처 : T아카데미 node.js 자료)




'Javascript > node.js' 카테고리의 다른 글

비동기 흐름 제어를 위한 모듈 - async  (0) 2016.09.18
node.js 시작하기  (0) 2016.03.01

요새 자바스크립트 하나만 잘 알아도, 웹사이트 전체를 만들 수 있는 풀스택 개발이 가능하다고 한다. 이러한 풀 스택 개발이 가능하게 된 기반은 node.js라는 자바스크립트 프레임워크의 존재 떄문이다. 


자바스크립트는 초기에 그저 브라우저 내 에서의 동적인 처리를 위한 스크립트 언어였고, 현재도 대부분이 jquery나 angular.js와 같은 프론드엔드 프레임워크를 많이 사용한다. 하지만 수많은 자바스크립트 프레임워크중에 특출나게 서버 사이드를 처리하는 프레임워크가 있으니, 그것이 바로 node.js다. 기존의 자바스크립트 프론트엔드 프레임워크와, node.js가 합쳐져, 그야말로 자바스크립트만 잘 알아도 사이트 하나는 뚝딱 만드는 것이다. 

그 뿐만 아니라 node.js는 기존의 서버와는 다르게 event-driven 기반, 싱글 쓰레드에 non-Blocking I/O 방식으로 작동한다고 한다.(데이터 입출력때마다 blocking되지 않는다.)

그리고 jsp나 php와 같이 웹서버나 WAS가 필요 없고, node.js 그 자체가 웹서버로서 동작한다.


node.js에 대한 관심은 항상 가지고 있었다. node.js는 매 업데이트마다 죄다 뒤집어져서 책이 의미가 없다고 하니, 구글링과 레퍼런스를 통해 독학으로 시작하려 한다.



node.js는 공식 사이트에서 받을 수 있는데, 검색해서 찾아가보니 메인화면만 유일하게 한글화가 되어있다..(..)


공식 사이트의 주소는 다음과 같다 - https://nodejs.org/en/




사이트에 들어가면 위와 같이 LTS 버젼과, Stable버젼이 있다. Stable 버젼이란 안정화된 최신 버전을 뜻하고

LTS란 보통 Long Term Support, 장기간 지원을 하는 버전을 뜻한다. 4.3.1 LTS버젼을 다운 받아보자.




다운 받으면 설치 파일을 실행, node.js에 흥미를 가지실 정도의 분이라면 설치에 대한 두려움을 가진 사람은 없으리라 생각한다.






설치 완료!


C:\nodejs폴더에 example.js 파일을 생성하고, 다음 예제코드를 입력해보자.

const http = require('http');

http.createServer( (request, response) => {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');


명령 프롬포트를 실행하고, 다음과 같이 입력해보자.




브라우저를 이용해 http://localhost:8124/ 접속해보면 서버가 정상적으로 작동하여 HelloWord가 출력 되었음을 확인 할 수 있다. 




서버를 종료하고 싶을 경우 명령 프롬포트를 종료하거나, 명령 프롬포트에서 Ctrl+C를 누르면 된다.

'Javascript > node.js' 카테고리의 다른 글

비동기 흐름 제어를 위한 모듈 - async  (0) 2016.09.18
node.js 모듈  (0) 2016.03.30

+ Recent posts