0. 동기
- 동기적 처리 (Synchronous)
- 순차적 실행
- 서버에 요청을 보냈을 때 응답이 돌아온 뒤 다음 동작을 수행
- A 작업이 모두 진행되어 마칠 때까지 B 작업은 대기
ex.
console.log('first');
console.log('second');
console.log('third');
/*
first
second
third
*/
위와 같이 코드를 작성한 뒤 실행되는 결과를 확인해 보면
위에서부터 한 줄씩 내려오며
하나의 작업이 완전히 끝난 뒤 다음 코드가 차례로 실행되는 것을 확인할 수 있다.
이를 동기적 처리 방식이라고 한다.
1. 비동기
- 비동기적 처리 (Asynchronous)
- 서버에 요청을 보냈을 때 응답 상태와 관계 없이 다음 동작 수행 가능
- A 작업이 시작되면 동시에 B 작업 실행 시작
- 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성
ex.
console.log('first');
setTimeout(() => {
console.log('second');
}, 1000);
console.log('third');
/*
first
third
second
*/
위 코드에서는 간단한 비동기 처리 방식의 순서를 확인하기 위해 setTimeout 함수를 사용했다.
setTimeout 함수의 첫 번째 인자는 콜백 함수, 두 번째 인자는 지연 시간으로 0을 주었다.
코드가 동작하는 과정을 한 줄 한 줄 보면,
- console.log('first');를 만나 콘솔에 first를 찍는다.
- setTimeout() 메소드를 만나 이 메서드를 처리하는 다른 프로그램에 전송한다.
- console.log('third'); 줄로 이동해 콘솔에 third를 찍는다.
- setTimeout() 메소드를 처리하는 프로그램은 비동기를 제외한 모든 동기적 코드가 실행된 뒤 결과를 콘솔에 찍는다.
이렇게 무작정 위에서부터 한줄씩 읽으며 찍는 것이 아니라는 것을 확인할 수 있다.
2. JS에서 비동기 코드를 처리하기 위한 방법
2.1 Callback 함수
- JS에서는 함수를 인자로 받고 다른 함수를 통해 반환되는 것이 가능한데, 이때 인자로 대입되는 함수
- 다른 함수가 실행이 끝난 뒤 실행되는 함수
- 함수를 선언할 때, 인자로 함수를 받아서 사용 가능
- 비동기 방식으로 작성된 함수를 동기 방식처럼 순서대로 실행할 수 있도록 만들 수 있다.
(하지만, 코드는 여전히 비동기적으로 동작)
function mainFunc(param1, param2, callbackFunc) {
// ... 처리 내용 작성
callbackFunc(result);
}
기본적인 콜백 함수의 형태이다.
보통 함수를 선언한 뒤 함수 타입 파라미터를 가장 마지막에 하나 더 선언해 주는 방식으로 정의한다.
동기 방식으로 작성된 코드의 처리가 끝나면 파라미터로 전달 받은 함수를 실행한다.
( + 필요한 경우 결과 값을 인자로 넘겨줄 수도 있음 )
★ 콜백 지옥 ( Callback Hell )
- 비동기 프로그래밍 시 발생 가능성 있는 문제
- 콜백 함수를 익명 함수로 전달하는 과정에서 또 다시 콜백 안에 함수 호출이 반복
▶ 코드의 들여쓰기가 너무 깊어지는 현상 - 가독성이 낮아지는 동시에 코드 수정 난이도가 높아짐
2.2 Promise
- 비동기 함수를 동기적으로 처리하기 위해 만들어진 객체
- 성공 / 실패를 분리하여 반환
- 비동기 작업이 완료된 뒤, 다음 작업을 연결시켜 진행할 수 있음
- 최종 결과를 반환하는 것 X ▶ 미래의 어떤 시점에 결과를 제공하겠다는 '약속'을 반환
★ promise의 상태
- Pending (대기) : Promise를 이행하지도, 거부하지도 않은 초기 상태 / 수행하지 않은 상태
- Fulfilled (이행) : Promise가 Resolve (성공) 된 상태
- Rejected (거부) : Promise가 지켜지지 못한 / Reject (실패) 된 상태
- Settled : Fulfilled 혹은 Rejected로 결론이 난 상태
★ Promise Chaining (프로미스 체이닝)
- 프로미스 체이닝은 코드를 더 효율적으로 짜기 위해 사용됨
- 비동기 코드를 매우 간단하게 정리할 수 있음
- then 메서드를 연속적으로 사용하여 순차적인 작업이 가능
- 여러 개의 프로미스 체인 중 하나라도 rejected 상태가 되면 가장 마지막에 달린 catch 문으로 이동하여 에러를 처리
▶ 나머지 프로미스를 하나하나 차례로 확인하는 불필요한 작업 X
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
위 코드의 실행 순서를 보면,
- 1초 뒤 첫 번째 프로미스 함수가 실행 // (*) 부분
- 첫 번째 .then 핸들러 호출 // (**) 부분
- 2에서 반환한 값은 다음, then 핸들러로 전달 // (***) 부분
- 더 있는 경우 이러한 과정 반복
result 값은 alert 창에 1, 2, 4가 차례로 출력됨.
2.3 Async Await
- 가장 최근에 나온 방법
- promise chaining을 하다보면 then 함수가 많아져 꼬리를 물게 되어 코드의 가독성 저하 가능
- 보다 직관적인 코드
- 따로 새로운 기능 추가 된 것 X ▶ promise를 다르게 사용하는 것
async | await |
function 앞에 위치 | 프로미스 앞에 위치 |
프로미스가 아닌 값을 반환해도 이행 상태의 프로미스로 값을 감싸서 해당 프로미스 반환 | 프로미스가 모두 실행되어 처리될 때까지 대기 |
비동기로 실행되는 것이 있음을 알림 | 프로미스가 모두 처리되면 결과를 마지막에 반환 |
async가 붙은 함수는 항상 promise 반환 | await는 async 함수 안에서만 동작 |
728x90
'JavaScript' 카테고리의 다른 글
[JS] 프로그래머스 코딩테스트 - 옹알이(1) (0) | 2023.12.02 |
---|---|
[MongooseError] Mongoose.prototype.connect() no longer accepts a callback 에러 (0) | 2023.10.02 |
[JS] JS와 JQuery 코드 비교 (0) | 2023.08.03 |
[JS] JavaScript DOM이란? (0) | 2023.07.31 |
[JS] JS에서 함수(function)란? (0) | 2023.07.26 |