Promise( AJAX, AXOIS ) 와 같은 비동기 연산 처리 ( 자바스크립트 )
Promise ( 부제 : 자바스크립트 비동기 함수에 대한 이해 )
Promise의 다른 문법적인 부분은 잘 설명된 글이 많으니 설명은 간단히 하겠다.
본문은 디테일한 내용보다는 대략적인 개념을 잡는데 좋은 영향을 줄 수 있길 바란다.
유사한 AJAX, AXIOS등에서 사용되는 구조인데 이에 처음 접할때 힘든 경우들을 보았다.
Promise는 비동기 연산을 나타내는 객체다.
음.. 지금은 지나치자 그냥 이정표를 하나 본 거다.
뭘 알려고 하는가? 이거에대한 것이니 그냥 흘깃 한번 보고 지나치자
낯설 수 있는 단어가 처음은
비동기/동기 라 생각한다.
( async / sync )
단어그대로 뭔가 같이하지 않은 상태/동조된 상태가 떠오를 것이다.
그리고 그 흐름이 맞다.
한단계 이해를 거쳐야하는 코드보다
우선 예시를 생각해볼건데
그 전에 오해?오류?가 있을 수 있는 것들을 짚고가겠다
오해가 있는 상태로 예시를 보면 오해에 개념을 입혀 고착화 시킬 수 있기때문이다.
비동기는 쓰레드를 여러개 사용한다 / 멀티 쓰레드 환경에서 쓰인다 -> False
비동기 작업은 항상 더 빠르다 -> False
동기 작업은 항상 blocking(lock)된다 -> False
혹시 이렇게 생각하고 있었다면
이건 지워보도록 하자
비동기/동기의 예시를 들어본다면
요리를 한다고 생각해보자
가스렌지에 화구가 2개 있다.
A.
화구 하나에 후라이팬을 놓고 계란후라이를 한다.
->
후라이가 완료됐다.
->
냄비를 놓고 김치찌개를 한다.
->
김치찌개가 완료됐다.
B.
화구 하나에 후라이팬을 놓고 계란후라이를 한다.
->
옆의 화구에 냄비를 놓고 김치찌개를 한다.
->
김치찌개가 완료됐다
->
후라이가 완료됐다.
A와 B의 경우를보면
A는 하나의 작업을 하고 그 작업이 완료되면 다음 작업을 했다.
B는 하나의 작업을 하고 그 작업의 완료를 기다리지 않고 다음 작업을 했다.
대신 예시다보니 B의 경우 김치찌개를 먼저 완료했다고 했는데
완료 순서는 사실 열린결말이다.
김치찌개가 더 오래걸릴 수도 있고
후라이가 더 오래걸릴 수 있다.
여기서 중요한건
B는 다음 작업을 실행할때, 먼저 작업의 종료를 기다리지 않았다는 것이다.
요 특징 하나만 잡으면 된다.
그럼 이제 오해들을 하나씩 보자
1. 비동기는 쓰레드를 여러개 사용한다 / 멀티 쓰레드 환경에서 쓰인다
: 예시를 보며 의문이 들 수 있다.
아니, 화구가 2개고 그래서 2군데서 했으니까 멀티쓰레드 아니야?
설명도 그렇게 해놓고 뭐야?
싶을 수 있다.
예시는 설명하려는 특징점을 잘 나타낼 수 있도록 설정했다.
여기서 조금 다르게 바라봐보자
요리를 하는 사람은 몇명인가?
이걸 지금 쓰레드와 프로세스로 확장시켜보지는 말자
그냥 한 사람이 번갈아서 이 요리 저 요리를 했다고 생각해보자
이게 자바스크립트의 싱글쓰레드에서 이뤄지는 비동기 작업이다.
즉 해당 명제는 틀린경우가 있다. 옳은 경우도 당연히 있다.
그렇기 때문에 명제는 틀렸다.
2. 비동기 작업은 항상 더 빠르다
위의 요리 예제에서는 당연히 두 개의 요리를 같이 하기때문에
더 빨리 완료될 것이다.
( 그냥 짚고 넘어가자면 그에따른 리소스는 당연히 더 들어간다 )
그런데 만약
1의 마지막에 얘기한 것처럼 한 사람이 번갈아서 이 요리 저 요리를 한 것처럼
두개의 문서 이력서, 자기소개서를 작성한다 했을때
하나씩 번갈아서 작업하면 어떻게 될까
흐름이 끊기지 않는다면 최소한 똑같은 시간이 걸리거나
다른 작업으로 변경하는 시간이 소요된다면 시간이 더 걸릴 수 있다.
( 대신 두 서류의 연관된 정보를 잘 담을 수 있을지도 모른다 )
이처럼 2번 역시 명제로서 참/거짓은 false이다.
3. 동기 작업은 항상 blocking(lock)된다
이 역시 2에 나왔듯이
( 대신 두 서류의 연관된 정보를 잘 담을 수 있을지도 모른다 )
에서 처럼 접근가능할 수 있다.
락을 거는건 별개의 개념으로 비동기/동기와 관련돼있지 않다.
락을 걸면 거는거고 아니면 아닌거다.
즉 false이다.
이제 비동기/동기를 살펴보았으니
Promise를 보자.
Promise는 try-catch처럼 활용한다고 생각하면 좋다.
여기에 비동기를 한스푼 넣으면 된다.
promise는
비동기로 연산을 할 수 있도록 한 객체이고
2가지 인자를 받는다 ( 사용여부는 선택적이다. )
resolve와 reject이고
resolve는 성공시 받게되는
reject는 실패시 받게되는
함수인 인자이다.
이는 Promise 객체 생성시 생성자 함수에의해 제공되는 콜백함수이다.
이때
then() : try의 완수처럼
catch() : catch
finally() : finally
이렇게 각 경우에따라 처리 로직을 지정할 수 있는데
뭔가 복잡하게 느껴하는 경우들이 있는데
그냥 성공하면 then
실패하면 catch
무조건 finally를 실행하는 개념이다.
여기에 비동기가 더해져서
본 흐름과 별개로 진행될 뿐이다.
그리고 비동기 연산의 결과는 도착하면 그때 반영하게 되는거고
이때의 분기를 나누기위해 필요한 함수들일 뿐이다.
ajax(axios)의 경우에도 통신 성공, 실패에따른 분기를 나누고 통신요청을 보내고나서
결과를 기다릴동안 다른 작업들은 다른 작업대로 진행하고 이것의 결과가 도착하면
결과에대한 별도 처리를 하는 부분이 .ok() .error()등에 있는 것이다.