본문 바로가기
JavaScript

2021.08.04 JavaSript 콜백 지옥에서 벗어나기

by 해맑은 코린이 2021. 8. 4.

2021.08.04 JavaSript 콜백 지옥에서 벗어나기_정리노트

 

 

책에서 이제 외부 API 연동을 위해서 자바스크립트 개념이 나오기에... 미뤄왔던 개념부터 정리할 예정....흑흑.....객체랑 콜백이 제일 어렵단... 이번에는 조금 빡세게 정리하고 넘어가야할듯하다. 그동안은 계속 가볍게 얘기해왔기에..

 

 

그 전에 비동기 작업에 대한 이해를 책에서 다루기 때문에 같이 정리해볼 예정!

 

비동기 작업

웹 애플리케이션을 만들다 보면 처리할 때 시간이 걸리는 작업이 있다.

예로 서버쪽 데이터가 필요할 때는 Ajax 기법을 사용하여 서버의 API 를 호출함으로써 데이터를 수신한다. 이렇게 서버의 API 를 사용해야할 때는 네트워크 송수신 과정에서 시간이 걸리기 때문에 작업이 즉시 처리되는 것이 아닐라, 응답을 받을 때까지 기다렸다가 전달받은 응답 데이터를 처리한다. 이 때 처리과정을 우리는 비동기적으로 처리하게 된다. 

 

 

 

맥은 왜 그림판 없나요..... 쥬..륵..... 

 

쨋든 대충 일러스트로 그려서 가져왔는데 위의 그림처럼 동기적으로 작업을 처리한다면, 1번의 요청이 끝날 때까지 기다리는 동안 2번 3번이 중지하게 되고, 다른 작업을 할 수 없게 된다. 1번이 끝나면 2번이 수행되고 2번이 끝나면 3번이 수행되고..

 

이를 비동기적으로 작업하게 되면, 멈추지 않고 1번을 기다리는 동안 2번 3번 작업,요청을 처리할 수 있고, 기다리는 과정에서 다른 함수도 호출할 수 있다. 

 

이렇게 서버 API 를 호출할 때 외에도 작업을 비동기적으로 처리할 때가 있는데, setTimeout 와 같이 특정 작업을 예약할 때이다. 

 

function printMe(){
 	console.log("print me !")
}
setTimeout(printMe, 3000);
console.log(" 대기중입니다... ");

 

printMe 함수가 3초 뒤에 실행하라고 setTimeout 이 사용되는 시점에서 3초동안 멈추는 것이 아니라, 일단 코드가 위부터 아래까지 다 호출되고 3초뒤에 print me! 가 뜨는 것을 볼 수 있다. 

 

setTimeout 에 인자로 지금 printMe 라는 함수를 전달해주었는데, 이를 콜백함수라 하며 자바스크립트에서 비동기 작업을 할 때 가장 흔히 사용하는 방법이다. 

 

콜백함수

파라미터로 함수를 전달받아, 함수 내부의 함수를 뜻한다. 함수 내부에서 실행하는 함수!

 

 

책에서 나온 예제도 보면,

 

 

해당 예제도 1초뒤에 setTimeout 으로 파리미터를 받은 후 1초 뒤에 10을 더해서 반환한다. 

 

 

그리고 해당 함수가 처리된 직후에 어떠한 작업을 하고 싶으면 2번째 인자로 콜백함수를 넣어주면 된다!

 

 

 

 

https://www.youtube.com/watch?v=s1vpVCrT8f4 

 

 

 

두번 첨부하기 ㅎㅅㅎ 체고 여기서 콜백 지옥도 볼 수 있다. 

콜백을 순차적으로 처리하고 싶어서 콜백함수를 중첩에 중첩..하다보면 무한 콜백 지옥 생성!

 

 

이를 1초뒤엔 10을 더해주고, 그게 끝나고 1초뒤에 또 10을 더하고, 이를 계속.. 하다보면 가독성이 극강으로 떨어지는 콜백지옥 함수가 완성됨.

 

콜백지옥,,,,,, 3개밖에 안했는데도 정신 혼미

 

 

혼미하군..... 이러한 코드는 가독성을 극강으로 떨어뜨리기 때문에 지양할 형태의 코드이다. 

 

 

 

콜백함수의 원칙

( 참고 자료: https://velog.io/@minidoo/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%BD%9C%EB%B0%B1-%ED%95%A8%EC%88%98Callback-Function )

 

익명 함수 사용

여기서도 우리가 화살표 함수를 사용했는데, 저번에 말했을 때 화살표 함수는 익명함수기 때문에 이렇게 적어주었다.  함수 안의 함수기 때문에 이름을 붙여주지 않아도 된다.

 

 

 

함수의 이름만 넘기기

 

 

자바스크립트에서는 null,undefined 타입을 제외하고 모든 것을 객체로 다루는데, 함수를 변수처럼 사용하거나 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우 함수의 이름만!

 

여기서 보면 finishFunc 을 콜백함수로 넣어주었는데, whatYoutName 함수에  finishFunc () 이렇게 넘겨주지 않았고, 마찬가지로 whatYoutName 인자 자체에서도 callback() 이 아닌 callback 으로 넘겨주었다.

 

 

 

지역 변수,전역 변수 사용 가능

 

 

여기서는 콜백함수 eat 를 만들고, 함수 안에 지역변수인 vegetable, 전역변수인 fruit 또한 콜백함수에 넣어주었다. 

그래서 callbackFunc 인자에 eat 콜백함수를 담아주었는데, 정상적으로 전부 담아서 출력해주는 것을 볼 수 있다!

 

 

 

음음.. 헷갈리지만, this 만 사용하지 않는다면 ......ㅎㅎ..... 차근차근 이해는 되는 것 같다..! this 를 사용할 때는 this 가 가리키는게 너무너무ㅜ너무 헷갈..ㅠ ㅎㅎ


 

쨋든 콜백지옥등등 문제 때문에 역시 ES6에서는 새로운 기능 나왔다! 

 

와! Promise!

 

Promise

해당 기능은 콜백 지옥 같은 코드가 형성되지 않게 하는 방안. 

 

예제 코드

function increase(number){

const promise = new Promise((resolve,reject)=>{
// 성공하면 resolve, 실패하면 reject
setTimeout(()=>{
    const result = number+10;
    if(result>50){
    //50보다 높으면 에러 발생 시키기
    const e =new Error('숫자가 너무 큽니다');
    return reject(e);


}
resolve(result); // number 값에 +10 후 성공 처리

},1000)
})
return promise;
}

 

Promise 의 상태는  3개로 나뉜다. 

 

 

 

대기 

비동기 처리 로직이 아직 완료되지 않은 상태

new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve, reject이다.

 

이행

비동기 처리가 완료되어 프로미스가 결과 값을 성공적으로 반환해준 상태

여기서 콜백함수의 인자인 resolve 를 실행하면 이행 상태가 된다. 

 

실패

처리가 실패하거나 오류가 발생한 상태

여기서 콜백함수 인자인 reject 를 실행하면 실패 상태가 된다. 

 

 

이렇게 프로미스를 실행하면 각각의 상태를 받을 수 있는 함수가 또 존재!

 

예제 코드

increase(0)
.then(number=>{

//Promise 에서 reslove 된 값 .then 으로 받아오기 가능
console.log(number);
return increase(number) //Promise return 하면,

}) .then(number=>{
// 또 then 으로 처리 가능
console.log(number);
return increase(number)

}).then(number=>{

console.log(number);
return increase(number)

}).then(number=>{

console.log(number);
return increase(number)

})
.then(number=>{

console.log(number);
return increase(number)

})
.then(number=>{

console.log(number);
return increase(number)

}) 
.catch(e=>{
console.log(e);
})

 

 

여기서 50이 넘으면 에러를 띄우라고 했는데 그 전에는 이행, 즉 resolve 상태를 반환하므로 이 때는 .then 으로, reject로 실패 상태를 반환할 때는 .catch 로 각각 처리 결과를 받을 수 있다. 

 

 

 

이렇게!!!!! 이렇게 하면 함수안에 함수를 여러번 감싸지 않고 .then 을 이용해서 그 다음 작업을 설정하기 때문에 콜백 지옥이 형성되지 않는다!!!! 굿굿

 

 


 

 

근데!!!! 또 Promise 를 더욱 쉽게 사용할 수 있도록 해주눈 ES8 문법인 async / await 문법도 있다! 정리 ㄱ

 

async / await 

기존 비동기 처리 방식인 콜백함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 나온 최신 문법으로, 기존 비동기 처리의 순서를 보장받기 위해서 여러가지 복잡한 것을 쓰는 것인 아닌 async / await 키워드를 추가해줌으로써 위에서 밑으로 순서대로 편하게 읽을 수 있는 마법...! 

ㅠㅠㅠㅠㅠㅠㅠ 최고... 

 

기본 형태는

 

async function 함수명() {
  await 비동기_처리_메서드_명();
}

 

이렇게 이루어지고, 이렇게 하면 콜백 함수나 .then 을 사용하지 않아도 Promise 가 끝날 때까지 기다렸다가 결과 값을 특정 변수에 담을 수 있음!

 

 

아까 썼던 increate 함수에 대한 처리를 async awiat 를 통해서 해보자!

//async 키워드 추가

async function runTasks(){


// try, catch 구문을 사용하여 예외 처리
// 메소드 앞에 await 키워드 추가
try{
    let result = await increase(0)
    console.log(result);

    result = await increase(result);
    console.log(result);
    

    result = await increase(result);
    console.log(result);

    result = await increase(result);
    console.log(result);


    result = await increase(result);
    console.log(result);

    result = await increase(result);
    console.log(result);


}catch(e){
    console.log(e);


}


}

 

 

 

크으 좀 더 괜찮아진거같음.

예외처리도 try, catch 문으로 하면 되기 때문에 좀 더 괜찮아졌균!!!!!

 

 

 

 


점점 발전하는 자바스크립트....끌끌 이제는 어느정도 비동기처리에 대한 이해를.......다 하진 못했지만...^^ 지금 한 3번째 찬찬히 읽어보니까 처음보다는 나은거같아~~~~ 다음에 또 보면 이해가 될 거라고 긍정적으로 생각을 하규 !! 

오늘은 책에서 본격적으로 외부 API 와 통신을 하는 코드를 작성할거기 때문에 한번 기본 개념 정리가 필요한 시점인 것 같아 간단한듯..아닌듯 하게 한번 개념 정리를 했다!!!

 

후후..화..이팅...!!!! 오늘의 포스팅은 끝!

댓글