taeridad19 님의 블로그 입니다.

  • 2025. 4. 12.

    by. taeridad19

    목차

       

      자바스크립트 비동기 처리: 콜백, 프로미스, 그리고 async/await

      비동기 처리란 무엇인가?

      **비동기 처리(Asynchronous Processing)**란, 코드가 실행되는 동안 다른 작업을 기다리지 않고 동시에 처리할 수 있도록 하는 방식입니다.
      자바스크립트(JavaScript)는 기본적으로 싱글 스레드(Single Thread) 환경이기 때문에, 비동기 로직이 필수적입니다.

      예를 들어, 사용자의 버튼 클릭, 서버에서 데이터 받아오기(AJAX), 파일 읽기, 타이머 설정 등은 시간이 오래 걸릴 수 있으므로 비동기 방식으로 처리해야 UI가 멈추지 않고 부드럽게 동작합니다.


      콜백 함수 (Callback Function)

      콜백 함수란?

      콜백 함수는 어떤 함수에 인수로 전달되어 특정 시점에 호출되는 함수입니다. 비동기 작업이 완료되었을 때 실행되도록 예약할 수 있습니다.

      예제:

      function fetchData(callback) {
        setTimeout(() => {
          console.log("데이터를 가져왔습니다!");
          callback();
        }, 1000);
      }
      
      fetchData(() => {
        console.log("콜백 실행 완료!");
      });
      

      단점: 콜백 지옥

      콜백을 중첩해서 사용하다 보면 다음과 같이 **“콜백 지옥(Callback Hell)”**에 빠지기 쉽습니다.

      login(user, () => {
        getProfile(user, () => {
          getPosts(user, () => {
            showFeed();
          });
        });
      });
      

      코드가 가독성이 떨어지고 유지보수가 어려워지는 문제가 발생합니다.


      프로미스(Promise)

      프로미스란?

      **프로미스(Promise)**는 비동기 작업의 성공(resolve) 또는 실패(reject)를 처리하는 객체입니다. 콜백보다 구조화된 에러 처리연결된 체이닝이 가능해 보다 직관적인 코드 작성이 가능합니다.

      기본 구조:

      const promise = new Promise((resolve, reject) => {
        // 비동기 작업
        if (성공) {
          resolve(결과값);
        } else {
          reject(에러);
        }
      });
      

      예제:

      function fetchData() {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve("데이터를 성공적으로 불러왔습니다!");
          }, 1000);
        });
      }
      
      fetchData()
        .then(data => {
          console.log(data);
        })
        .catch(err => {
          console.error(err);
        });
      

      장점:

      • 가독성 향상
      • 체이닝 가능 (.then().then())
      • 에러를 .catch()로 관리 가능

      async/await

      async/await란?

      async/await는 프로미스를 기반으로 만들어진 비동기 처리 문법의 최신 방식입니다.
      async 키워드가 붙은 함수 내부에서 await를 사용하면, 해당 작업이 완료될 때까지 기다렸다가 다음 줄을 실행합니다.

      사용 예:

      async function loadData() {
        try {
          const data = await fetchData();  // Promise가 반환되어야 함
          console.log(data);
        } catch (err) {
          console.error("에러 발생:", err);
        }
      }
      

      특징:

      • 마치 동기식 코드처럼 읽기 쉽고 직관적
      • try/catch로 에러를 처리할 수 있음
      • await는 반드시 async 함수 안에서만 사용 가능

      세 가지 방식 비교

      항목  콜백 함수  프로미스(Promise) async/await
      가독성 낮음 (콜백 지옥 발생) 중간 (체이닝 가능) 높음 (동기식처럼 작성)
      에러 처리 try-catch 어려움 .catch() 사용 가능 try-catch 사용 가능
      디버깅 편의성 어려움 중간 좋음
      코드 길이 길어짐 줄어듦 가장 짧음

      실전 예제: API 호출 시 async/await 활용하기

      async function getUserInfo() {
        try {
          const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
          const data = await response.json();
          console.log("유저 정보:", data);
        } catch (error) {
          console.error("에러 발생:", error);
        }
      }
      
      getUserInfo();
      

      이렇게 작성하면 비동기 요청이 마치 동기 방식처럼 순차적이고 가독성 있게 처리됩니다.


      결론: 어떤 방식이 가장 좋을까?

      • 콜백 함수는 단순한 작업에는 빠르지만 복잡해지면 지옥을 경험할 수 있음
      • 프로미스는 체이닝을 통한 작업 순서 제어가 가능함
      • async/await는 가장 최신 방식으로, 가독성과 유지보수성이 가장 뛰어남

      현재는 대부분의 프로젝트에서 async/await을 표준으로 채택하고 있습니다. 하지만 모든 방식의 구조를 이해하고 있어야 다양한 상황에 유연하게 대응할 수 있습니다.