ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript/TypeScript의 async 이해하기
    typescript 2024. 12. 11. 00:38

    typescript async 예제

    1. 'async' 사전적 의미

    async는 “asynchronous(비동기적인)“의 약어다. 프로그래밍에서 이 용어는 “한꺼번에 일어나지 않는” 상황을 다룰 때 사용된다.

    어원을 살펴보면:

    • a-: 부정을 나타내는 접두사 (“~이 아니다”)

    • syn-: “같이”를 뜻하는 어근

    • chronos: “시간”을 뜻하는 어근

    → 즉, “같은 시간에 일어나지 않는다”는 의미를 담고 있다.


    2. 동기 vs 비동기

    - 동기적(Synchronous) 동작

    동기적인 동작은 작업이 순서대로 실행되고, 하나가 끝나야 다음 작업이 시작된다. 비유를 들어 설명하자면 라면 끓이기 과정과 비슷하다.

    1.  물을 끓인다 (3분 대기)
    2.  면을 넣는다
    3.  스프를 넣는다

    위 과정에서 물이 끓는 동안 우리는 멍하니 기다릴 수밖에 없다.

     

    - 비동기적(Asynchronous) 동작

    비동기적인 동작은 여러 작업을 동시에 처리하거나, 시간이 오래 걸리는 작업을 기다리는 동안 다른 작업을 할 수 있다. 이를 식당에서 주문을 처리하는 상황으로 비유할 수 있다.

    async function 주문처리() {
    
        const 주문1 = 라면준비();  // 라면 조리 시작_
    
        const 주문2 = 김밥준비();  // 김밥 준비 시작_
    
        await 주문1;  // 라면 완성될 때까지 기다림_
    
        await 주문2;  // 김밥 완성될 때까지 기다림_
    
        console.log("모든 주문 완료!");
    
    }

    위 코드는 라면과 김밥을 동시에 준비시키고, 각각의 완료를 기다린 후에 최종 메시지를 출력한다. 비동기 처리를 통해 시간과 효율을 극대화할 수 있는 것이다.


    3. JavaScript와 다른 언어의 차이

    JavaScript의 비동기 처리 방식

    JavaScript는 단일 스레드(single-threaded) 언어다. 즉, 한 번에 하나의 작업만 처리할 수 있다. 그럼에도 웹 브라우저와 같은 환경에서는 사용자 인터페이스(UI)가 멈추지 않도록 비동기 처리를 지원한다. 이를 가능하게 하는 핵심은 이벤트 루프(event loop)다.

    다른 언어와 비교

    다른 언어들은 JavaScript와는 접근 방식이 다르다. 예를 들어 Java나 Python은 멀티스레드나 멀티프로세스를 활용해 진정한 병렬 처리를 수행한다.

     

    - Java의 멀티스레드

    new Thread(() -> {
    
        // 오래 걸리는 작업
    
    }).start();

     

    - Python의 멀티스레드

    import threading
    
    thread = threading.Thread(target=long\_running\_task)
    
    thread.start()

     

    - C#의 비동기 처리

    await Task.Run(() => {
    
        // 오래 걸리는 작업
    
    });

    주요 차이점

    • JavaScript는 단일 스레드에서 비동기 작업을 수행하므로 실제로 병렬로 실행되는 것은 아니다.

    • Java, Python, C# 등은 멀티스레드/멀티프로세스를 통해 실제로 여러 작업을 동시에 실행할 수 있다.

    • JavaScript는 이벤트 루프와 비동기 API(Fetch, Timer 등)를 활용해 마치 병렬로 실행되는 것처럼 보이게 만든다.


    4. 실제 사용 예시

    JavaScript/TypeScript에서 비동기 코드를 작성할 때 가장 흔히 사용되는 예는 데이터 로드 작업이다. 다음 코드를 보자.

    async function loadData() {
    
        const response = await fetch('[https://api.example.com/data'](https://api.example.com/data'));  // 네트워크 요청
    
        const data = await response.json();                           // 데이터 파싱
    
        return data;
    
    }

    이 코드는 다음과 같은 특징을 가진다:

    1.  데이터가 로드될 때까지 기다리는 동안에도 UI는 계속 작동한다.
    2.  사용자는 애니메이션을 보거나 버튼을 클릭하는 등의 작업을 할 수 있다.
    3.  애플리케이션 전체가 멈추는 일이 없다.

    5. 코드에 설탕같은 존재 async

    일반적으로 비동기 작업을 처리할 때 JavaScript에서는 Promise를 사용한다. 하지만 Promise만 사용한 코드는 다소 복잡해 보일 수 있다. 특히, .then() 메서드를 체인처럼 연결해야 하기 때문에 코드가 길어질수록 가독성이 떨어지는 문제가 있다.

    • Promise 기반 코드의 예
      fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => {
        console.log(data);
      })
      .catch(error => {
        console.error(error);
      });
      위 코드는 데이터를 가져오고, JSON으로 파싱한 다음, 결과를 출력한다. 하지만 .then()이 중첩되면서 코드가 복잡해질 수 있고, 가독성도 떨어진다.

    async/await는 이러한 문제를 해결하기 위해 등장했다. 이 기능을 사용하면 Promise를 기반으로 한 코드를 마치 순차적으로 실행되는 동기 코드처럼 작성할 수 있다.

    • async/await로 바꾼 코드의 예
      async function loadData() {
      try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error(error);
      }
      }
      이 코드는 겉으로 보기에는 동기적으로 한 줄씩 실행되는 것처럼 보인다. 하지만 실제로는 fetch와 같은 비동기 작업을 Promise로 처리하고, await 키워드로 그 완료를 기다린다. 즉, 내부적으로는 여전히 Promise 기반으로 동작하지만, 개발자가 코드를 작성할 때는 더 간결하고 직관적으로 쓸 수 있도록 도와주는 것이다.

    이를 비유하자면, Promise는 원재료이고, async/await는 이를 조리해서 먹기 좋은 형태로 만들어 주는 요리도구라고 할 수 있다. 핵심 로직은 같지만, async/await 덕분에 개발자가 더 쉽게 다룰 수 있도록 “포장”된 셈이다.

    결론적으로, async/await는 프로그래머가 비동기 작업을 동기 작업처럼 다룰 수 있도록 도와주는 문법적 설탕(syntactic sugar)이다. 하지만 그 속에는 여전히 JavaScript의 비동기 처리 방식인 Promise가 작동하고 있다.

    'typescript' 카테고리의 다른 글

    Phaser Tween Chain 가이드  (0) 2025.02.15
Designed by Tistory.