본문 바로가기

프로젝트

코드 리팩토링 비동기편 (await과 병렬)

비통기 통신 await과 병렬통신

프로젝트 코드를 보던 중 비동기에 대해 생각하고 있었는데 await이 지금 내 프로젝트에 어울릴까 하는 생각이 들었고 

await 보다 병렬 통신이 더 잘 어울린다 생각해 병렬 통신으로 바꾸게 되었다! 

 

비동기이란? 

두 가지 작업이 동시에 실행되거나, 하나의 작업이 끝날 때까지 기다리지 않고 다른 작업을 실행하는 것을 말한다.

 

탕짜면 주문이 들어왔을 때와 볶음밥과 짜장면이 하나씩 주문 들어왔을때 써야할 비동기 통신이 다르다!

 

await은 탕짜면?

await은 비동기적으로 데이터베이스 쿼리를 실행하고 결과를 가져오는 방식이다. 특징은 아래와 같다.

   - 개별 데이터 호출에 대해 순차적으로 처리

   - 코드의 가독성이 좋음

   - 데이터 호출이 순차적으로 처리되므로, 데이터 호출 간의 의존성이 있는 경우에 유용

   - 데이터 호출이 순차적으로 이루어지므로, 병렬 처리에 비해 전체적인 실행 시간이 느릴 있음

 

await이 사용되는 예를 들자면 탕짜면 주문이 들어왔을때 탕수육이 튀겨질동안 짜장면을 만드는 것과 비슷한데 

이유는 await의 특징중 데이터 호출의 의존성이 있는 경우에 사용되기 때문이다. 아래 코드를 보자

 

async function 탕짜면(){ // 탕짜면 만들려면 
    const 탕수육 = await 튀김옷입히기 + 튀기기; // 탕슉 만들때
    const 짜장면 = await 면삶기 + 소스만들기; // 짜장면 만들고
    return [짜장면, 탕수육] // 같이 나간다. 
}

 

위 주석처럼 탕슉 만들 동안 짜장면을 만들고 같이 나가는 것과 같다! 

여기서 탕짬면이 만들어 지려면 탕수육과 짜장면이 필요하다 즉 탕짜면은 탕수육과 짜장면에 의존성을 가지고 있다. 

탕수육과 짜장면이 다 만들어져야 탕짜면이 되기 때문이다. 

그래서 await이 의존성을 가지고 있는 비동기 통신에 쓰이게 되는 것이다.

 

병렬은 짜장면 하나 볶음밥 하나

병렬 비동기 통신은 각기 다른 주문을 만들 때 사용된다! 

예를 들어 짜장면 하나 볶음밥 하나가 주문되면 짜장면 만들 동안 볶음밥도 동시에 만드는 것이다!

병렬 비동기 통신을 하려면 Promise.all을 사용하면 된다! 

 async function 메뉴두개() {
  const [짜장면, 볶음밥] = await Promise.all([
    짜장면만들기(),
    볶음밥만들기()
  ]);
  console.log("짜장면:", 짜장면);
  console.log("볶음밥:", 볶음밥);
}

메뉴두개();

이렇게 하면 동시에 만들고 동시에 메뉴가 나가게 된다! 

주의점

Promise.all은 실패 우선성을 가지고 있기 때문에 하나라도 거절되면 다 거절되게 된다! 

그래서 아래처럼 발생할 수 있는 거부를 사전에 처리해하면 더 안전하게 할 수 있다! 

 const [짜장면,볶음밥] = await Promise.all([ // promise.all을 사용해 동기적으로 실행
 	짜장면만들기().catch(error => { return error }),
    볶음밥만들기().catch(error => { return error }),
    ]).then(values => {
  console.log(values[0]) // "짜장면"
  console.log(values[1]) // "볶음밥 해야하는데 밥이 없넹;;"
})

여기서 한번 더 주의할 점은 만약 짜장면의 면이 없어 에러가 났다면 에러 사유는 볶음밥이라도 면이 없다고 나오게 된다. 

 

그래서 바뀐 코드는 

병렬 Promise.all을 사용함

이렇게 되었다!