동기처리 방식

우리가 만약 세가지의 작업을 수행해야한다고 가정해보자.

    function taskA() {
      console.log("tast A");
    };

    function taskB() {
      console.log("tast B");
    };

    function taskC() {
      console.log("tast C");
    };

 

 

자바스크립트가 세가지의 작업을 처리하는 방식을 대략적으로 적어보면...

1. 연산과정이 필요하다.

=> 여기서 연산과정은 우리가 위에적었던 코드 한줄한줄을 다 연산한다고 생각하면 쉽다.

이때, 이 연산과정을 처리하는 친구를 "스레드" 라고 한다.

스레드라는 것은 코드를 한 줄 한 줄 실행시켜주는 친구라고 생각하면 쉽다.

 

tastA => taskB => taskC를 순차적으로 실행시켜줄텐데 0.3초 0.5초 0.2초가 걸리고 있다.

taskA작업을 스레드가 수행하고 있을때, 스레드는 taskA에 혼신의 힘을 쏟고 있는 것이다.

(다른작업은 하지않음) taskA 끝나야 비로소 taskB가 수행된다.

이렇게 지시한 순서대로 작업을 진행하면서 앞에 작업이 끝날때까지 기다렸다가

다음 작업을 수행하는것을 동기적 방식이라고 부른다.

 

그리고 스레드에서 작업 하나가 수행하고 있을때,

다른 작업을 동시에 할 수없는 방식을 블로킹 방식이라고 한다.

(블로킹 방식은 지금은 내가 실행중이니 방해하지마~ 라는 뜻)

위의 코드에서는 하나하나의 작업들이 길어봐야 0.5초이기때문에 문제가 없다.

 

하지만 수행해야할 여러가지 작업들이 20초나 10초씩 걸린다면 어떻게 될까?🤯

자바스크립트를 배우고 사용하는 이유는 웹사이트의 동작을 제어하고

사용자가 어떤 버튼을 누르고 스크롤을 했을때, 반응을 해주기 위해서 자바스크립트를 배우고 있는 것인데..

사용자가 버튼을 누르고 실행하는데 30초나 걸린다면....사용자는 속터지고 다시는 웹사이트에 

방문하지 않을것이다.🥶

 

이렇게 동기적으로 작업을 처리하게 되면 중간에 오래걸리는 작업도 포함하기때문에

작업 수행시간이 길어지게 되는 성능상의 문제가 생긴다.

 

 

 

그렇다면 우리의 친구 스레드를 여러개로 늘리면 더 빠른 작업을 할 수 있지않을까?

스레드를 두 개로 늘려보았다. 스레드가 여러개를 사용하는 방식은 멀티 스레드라고 부른다.

 

하지만 안타깝게도...

자바스크립트에선 스레드를 하나밖에 사용하지못하는

싱글 스레드를 사용하고 있다. => 스레드(일꾼)을 여러개로 늘릴 수 없다.

 

 

 

비동기 처리방식

그럼 우리는 항상 속터지는 웹사이트를 방문해야할까? 아니다

스레드가 하나일지라도 여러개의 작업을 동시에 할 수있게 실행시켜버리면 된다. 

(전의 작업이 끝나던말든 상관x)

동기적이기않게 여러개의 작업을 동시에 수행하는 방식을 비동기 처리방식이라고 한다.

하나의 작업이 스레드를 점유하지않는 이런 방식을 블로킹하지않는다해서 논 블로킹 방식이라고 부른다.

그럼 마구잡이로 동시에 실행시켜버리면 작업이 언제끝났는지 어떻게 알 수 있을까?

 

콜백함수를 사용한다.

각각의 함수들에 '이 작업이 끝나면 이걸 실행해!' 라는 의미의 콜백함수를 붙여서 전달해주면 된다.

    taskA(() => {
      console.log(`A 끝. 작업결과 : ${resultA}`)
    });

    taskB(() => {
      console.log(`B 끝. 작업결과 : ${resultB}`)
    });

    taskC(() => {
      console.log(`C 끝. 작업결과 : ${resultC}`)
    });

비동기처리를 할때는 우리가 자바스크립트에서 함수를 호출할때 콜백함수를 붙여 그 비동기처리의 결과값이나

어떻게 잘 끝났는지 확인하는 역활을 하게 된다.

 

 

 

useEffect hook을 사용하는 코드를 보면서

비동기 처리방식을 조금 더 살펴보자.

import { useEffect, useState } from 'react';

function App() {
  const [first, setFirst] = useState(1);
  const [second, setSecond] = useState(1);

  const handleFirstClick = () => setFirst(first + 1);

  const handleSecondClick = () => setSecond(second + 1);

  useEffect(() => {
    console.log('렌더링 이후', first, second);
  }, []);

  console.log('렌더링', first, second);

  return (
    <div>
      <h1>
        {first}, {second}
      </h1>
      <button onClick={handleFirstClick}>First</button>
      <button onClick={handleSecondClick}>Second</button>
    </div>
  );
}

export default App;

위에 코드를 그대로 콘솔에 실행을하면 

1. '렌더링'이 제일 위에 오고

2. '렌더링 이후'가 그다음에 오게된다.

이유는? 컴퓨터는 어떠한 작업을할때 위에서 아래로 코드를 읽어나가는데

useEffect는 비동기이기 때문에 따로 비동기만 저장 할 수 있는 어떠한 공간에 비동기를 임의로 저장시켜둔다.

그 다음 밑으로 내려서가서 동기를 먼저 실행시키고 나서 다시 비동기를 실행시킨다.

우리 눈에는 보이지않지만 해당 과정이 끝나고 나면 

우리가 보는 페이지는 정상작동이 되는 것이다.

 

 

1. 동기는 지시한 순서대로 작업을 진행하면서 앞에 작업이 끝날때까지 기다렸다가 수행하는 것이다.
2. 동기는 중간에 오래걸리는 작업이 포함되면 작업 수행시간이 길어지게 되는 성능상의 문제가 생긴다.
3. 비동기는 먼저 지시한 작업이 끝날때까지 기다리지않고 여러개의 작업을 동시에 수행하는 방식이다.
4. 비동기는 동기보다 복잡하고 결과가 주어지는데 시간이 걸려도
그 시간동안 다른 작업을 할 수 있어서 보다 효율적일 수 있다.
5. 비동기처리를 할때는 콜백함수를 붙여주면 비동기처리의 결과가 잘 끝났는지 확인 할 수 있다.

 

리액트를 다루는기술 356p 14.1 참고

복사했습니다!