본문 바로가기
📌 Front End/└ JavaScript

[JavaScript] 자바스크립트 콜백 지옥(동기, 비동기)

by 쫄리_ 2023. 3. 10.
728x90
반응형

1. 동기와 비동기

javascript를 사용하면서 데이터를 처리할 때 사용하는 방식인 동기와 비동기 처리에 대해 설명해볼려고 한다 비동기 함수를 사용해 본 적은 있지만 이것의 개념을 정확하게 알지 못하고 넘어간 거 같아 이번 기회에 한 번 동기와 비동기의 차이점과 비동기 함수의 콜백함수 개념을 간단한 예제를 통해 설명하겠습니다.


동기(Synchronous)

동기는 반드시 작성된 순서대로 실행된다 먼저 불러온 순서대로 차례대로 나오는 방식입니다 이전의 함수가 무조건 끝나야 다음이 실행됩니다


비동기(Asynchronous)

자바스크립트는 싱글스레드이기 때문에 한 번에 하나의 작업만 수행할 수 있습니다 이를 해결하기 위해 비동기 처리가 생겼습니다 비동기는 작성된 순서대로 실행하지 않고 내가 원하는 함수를 먼저 호출하거나 오래 걸리는 작업의 위치를 자유롭게 변동하여 시간 낭비를 줄일 수 있습니다 멀티태스킹 방식으로 모든 작업을 한꺼번에 실행하여 처리 속도가 향상됩니다


🐭 근데 이거 Blocking, Non-Blocking이랑 같은 개념아니야??


2. Blocking & Non-blocking

위 동기와 비동기는 시간의 관점으로 볼 수 있고 블로킹과 논블로킹은 제어권의 관점으로 볼 수 있다 막힌 상태인가 안 막힌 상태인가를 생각해보고 위 사진을 통해 각 역할을 비교할 수 있다 보통은 (blocking + synchronous) , (non-blocking + asynchronous)가 흔하게 볼 수 있는 모델이다


동기 비동기 Blocking Non-blocking 이해하기

아래 예시를 보면서 각 역할에 따른 내용을 확인해볼 수 있습니다 Non-blocking & Asynchronous 조합이 가장 효율적인 방법인것을 확인할 수 있습니다

🐭 비동기에 대해 아직 잘 모르겠어 예시를 들어줘


3. setTimeout

자바스크립트에서 가장 대표적인 비동기 처리 방법 중에 setTimeout()으로 이후 함수를 실행시켜주고 본인은 일정 시간 이후에 함수를 실행시켜줍니다 setTimeout()에는 크게 두 개의 인자가 있는데 첫 번째는 일정 시간 이후에 실행할 콜백함수와 몇 초 후에 실행할지 정해주는 두 번째 인자가 존재한다 아래는 코드 사용 방법입니다 그렇다면 예시를 들어보면서 자세히 알아보도록 하겠습니다

setTimeout(() => { /* 실행코드 */ } , delay)

집안일

현재 창문 닦기, 빨래하기, 방 청소이 세 가지를 순서대로 진행해야 한다고 예를 들어보자 동기로 예를 들어보면 빨래를 널기 위해서는 세탁기를 돌려야 하는데 세탁기가 돌아가는 40분 동안은 아무것도 진행하지 않고 그대로 기다려야 한다 하지만 비동기로 작업을 할 경우 세탁기가 돌아가는 동안 방 청소를 완료하고 그 이후에 세탁기가 끝나면 빨래 널기를 진행하면 작업이 끝난다

 


결과처럼 비동기를 사용하면 작업이 실행되는동안 다른 작업을 돌릴 수 있기 때문에 시간 절약이 가능합니다 동기는 방 청소까지 해야 하는 모습이 보입니다

🐭 차이점은 이해했지만 아직 비동기 프로그래밍에 대해 이해하지 못하겠어


4. 비동기 처리

위에 설명에서 비동기는 싱글스레드인 자바스크립트에서 비동기 함수를 사용해 이 문제를 해결했다고 했다 그중 대표적인 처리 방법 중 setTimeout()을 이용해 예시를 들었는데 우리는 비동기로 처리하는 여러 가지 방식에 관해 설명하고 비동기 제어가 어떤 식으로 발전했는지 알아보도록 하겠습니다


비동기의 주요 사례

  • 마우스, 키보드 입력 (click, keydown 등)
  • 타이머 API (setTimeout 등)
  • fetch API , AJAX

콜백(Callback) 함수

이전에 setTimeout()에 첫 번째 인자로 콜백 함수를 사용한다고 설명했었다 콜백 함수는 나중에 호출되는 함수를 말합니다 지정한 함수가 실행되면 이후에 들어있는 함수가 동작하는 상태를 말합니다 우리가 setTimeout에 delay를 걸고 그 시간이 지나면 안에 함수가 출력되는 상태를 말합니다

function 콜백할함수() {
  setTimeout(() => {
    alert("안녕");
  }, 2000);
}

🐭 콜백함수를 전달할 때 반복적으로 사용해야할때도 이 방법을 사용해??

콜백지옥

위처럼 단순하게 콜백 처리한다면 문제가 없지만 우리가 비동기로 프로그래밍을 할 때, 실행 순서를 신경 쓰다 보면 여러 가지 함수가 필요할 것이다 특정값을 찾기 위해 많은 함수가 필요할 때 우리는 코드를 어떻게 짜야 할까 아마도 아래와 같은 코드가 만들어질 것입니다

위 사진의 내용을 요약하면 대학생 A의 고등학교 3학년 당시에 담당 수학 교사의 교사명을 찾아내는 코드입니다
1. 대학생 A의 학번을 입력하는 함수
2. 학번으로 학생의 주민번호와 고등학교명을 찾는 함수
3. 고등학교명으로 A의 수강했는 수업을 출력하는 함수
4. 수강했던 수업 중에 수학을 찾아내 수학의 수업코드를 찾아내는 함수
5. 해당 수업 코드를 담당했던 교사의 이름을 출력하는 함수

5개의 함수가 한곳에 모두 들어가 있는 상태입니다 우리는 이것을 콜백지옥이라고 부르고 이렇게 코드를 짠다면 코드의 가독성은 엄청나게 떨어질 것입니다 그렇게 해서 자바스크립트 ES6 이상 버전에서 Promise 라는 것이 생깁니다


Promise

ES6부터 도입된 Promise는 비동기 작업을 수행하는 함수가 프로미스의 객체를 반환하는데 그 생성자에 두 개의 인자가 들어가는데 첫 번째는 수행할 비동기 작업 두 번째 인자에는 작업한 결과물을 콜백함수에 전달하는 함수가 들어갑니다 그리고 해당 함수에 resolve 성공과 reject 실패도 할 수 있습니다 그렇다면 Promise를 사용해 코드를 작성해보겠습니다

대학생 A의 학번을 입력하는 함수를 받아오고 then이라는 함수를 이용해 체이닝 방식으로 비동기 작업을 순차적으로 처리가 가능합니다 결과는 똑같지만 훨씬 직관적이고 가독성이 나아져서 콜백지옥을 탈출했습니다

🐭 많이 좋아졌지만 난 아직도 복잡해 보이는걸


async/await

ES8부터 도입된 async/await입니다 이것은 비동기 함수를 마치 동기적 코드인 거처럼 동작하도록 구현할 수 있습니다 특히 Promise에서 사용했던 후속 처리 메서드 없이도 처리결과를 반환하도록 구현할 수 있습니다 단, await는 async안에서만 작동하기 때문에 함수 앞에 꼭 async를 넣어주도록 합니다 그러면 async/await를 사용해 다시 코드를 작성해보겠습니다

await를 사용해 해당 변수를 가져오면 그다음 함수가 실행되도록 할 수 있습니다

콜백지옥과 async/await 두개를 비교해보면 그 체감은 더욱 극대화할 것입니다


자료 코드보기

깃허브 링크

도움 자료

자바스크립트는 왜 싱글스레드일까??   https://chanyeong.com/blog/post/44
동기,비동기 그리고 blocking & non-blocking  https://musma.github.io/2019/04/17/blocking-and-synchronous.html
비동기 프로그래밍 - https://www.youtube.com/watch?v=m0icCqHY39U

728x90
반응형