본문 바로가기
Programming/Javascript

[Javascript]Synchronous Processing(동기) 와 Asynchronous(비동기)에 관하여

by SheenaKaze 2024. 9. 5.

1.Synchronous Processing 동기

요청을 보내고, 응답이 올 때까지 대기한 후 응답이 오면 작업 진행

일의 순서가 중요한 경우 동기 처리를 진행하면 된다.

처리 순서가 보장되지만, 다음 응답이 오기까지 다른 작업을 수행할 수 없기에 비효율적일 수 있다. 

 

  console.log("첫 번째");

  for (let i = 0; i < 1000000000; i++) {
    // 무거운 작업
  }
 
  console.log("두 번째");

2. Asynchronous Processing 비동기 

요청을 보내고, 응답을 기다리지 않고 다음 작업을 계속 해서 진행

일의 순서가 중요하지 않을 경우 효율적인 작업의 처리를 위하여 활용할 수 있다. 

  function sendTextMessage(message, callback) {
    // 메시지를 보내는 비동기 작업을 가정해요.
    setTimeout(() => {
      console.log("문자 메시지 전송 완료: " + message);
      callback(); // 응답이 도착하면 콜백 함수 호출
    }, 2000); // 2초 후에 메시지 전송이 완료된다고 가정
  }
 
  console.log("메시지 보내기 시작");
  sendTextMessage("안녕, 잘 지내?", function () {
    console.log("메시지 전송 후 후속 작업 수행");
  });
  console.log("다른 작업 수행");
 
  // 출력 결과:
  // 메시지 보내기 시작
  // 다른 작업 수행
  // 문자 메시지 전송 완료: 안녕, 잘 지내?
  // 메시지 전송 후 후속 작업 수행

 

import React, { useState, useEffect } from "react";

function App() {
  const [post, setPost] = useState(null);

  useEffect(() => {
    console.log("시작");

      .then((response) => response.json())
      .then((json) => {
        setPost(json);
        console.log("데이터 가져오기 완료");
      });

    console.log("끝");
  }, []);

  return <div>{post ? <div>{post.title}</div> : <div>Loading...</div>}</div>;
}

export default App;

 

위와 같은 대표적인 예시가 비동기적 처리의 예시입니다. 

 

3. Promise.. Promise.all.. Async/Await

자바스크립트는 기존에 비동기 작업을 처리할 때 콜백 함수를 많이 사용했었다.

그러나 콜백함수를 중첩해서 사용하다보면 가독성이 떨어지고, 코드가 복잡해진다. 아래의 코드에서도 확인이 가능하다. 

이러한 상황을 콜백 지옥이라고 부른다  = 가독성이 떨어지고, 코드가 복잡한 상황 => 유지보수의 어려움, 인수인계의 어려움을 낳음. 

import React, { useState, useEffect } from "react";

function App() {
  const [post, setPost] = useState(null);
  function doSomething(callback) {
    setTimeout(() => {
      console.log("작업 1 완료");
      callback();
    }, 1000);
  }
 
  function doSomethingElse(callback) {
    setTimeout(() => {
      console.log("작업 2 완료");
      callback();
    }, 1000);
  }
 
  function doThirdThing(callback) {
    setTimeout(() => {
      console.log("작업 3 완료");
      callback();
    }, 1000);
  }
 
  doSomething(() => {
    doSomethingElse(() => {
      doThirdThing(() => {
        console.log("모든 작업 완료");
      });
    });
  });
 
  return <div>
    {post ? <div>{post.title}</div> : <div>Loading...</div>}
    </div>;
}

export default App;

Promise : 비동기 작업이 성공하거나 ,실패했을 때 성공과 실패에 대한 각각의 결과를 처리하는데에 필요.

 

3-1 Promise

Promise는 3가지 상태를 가진다. 

대기 pending 이행되거나 ,거부되지 않을 상태,

이행 fullfilled 비동기 작업이 완료된 상태 resolve으로 인하여 pending에서 fullfilled

거부 Rejected// (1) 컴포넌트가 마운트될 때 fetch를 사용해 데이터를 비동기적으로 가져와요

react에서 데이터를 가져오는 작업은 비동기적으로 이루어지기에 promise가 많이 사용되어 진다. 

// (1) 컴포넌트가 마운트될 때 fetch를 사용해 데이터를 비동기적으로 가져와요
// (2) Promise의 then 메서드를 사용해 데이터를 설정합니다.
// (3) 에러가 발생하면 catch 메서드를 통해 에러를 처리합니다.
import React, { useState, useEffect } from "react";

function App() {
  const [post, setPost] = useState(null);

  useEffect(() => {
      .then((response) => response.json())
      .then((json) => setPost(json))
      .catch((error) => console.error("데이터 펫칭 오류! => ", error));
  }, []);

  return <div>{post ? <div>{post.title}</div> : <div>Loading...</div>}</div>;
}

export default App;

 

여러 비동기 작업을 처리할 때에는  promise.all 메서드가 사용되어 진다. 

// 두 개의 API 호출을 병렬로 처리하는 예제
// 모든 비동기 작업이 완료되면 데이터를 설정합니다.
import React, { useState, useEffect } from "react";

function App() {
  const [data, setData] = useState({ posts: [], users: [] });

  useEffect(() => {
    // 두 개의 처리를 동시에 시작해요.
    Promise.all([
      fetch("https://jsonplaceholder.typicode.com/posts").then((response) =>
        response.json()
      ),
      fetch("https://jsonplaceholder.typicode.com/users").then((response) =>
        response.json()
      ),
    ])
      .then(([posts, users]) => {
        setData({ posts, users });
      })
      .catch((error) => console.error("데이터 펫칭 오류! => ", error));
  }, []);

  return (
    <div>
      <h1>Posts and Users Data</h1>
      <div>
        <h2>Posts</h2>
        {data.posts.length > 0 ? (
          data.posts.map((post) => <div key={post.id}>{post.title}</div>)
        ) : (
          <div>Loading posts...</div>
        )}
      </div>
      <div>
        <h2>Users</h2>
        {data.users.length > 0 ? (
          data.users.map((user) => <div key={user.id}>{user.name}</div>)
        ) : (
          <div>Loading users...</div>
        )}
      </div>
    </div>
  );
}

export default App;

 

3-2 Async , await 

Async, await 구문을 사용하면 비동기 코드를 동기 코드처럼 작성할 수 있어 가독성이 크게 향상이 된다. 

try, catch 구문을 사용하여 비동기 작업에서 발생하는 오류를 간편하게 처리할 수 있다. 

import React, { useState, useEffect } from "react";

function App() {
  const [post, setPost] = useState(null);

  useEffect(() => {
    const fetchPost = async () => {
      try {
        const response = await fetch(
        );
        const data = await response.json();
        setPost(data);
      } catch (error) {
        console.error("Error fetching post:", error);
      }
    };

    fetchPost();
  }, []);

  return <div>{post ? <div>{post.title}</div> : <div>Loading...</div>}</div>;
}

export default App;