Promise
- 자바스크립트에서 비동기 연산의 결과를 대표하는 객체
- 비동기 작업이 완료되고 나서 결과를 처리하기 위해 사용
- 비동기 연산이니까 결과값 받을때까지 기다리기로 '약속'한 것 이라고 생각하면 됨
promise의 상태
- Pending(대기중) : 초기의 상태, 성공도 실패도 아닌 상태
- Fulfilled(이행됨) : 연산이 성공적으로 완료됨
- Rejected(거부됨) : 연산이 실패함
promise의 메소드
- .then() : 결과값을 성공적으로 반환받았을 경우 실행 (Fulfilled 됐을 때)
- .catch() : 오류 발생시 처리 (Rejected 됐을 때)
- .finally() : 비동기 연산이 처리되었을 경우 성공, 실패 관계 없이 실행, 주로 정리(clean-up)작업이나 로딩 표시를 숨기는 용도
promise 사용 예제
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
myAsyncFunction('https://example.com')
.then(response => console.log(response))
.catch(error => console.error(error))
.finally(() => console.log('완료'));
Callback
- 다른 함수에 인수로 전달되는 함수
- 비동기 연산이 완료된 후 실행되어야 하는 작업을 정의할 때 사용
- 자바스크립트에선 특히 이벤트 처리나 비동기 API에서 널리 사용
Callback hell(콜백 지옥)
- 중첩된 callback으로 인해 코드가 복잡해지는 문제
- 코드의 가독성과 유지보수성이 떨어짐
Callback hell 해결 방법
- Promise 사용
- Promise를 사용하여 비동기 작업을 처리하면 콜백 지옥을 피할 수 있음
- .then()과 .catch() 메소드를 사용하여 성공과 오류 관리
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
- Async/Await 사용
- async, await을 사용하여 비동기 코드를 동기 코드처럼 보이게 만들어 줌
- async 키워드로 함수를 감싸고 await 키워드로 비동기 작업의 결과를 기다림
- 해당 방법은 코드의 가독성을 크게 향상시킬 수 있음
async function asyncFunction() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log(`Got the final result: ${finalResult}`);
} catch (error) {
failureCallback(error);
}
}
- 모듈화
- 복잡한 콜백을 작은 함수로 분리
- 각 함수는 하나의 작업만 수행하며 이를 조합하여 사용
- 코드의 재사용성, 테스트 용이성이 향상
- 라이브러리 및 프레임워크 사용
- Bluebird나 Q와 같은 promise 라이브러리를 사용하여 콜백 지옥 해결 가능
- 이러한 라이브러리는 promise API를 확장하고 추가적인 기능 제공
- 콜백을 명확하게 관리하기
- 콜백 함수를 명확하게 정의하고 문서화하여 사용
- 가능한 콜백 함수의 중첩을 피하고 각 콜백의 목적을 명확히 해야 함
Promise와 Callback의 관계
- Promise를 사용하면 비동기 작업의 성공, 실패, 완료에 대한 Callback 함수들을 체인 형태로 구성할 수 있어 코드의 관리가 용이해짐
- 또한 사용자가 직접 Callback 함수를 관리할 필요 없이 promise의 여러 메소드를 활용해 관리하기 때문에 코드의 구조가 훨씬 명확하고 간결해짐
추가 - promise를 활용한 비동기 통신과 Async, Await을 사용한 비동기 통신의 차이점
| Promise 활용 | Async, Await 사용 |
|---|
| 구조 | then, catch, finally와 같은 메서드 활용 | Async로 함수를 감싸고 Await으로 비동기 작업의 결과값을 기다리는 구조 |
| 가독성 | promise체인은 때때로 복잡해질 수 있음 | 동기적 방식으로 작성되어 가독성이 좋음, 코드의 흐름이 명확해짐 |
| 오류 처리 | .catch() 메소드를 활용 | try...catch 문을 활용 |
| 유연성 | 다양한 비동기 작업을 조합하고 여러 비동기 작업을 병렬로 처리하는 등의 복잡한 시나리오에서 유용 | 코드의 직관성과 가독성이 중요할때 유용 |