일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 웹개발프로젝트
- 코딩 국비지원
- 와탭랩스
- tempfile
- 엘리스AI트랙데모데이
- fabricjs
- Python
- 코딩교육
- FLASK
- 이미지처리프로젝트
- devmode
- 코딩배우기
- 엘리스AI트랙
- after_this_request
- 엘리스 AI 트랙
- REACT
- 블로그와 친해지기
- 개발자 채용설명회
- 엘리스
- aws_s3
- 웹개발포트폴리오
- 코딩부트캠프
- 팀프로젝트
- reactStrictMode
- 코딩국비지원
- 프레임워크vs라이브러리
- 프로젝트마무리
- pymupdf
- 부트캠프프로젝트발표
- 인공지능모델학습
Archives
- Today
- Total
자몽이 조아
try catch finally 는 항상 비동기를 기다리지 않는다 본문
반응형
개요
JavaScript의 try...catch...finally 구문을 사용할 때, finally 블록이 항상 비동기 코드가 끝날 때 실행된다고 착각하는 경우가 많다. 하지만 finally 블록은 try가 종료되면 즉시 실행되며, 내부의 비동기 코드가 완료되길 기다리지 않는다. 이를 이해하지 못하면 로딩 상태 관리나 비동기 작업의 순서를 제어하는 데에서 문제가 발생할 수 있다.
문제 상황
아래의 슈도코드를 살펴보자. 이 코드는 네트워크 요청을 수행한 후, 데이터를 다운로드하는 동안 로딩 상태를 표시하려는 의도로 작성되었다.
function downloadFile() {
setLoading(true); // 로딩 시작
try {
fetchDataFromServer() // 비동기 요청
.then((response) => response.blob())
.then((blob) => {
const url = createDownloadUrl(blob);
triggerDownload(url, "output.pdf");
})
.catch(handleError);
} finally {
setLoading(false); // 로딩 종료
}
}
이 코드를 실행하면 예상과 달리 로딩 상태가 즉시 false로 바뀌어 버린다. 왜 그럴까?
원인 분석
- fetchDataFromServer()는 비동기 함수이므로 즉시 실행되지 않고, 프로미스를 반환한다.
- 하지만 try 블록이 실행된 후 바로 finally 블록이 실행된다.
- finally 블록은 fetchDataFromServer()의 비동기 완료 여부와 상관없이 실행되므로, 로딩 상태가 너무 일찍 false로 변경된다.
해결 방법
이 문제를 해결하려면, finally 블록 대신 .finally() 메서드를 사용해야 한다.
function downloadFile() {
setLoading(true);
fetchDataFromServer()
.then((response) => response.blob())
.then((blob) => {
const url = createDownloadUrl(blob);
triggerDownload(url, "output.pdf");
})
.catch(handleError)
.finally(() => setLoading(false)); // 비동기 완료 후 실행
}
또한, async/await을 사용하여 보다 가독성이 좋은 방식으로 작성할 수도 있다.
async function exportPDF() {
setLoading(true); // 로딩 시작
try {
const response = await fetchDataFromServer();
const blob = await response.blob();
const url = createDownloadUrl(blob);
triggerDownload(url, "output.pdf");
} catch (error) {
logError("Download failed", error);
} finally {
setLoading(false); // 로딩 종료
}
}
두 함수는 같은 기능을 수행하지만, then/catch 방식과 async/await 방식을 각각 활용하여 다른 형태로 구현할 수 있다. 상황에 따라 적절한 방식을 선택하는 것이 중요하다.
결론
- try...catch...finally는 동기 코드에서는 정상적으로 작동하지만, 내부의 비동기 코드가 완료되기 전에 finally가 실행될 수 있다.
- 비동기 작업이 끝난 후 특정 작업을 실행하려면 .finally()를 사용해야 한다.
- async/await을 활용하면 더 명확한 흐름을 만들 수 있다.
- try...catch...finally는 비동기 작업의 성공/실패 여부와 무관하게 항상 실행되지만, 프로미스 체인을 기다리지 않는다.
- 같은 기능을 수행하는 코드라도 then/catch와 async/await의 형태로 다르게 표현할 수 있다.
이러한 동작을 이해하고 코드를 작성하면, 비동기 흐름을 더욱 효과적으로 관리할 수 있다.
반응형
'개발공부 > Javascript' 카테고리의 다른 글
ECMAScript 6 (0) | 2021.12.28 |
---|---|
DOM 이란? (0) | 2021.12.28 |
Javascript Pattern (0) | 2021.12.28 |
번들링(Bundling) (0) | 2021.12.28 |
Comments