728x90

nodejs에서는 io나 db입출력에 관한건 비동기식으로 처리한다.

비동기에서 잘 모르는 사람은 그냥 원래 흐름(동기)과 다르게 작동한다고 생각하면 된다.

이벤트 핸들링 방식이라고 생각해도 무방하다. 조금은 다르지만.

이 방식은 명확한 장점과 명확한 단점을 동시에 가지게 된다.

일단 장점은 CPU 유휴시간이 없으므로 고성능을 발휘한다. 또한 쓰레드처럼 컨텍스트 스위칭이 일어나지 않으므로 원코어의 쓰레드보다도 성능이 좋다.

물론 쓰레드와는 스타일이 좀 다르므로 뭐가 좋다고 딱 말할수는 없다...

단점은 비동기이기 때문에 동시에 일어나서 루틴이 꼬일 수 있다는 것이다.

예를들어 아래의 코드를 보자.

 

router.get('/', function (req, res, next) {
    var data;

    db.put('ThisIsKey', 'ThisIsValue', function (err) {
        if (err) {
            console.log(err);
        }
        db.get('ThisIsKey', function (err, value) {
            if (err) {
                console.log(err);
            }
            console.log(value);
            res.send(value);
        });
    });
});

 

위 코드는 nodejs의 express프레임워크 코드의 일부이다.

해당 코드는 총 3가지의 루틴이 있는데 DB에 저장을하는 put과 DB의 데이터를 가져오는 get 그리고 화면에 렌더링해주는 res.send로 3가지가 있다.

왜 코드가 이렇게 콜백을 사용해서 들여쓰기로 되있느냐...

그 이유는 비동기로 동작하기 때문이다.

요청하는 타이밍은 정해지지만 응답받는 타이밍은 랜덤이기 때문에 콜백으로 코딩할 수 밖에 없다.

잘 생각해보면 알겠지만 db의 데이터를 넣어야 db를 가져오는게 가능하고 db에서 데이터를 가져와야 화면에 그 데이터로 출력하는게 가능하다.

문제는 이 3가지는 우선순위를 가진다. 결국 콜백으로 코딩할 수 밖에 없다.

이러한걸 콜백 지옥이라고하는데 지금은 3단계 밖에 안되지만 경우에 따라서는 10계단을 내려갈 수도 있다.

 

그러면 영영 이런식으로 써야하느냐? 그렇지않다.

이러한 콜백지옥(이걸 검색해본 사람들은 모두 알겠지만 지옥이라는 말이 딱 적당하다.)을 해결하는 방법이 있다.

방식은 여러가지가 있는데 그 중에서 가장 대표적인 방식이 async 패키지를 사용하는 것이다.

 

npm install async -save

 

 

위와같이 해서 async를 패키지에 추가하자.

 

 

이제 패키지에 추가된게 확인되었다. 사용하여 보자.

 

var async = require('async');

 

패키지를 사용하기 위해서 반드시 require시켜줘야한다. 굳이 설명하지 않아도 필수이다.

 

const task1 = function (callback) {
    db.put('ThisIsKey', 'ThisIsValue', function (err) {
        if (err) {
            console.log(err);
        }
        console.log('task1');
        callback(null);
    });
};

const task2 = function (callback) {
    db.get('ThisIsKey', function (err, value) {
        if (err) {
            console.log(err);
        }
        data = value;
        console.log('task2');
        callback(null);
    });
};

const task3 = function (callback) {
    res.send(data);
    console.log('task3');
    callback(null);
};

 

그 다음 세가지의 루틴을 쪼개서 각각의 변수에 담는다.

이때 변수는 함수로 담아야한다.

그리고 꼭 callback(null)을 선언해줘야한다.

이 선언의 의미는 callback이 끝났다고 알려주는 것이다.

 

const tasks = [task1, task2, task3]
async.series(tasks);

이제 마지막으로 세개의 루틴을 하나의 리스트에 담고 나서

asun.series에 담는다. 여기서도 콜백을 써도된다. 본인의 자유.

 

asyn.series(tasks,callback);

 

이제 비동기 루틴들이 하나의 루틴으로 작동하는걸 확인할 수 있다.

 

 

비동기를 처리하는 방법은 이 외에도 여러가지가 있다.

그러니 다른 방법을 찾아서 사용하는것도 좋은 방법이다.

 

+ Recent posts