OI7MI
[React] API 호출 .then() 대신 async-await 처리 본문
리액트에서 외부 데이터를 가져올 때 보통 fetch를 사용한다
예전에는 .then()을 활용한 체이닝 방식이 많이 쓰였지만
요즘은 가독성과 유지보수 측면에서 async/await 방식이 사실상 표준처럼 사용된다.
then() vs async-await
기존 방식→ .then() 체이닝
.then()을 계속 이어 붙이다 보면 코드가 점점 길어지고 비동기 흐름을 한눈에 파악하기 어려워진다
useEffect(() => {
fetch(`https://yts.mx/api/v2/list_movies.json`)
.then((response) => response.json())
.then((json) => {
setMovies(json.data.movies);
setLoading(false);
});
}, []);
개선된 방식→ async-await
비동기 로직을 별도의 함수로 분리하여 동기 코드(위에서 아래로 실행되는 코드)처럼 보이게 만든다
import { useEffect, useState } from "react";
function App() {
const [loading, setLoading] = useState(true);
const [movies, setMovies] = useState([]);
const getMovies = async () => {
try {
const response = await fetch(
`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`
);
// fetch는 HTTP 에러를 자동으로 throw하지 않기 때문에 직접 체크
if (!response.ok) {
throw new Error("서버 응답 오류");
}
const json = await response.json();
setMovies(json.data.movies);
} catch (error) {
console.error("데이터 로딩 실패:", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getMovies();
}, []);
return (
<div>
{loading ? <h1>Loading...</h1> : (
<ul>
{movies.map((movie) => (
<li key={movie.id}>{movie.title}</li>
))}
</ul>
)}
</div>
);
}
2. 비동기인데 왜 await로 기다릴까?
비동기를 공부하다 보면 이런 의문이 생긴다
“비동기는 안 기다리는 거라면서 왜 await(기다리다)를 쓰는 걸까?”
핵심은 '어디가 멈추느냐'의 차이다
- 전체(브라우저)는 멈추지 않는다 (비동기)
- getMovies 함수가 데이터를 가져오는 동안, 리액트의 다른 기능이나 브라우저의 스크롤, 클릭 이벤트는 멈추지 않고 정상 작동한다. 이것이 비동기 처리의 본질인 'Non-blocking'이다.
- 함수 내부에서는 순서가 필요하다 (await)
- 하지만 getMovies라는 함수 내부에서는 이야기가 다르다. 서버에서 응답(response)이 와야 JSON으로 변환을 하고, 변환이 완료되어야 State를 업데이트할 수 있다.
- await는 "비동기 작업이 완료될 때까지 '이 함수 안에서만' 잠깐 기다려줘"라고 명령하는 것.
💡 정리하자면: 비동기 처리는 사용자가 느끼는 웹사이트 전체의 흐름을 멈추지 않게 하기 위해 사용하고, await는 개발자가 의도한 로직의 순서를 함수 내부에서 보장받기 위해 사용한다.
async-await 사용 시 주의할 점
async 함수는 항상 Promise를 반환한다
그래서 useEffect의 첫 번째 인자로 직접 async () => {}를 넣을 수 없다.
(별도 함수를 만들어 호출해야 함)
// ❌ 잘못된 예
useEffect(async () => {
...
}, []);
// 👉 대신 비동기 함수를 선언한 뒤 호출
useEffect(() => {
getMovies();
}, []);
초기값 설정
movies.map을 사용한다면 초기 상태값을 useState([])처럼 빈 배열로 설정해야 된다
데이터가 오기 전 undefined 에러를 방지할 수 있음 (즉 초기 상태값은 반드시 맞는 타입으로 설정한다)
const [movies, setMovies] = useState([]);
에러 처리
.catch() 대신 → try...catch문이 의미파악과 디버깅에 훨씬 유리할뿐만 아니라 예외 처리가 훨씬 직관적이다
정리
async/await는 비동기 코드를 동기 코드처럼 작성할 수 있게 해주는 자바스크립트의 강력한 문법이다.
이제 복잡한 .then() 체이닝 대신 가독성 좋은 async/await 패턴에 익숙해지면 React에서의 데이터 처리 흐름이 훨씬 명확해진다.
'프론트엔드 > React' 카테고리의 다른 글
| [React] 별점(Star Rating) 라이브러리로 구현하기 (0) | 2026.01.15 |
|---|---|
| [React] 리액트 <Link>와 HTML <a>의 차이점 (feat. CSS가 안 먹히는 이유) (0) | 2026.01.15 |
| [React] useState 상태 업데이트와 배열에서 특정 항목 삭제하기 (0) | 2026.01.09 |
| [React] useEffect() 와 Cleanup 함수 (0) | 2026.01.07 |
| [React] CSS Module 사용 이유와 사용 방법 (1) | 2026.01.06 |