ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript - Promise 와 비동기 작업
    JavaScript 2021. 10. 1. 00:49

    자바스크립트는 싱글 쓰레드 동작 언어 (쓰레드는 일꾼의 개념)

    -> 동시작업이 안되고, 작업을 하나씩 수행한다. 그러나, 비동기작업은 동시에 수행할 수 있다.

    동시에 수행한다는 표현으로 혼동이 있을 수 있어, 비유하자면 다음과 같다.

     

     

    자바스크립트 비동기 작업

    -하나의 일꾼이 2개의 작업을 동시에 수행하는 것이 아니라,

    일꾼을 도와주는 존재에게 위임을 해서 그 위임된 작업이 처리 될때까지 각각 다른 작업을 동시에 진행하는 것. 

    - 어떤 작업하나를 요청해두고, 다른 작업을 수행하다가, 요청한 작업에 대한 결과가 나오면 또 그 결과에 이어서 진행하는 것.

    요청하고, 즉시 결과가 나오는게 아니고, 요청 후 결과가 나올때까지 기다려야 하니까 그 텀에 다른 작업을 하면서 기다리기 때문에, 동기가 아니라 비동기.

     

     

    자바스크립트 비동기 작업의 처리 과정
    (여기서 말하는 콜백은 패턴을 말한다. ‘어떤 함수에 인수로 넘기는 함수’ 를 뜻하는 콜백함수와 다르다.) 

    1. 콜스택에 들어간다. (작업을 처리하는 곳, 이 곳은 작업을 한번에 하나씩 처리하는 작업장이다.)
    2. 콜스택에서 바로 처리되지 않고, WebAPI에게 해당 작업을 위임한다
      (WebAPI에는 dom, ajax, setTimeout, TackQueue, Event Loop 등이 있음.)
      -> 위임하기 때문에 콜스택에는 해당작업이 없는 상태이다, 따라서 콜스택에서는 다른 작업을 진행할 수 있다.
    3. 위임받은 WebAPI가 해당 작업을 처리하여, 콜백함수(다음에 처리해야하는 무언가)로 콜백큐라는 곳에 보낸다.
    4. 콜백함수가 된 해당 작업은 이벤트루프를 통해서 다시 콜스택에 넘어간다.
    5. 그러면 다시, 콜스택에서 해당 작업을 처리하고 완료되면 사라지고 다음 작업을 한다.

    *이 경우에 발생하는 문제는 다음과 같다.

     - 위 4~5번의 과정에서 콜스택이 받은 작업이 또 비동기 작업일 경우, 즉 비동기 처리가 꼬리에 꼬리를 무는 경우.

    -> 이런 경우가 되면, 호출이 계속 중첩되고, 코드가 깊어지고, 관리가 어려워진다.

    ->> 이러한 중첩문제를 ‘콜백헬’ 혹은 ‘멸망의 피라미드’ 라고 지칭해서 부를 정도이다.

     

     

    Promise

    이러한 문제를 방지 및 해결하기 위해 ES6에서 도입된 비동기처리 패턴이 Promise 이다.

    비동기 연산이 종료된 이후 결과를 알기위해 사용되는 객체.

    -> 비동기 처리가 끝나는 시점을 보다 명확하게 표현할 수 있어서, 비동기 작업이 끝나고 난 후 결과를 알고 쓰기에 좋다.

    프라미스는 생성자함수로 생성되고, 비동기 작업을 수행할 콜백함수를 인자로 전달받아 사용한다.

     

    어떤 작업이 처리될 때, 이 작업이 성공하거나 실패할 수 있음.

    Promise를 만들고 호출을 해본 상태값으로 성공/실패 여부를 알수 있다.

    상태값의 종류 다음과 같다.

    1. pending : 비동기 처리의 수행 전 (위의 성공, 실패 즉, resolve, reject 가 아직 호출되지 않음)
    2. fulfilled : 수행 성공 (즉, resolve가 호출된 상태)
    3. rejected : 수행 실패 (reject 가 호출된 상태)
    4. settled : 성공 혹은 실패 (resolve 혹은 reject가 호출된 상태)

     

    프라미스로 구현된 비동기 함수는 당연히 프라미스 객체를 반환한다.

    그리고, 프라미스로 구현된 비동기 함수를 호출하는 측에서는 이 프라미스 객체의 후속처리 메서드를 통해 비동기 처리결과를 받아서 처리한다.

    프라미스의 후속처리는 promise.then(성공했을때 인자, 오류 실패했을때 인자) 로 확인한다.

    (이 때, promise는 변수명으로, 변경될 수 있고 성공했을 때의 인자 즉, 첫번째 인자만 넘겨도 된다.) 

    두번째 문단의 아래에 .catch를 바로 이어서 사용도 가능하다.
    성공했을때는 .then 실패했을 때는 .catch 로 받아올 수 있다. 동시에도 사용 가능하다.

     

    Promise chaining

    후속처리 메서드에 then을 계속 연결해서 이어 쓰는 것.

    -> 이것으로 콜백 헬을 해결 할 수 있다.

    예를 들어, 비동기 작업 1, 2, 3을 프라미스 객체로 만들고, 위 사진의 .then 다음에 넣어서 잇고, 또 그다음의 .then에도 이어서 연결 시킬 수 있다.

    프라미스를 편하게 사용해 주는 async, await

    async 는 함수 앞 즉, function 앞에 붙여서 사용하고,

    그냥 함수이더라도 항상 프라미스를 반환해 준다.

    비동기 함수가 아니더라도 프라미스로 반환을 해준다.

    await 는 async 함수 안에서만 동작하기 때문에 async가 없이는 쓰지 못한다. (보통 마지막 result 값을 보는 코드에 위치한다)

    await를 쓰면 프라미스가 처리될때까지 (pending이 아니라, 완전히 다 처리가 될 때까지) 기다리고 처리결과를 반환한다.

    -> await를 쓰면, 쓰레드가 WebAPI에 작업을 위임하고 바로 다른 작업을 수행하는 것이 아니라, 프라미스가 처리될 때까지 기다린다.

    ->> 그리고 처리가 완료되면 그때서야 다시 작업을 수행한다.

    ->>> 비유하자면, 위임한 작업 처리될때까지 쓰레드 너 작업장에서 다른일 하지마!

     

     

    'JavaScript' 카테고리의 다른 글

    Filter 메서드의 사용  (0) 2021.10.28
    JavaScript - Debounce 와 Throttle  (0) 2021.10.10
    JavaScript 문법 정리3 (ES6 함수)  (0) 2021.09.30
    JavaScript 문법 정리2 (ES6 객체)  (0) 2021.09.30
    JavaScript 문법 정리 1 (ES6)  (0) 2021.09.30
Designed by Tistory.