리액트
리액트 - Async&Await&Promise
개발자 포비
2024. 12. 23. 22:59
Async/Await/Promise 정리
1. 기본 개념
Promise
- 비동기 작업의 결과를 담는 객체
- 상태: pending(대기) -> fulfilled(성공) 또는 rejected(실패)
- 체이닝으로 연속 작업 가능
async/await
- async: Promise를 반환하는 비동기 함수 선언
- await: Promise 완료까지 대기
- try-catch로 에러 처리
2. 실행 패턴
순차 실행
- await로 순서 보장이 필요한 작업 처리
- 예) 질문 조회 후 답변 목록 조회
병렬 실행
- Promise.all()로 독립적인 작업 동시 실행
- 예) 프로필과 작성 글 목록 동시 조회
혼합 실행
- 순차 실행과 병렬 실행 조합
- 예) 질문 조회 후 답변/댓글 동시 조회
3. Promise 메서드
기본 메서드
.then()
- 성공 처리.catch()
- 에러 처리.finally()
- 완료 처리
정적 메서드
Promise.all()
- 모든 Promise 완료 대기Promise.race()
- 가장 빠른 Promise 완료 대기Promise.allSettled()
- 성공/실패 무관 완료 대기
4. 에러 처리
async/await 방식
try {
await 비동기작업();
} catch (error) {
에러처리();
}
Promise 방식
비동기작업()
.then(성공처리)
.catch(에러처리)
5. 주의사항
- useEffect에서는 내부 async 함수 선언 후 호출
- 조건부 실행 시 early return 활용
- 불필요한 중첩 피하기
6. 선택 기준
async/await 선택
- 복잡한 비동기 로직
- 명확한 에러 처리 필요
- 순차 실행이 많은 경우
Promise 체이닝 선택
- 단순한 연속 작업
- 함수형 프로그래밍 스타일
- 메서드 체이닝이 자연스러운 경우
7. 실제 사용 예시 통합 코드
const ExampleComponent = () => {
const [data, setData] = useState({ profile: null, questions: [], answers: [] });
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// 1. 순차 실행 예시 (답변 작성 후 댓글 조회)
const handleAnswer = async (answerId, content) => {
try {
const response = await api.post(`/api/v1/answers/${answerId}`, { content });
const comments = await api.get(`/api/v1/answers/${response.data.id}/comments`);
return { answer: response.data, comments: comments.data };
} catch (error) {
throw new Error('답변 작성 중 오류가 발생했습니다.');
}
};
// 2. 병렬 실행 예시 (프로필과 활동 내역 동시 조회)
const loadUserData = async (userId) => {
try {
const [profile, questions, answers] = await Promise.all([
api.get(`/api/v1/users/${userId}/profile`),
api.get(`/api/v1/users/${userId}/questions`),
api.get(`/api/v1/users/${userId}/answers`)
]);
setData({
profile: profile.data,
questions: questions.data,
answers: answers.data
});
} catch (error) {
setError('사용자 데이터를 불러오는데 실패했습니다.');
}
};
// useEffect 사용 예시
useEffect(() => {
const init = async () => {
setLoading(true);
try {
await loadUserData(userId);
} catch (error) {
setError(error.message);
} finally {
setLoading(false);
}
};
init();
}, [userId]);
if (loading) return <div>로딩중...</div>;
if (error) return <div>{error}</div>;
return (
<div>
{/* 컴포넌트 렌더링 로직 */}
</div>
);
};
export default ExampleComponent;