동기와 비동기는 무엇인가?

Ma_Seokjae·2024년 1월 23일
1
post-thumbnail

React를 사용한 웹 사이트 개발 프로젝트를 진행하면서 동기, 비동기 작업 처리가 중요한 역할을 담당한다고 느끼는 일이 많았는데, 무작정 사용하는 것이 아닌 개념을 좀 더 분명하게 알고 사용하고 싶어 정리를 해보려고 합니다.


동기 (Synchronous)?

작업이 순차적으로 실행되는 것을 의미
즉, 한 가지 작업이 끝나야 다음 작업이 시작

  • 이전 작업이 끝나기 전에는 다음 작업이 시작되지 않음
  • 작업의 진행 상황을 예측하기 쉬움

[예제]

console.log('1');
console.log('2');
console.log('3');

동기, [예제] 설명

  • 콘솔에 1, 2, 3이 차례대로 출력
  • 한 번에 하나의 작업만 수행

유의할 점

  • 블로킹 (Blocking):
    동기 코드는 한번에 하나의 작업만 수행, 한 작업이 끝나기 전까지 다음 작업이 기다려야 함. 이런 특성 때문에 시간이 오래 걸리는 작업이 있을 경우 전체 코드의 실행이 멈추게 되는데, 이를 블로킹이라고 함
  • 순서:
    작성된 순서대로 실행 됨. 이는 코드의 흐름을 이해하고 예측하기 쉽게 해주지만, 동시에 여러 작업을 처리할 수 없다는 단점 존재
  • 오류 처리:
    try-catch 문을 사용하여 오류를 쉽게 처리

비동기 (Asynchronous)?

동시에 여러 작업이 실행될 수 있는 것을 의미

  • 작업의 순서가 보장되지 않음
  • 작업의 진행 상황을 예측하기 어려움

javascript에서는 asyncawait를 통해 비동기 작업을 다룸

  • async는 함수 앞에 사용되며, 이 함수는 항상 Promise를 반환
  • await는 async 함수 내부에서 사용되며, Promise의 완료를 기다림

[예제]

async function exFunc() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  console.log(data);
}

exFunc();

비동기, [예제] 설명

  • exFuncasync 함수이며, fetch 함수를 호출하여 비동기적으로 데이터를 불러옴
  • await 키워드를 사용해서 fetch 함수의 완료를 기다림
  • response.json() 메서드를 호출해서 비동기적으로 데이터를 JSON 형식으로 변환
  • response.json() 또한, await 키워드를 사용하여 이 작업의 완료를 기다림

유의할 점

  • 논블로킹 (Non-Blocking):
    비동기 코드는 한 작업이 끝나기를 기다리지 않고 바로 다음 작업으로 넘어갈 수 있음. 이는 시간이 오래 걸리는 작업을 백그라운드에서 처리하면서도 메인 스레드가 멈추지 않고 계속 다른 작업을 수행할 수 있게 해 줌
  • 콜백, 프로미스, async/await:
    이들 각각은 비동기 작업의 결과를 처리하는 방식에 차이가 있으며, 올바르게 이해하고 사용하는 것이 중요
  • 상태 관리:
    작업이 완료되기까지 시간이 필요하므로, 비동기 작업의 상태 (예: 로딩 완료, 오류 등)를 올바르게 관리하는 것이 중요
  • 순서 보장:
    작성된 순서대로 실행되지 않기 때문에 예상치 못한 결과가 발생할 수 있으므로, 필요한 경우 비동기 작업의 순서를 보장하기 위한 추가적인 로직이 필요

여기서 궁금한 점!

Q: 비동기 프로그래밍에서 순서 보장을 처리할 바에 그냥 동기적 프로그래밍을 사용하면 되지 않나요?
A: 그렇게 생각할 수 있지만, 비동기 프로그래밍이 가진 장점을 유지하면서 특정 순서를 보장하는 방법이 필요하므로 비동기적 요소에서 순서를 보장하는 경우가 많습니다.
예를 들어, 데이터를 활용해 UI를 업데이트하는 경우에 데이터 로딩 작업이 완료되지 않은 상태에서 UI 업데이트 작업을 시작하면 문제가 발생할 수 있기 때문에, 이런 경우 비동기 작업의 순서를 보장해야 합니다.

비동기 프로그래밍, 순서 보장을 위한 방법 예시

  1. Promise 사용

    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('첫 번째 작업 완료');
      }, 3000);
    });
    
    let promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('두 번째 작업 완료');
      }, 2000);
    });
    
    promise1.then((result1) => {
      console.log(result1); 
      return promise2;
    }).then((result2) => {
      console.log(result2);
    });
    • 위 코드에서는 promise1이 먼저 실행되고, promise1이 완료된 후에 promise2가 실행 됨. 즉, 비동기 작업의 순서를 보장
  2. async/await 사용

    async function asyncFunction() {
      let promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('첫 번째 작업 완료');
        }, 3000);
      });
    
      let promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('두 번째 작업 완료');
        }, 2000);
      });
    
      console.log(await promise1);
      console.log(await promise2);
    }
    
    asyncFunction();
    
    • 이 코드에서도 promise1이 먼저 완료된 후, promise2가 실행되기 때문에 비동기 작업의 순서가 보장
profile
Why not change the code?

0개의 댓글

관련 채용 정보