비동기, 그것은 무엇인가?

Kingdwan·2025년 4월 24일

💬 왜 이 글을 쓰게 되었나

프론트엔드 개발을 하다 보면 자주 접하는 단어, "비동기".

어느 날 문득 생각했다.

"비동기가 대체 정확히 뭘까? 왜 이렇게 다양하게 처리 방식이 존재할까?"

이번 포스트에서는 비동기의 기본 개념부터, 콜백 → then → async/await → try/catch 그리고 React Query에서의 현대적 비동기 처리 방식까지 순차적으로 정리해보려 한다.



🔍 비동기란?

동기(Synchronous): 한 작업이 끝나야 다음 작업으로 넘어감


비동기(Asynchronous): 다음 작업이 먼저 시작될 수 있음. 응답이 오면 그때 결과 처리

📌 "응답 시간이 예측 불가능한 작업"이 비동기의 본질

예: 서버 API 호출, 파일 읽기, setTimeout 등



🧵 비동기의 첫 단추 – 콜백 함수


getData((result) => {
  console.log("데이터:", result);
});

  • 결과를 받으면 콜백 함수에 전달해서 실행

  • 문제: 중첩이 생기면 가독성이 떨어짐 → "콜백 지옥(callback hell)" 발생

// 콜백 지옥 예시 코드

getUser(userId, (user) => {
  getPosts(user.id, (posts) => {
    getComments(posts[0].id, (comments) => {
      getLikes(comments[0].id, (likes) => {
        console.log("최종 결과:", {
          user,
          posts,
          comments,
          likes
        });
      });
    });
  });
});



🔁 콜백 지옥을 벗어나기 위한 then



fetchUser()  // 사용자 정보 가져오기 → user
  .then((user) => fetchPosts(user.id)) // 그 user.id로 게시물 가져오기 → posts
  .then((posts) => fetchComments(posts[0].id)) // 첫 번째 게시물의 id로 댓글 가져오기 → comments
  .then((comments) => console.log(comments)); // comments를 콘솔에 출력

  • Promise 기반 .then() 체이닝
  • 문제 해결: 중첩 제거 → 수직적 코드
  • 단점: 흐름 제어 어려움, 예외처리 분산 (.catch())


✨ async/await의 등장 – 동기처럼 보이는 비동기


async function loadData() {
  const user = await fetchUser();
  const posts = await fetchPosts(user.id);
  const comments = await fetchComments(posts[0].id);
  console.log(comments);
}

  • await → 마치 동기 코드처럼 읽힘
  • 가독성 ↑, 에러 핸들링도 try/catch로 자연스럽게


🔐 예외 처리는 try / catch


try {
  const res = await fetchData();
  console.log(res);
} catch (e) {
  console.error("문제 발생", e);
}

  • 직접 호출하는 비동기 함수에는 try/catch가 필수
  • 사용자에게 에러 메시지 띄우기, fallback 처리, 로깅 등 다양하게 활용 가능


🤔 그런데, React Query에서는 try/catch 안 써도 되던데?

React Query는 내부적으로 이미 try/catch 구조로 요청을 감싸고 있다.


const { data, isError, error } = useQuery(['data'], fetchData, {
  onSuccess: () => toast.success("성공!"),
  onError: () => toast.error("실패!"),
});

✅ 즉, React Query의 onError, isError는 try/catch를 선언적으로 대체한 구조!



🧭 언제 try/catch를 직접 쓰고, 언제 React Query를 쓰면 될까?


상황처리 방식
여러 API를 순차 실행async/await + try/catch
UI 상태 기반 자동 fetchReact Query 권장
재사용 가능한 API 함수try/catch 없이 순수 반환
사용자 메시지, 리디렉션 등 UX 연계React Query의 onError, onSuccess 활용


🧩 마무리하며 – 지금, 나는 어떻게 비동기를 다루는가?

프론트엔드 개발자라면 비동기 처리는 떼려야 뗄 수 없는 친구다. 우리는 이 친구를
콜백으로 처음 만나고, then으로 정리해보고, async/await로 길들이고, 이제는 React Query 같은 툴에게 안심하고 맡길 수 있게 되었다.

“비동기란, 제어에서 관찰로의 전환이다.”

비동기는 흐름을 제어하는 기술이 아니라, 흐름을 다루는 태도다.

0개의 댓글