자바스크립트는 기본적으로 동기식 처리 (Synchronous)
동기식 처리란 한번에 코드 한 줄씩 차례대로 처리한다는 뜻이다.
자바스크립트를 실행하는 웹 브라우저(런타임)는 stack이라는 코드 실행 공간이 있다.
거기서 코드를 한줄한줄 차례로 실행한다.
<script>
console.log(1);
console.log(2);
console.log(3);
</script>
위 코드는 1,2,3이 한줄씩 차례대로 실행된다.
왜냐하면 자바스크립트는 synchorous 하기 때문이다.
거의 대부분의 프로그래밍 언어들은 이런 특징을 가지고 있다.
자바스크립트는 비동기처리 (asynchoronous)라는 것도 가능하다
일단 자바스크립트에서 비동기처리란?
‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’을 의미한다.
특정 코드를 1초 후에 실행하고 싶으면 어떻게 할까?
파이썬에서 위 문장을 실행하려면
print(1);
time.sleep(1);
print(2);
이렇게 작성한다.
time.sleep(1)이라는건 1초 쉬어주세요 라는 뜻이다.
그럼 1이라는게 출력되고 / 1초쉬고 / 2라는게 출력된다.
자바스크립트에서 1초 쉬고 뭔가 출력하는 코드를 작성하려면
console.log(1);
setTimeout(function(){}, 1000);
console.log(2);
보통 프로그래밍 언어처럼 이렇게 작성하면 될까?
안된다. 1과 2가 콘솔창에 동시에 출력된다.
여기서 자바스크립트의 이상한 점을 느끼면 된다.
자바스크립트는 보통 프로그래밍 언어들과 생각하는 방식자체가 다르다.
왜그러냐면 setTimeout() 이라는 함수를 잘 보면 이건 실행까지 1초라는 시간이 걸리는 함수이다.
자바스크립트 실행환경인 웹 브라우저는
이런 특수한 코드들을 발견하면 약간 제쳐두고 다른 코드부터 실행하려고 한다.
그래서 setTimeout() 을 제껴두고 밑에 있는 console.log(2)라는 코드부터 실행하는 것이다.
이런 처리방식을 바로 비동기(asynchronous)라고 한다.
실행이 오래걸리는 그런 코드들은 잠깐 대기실(Web API)에 제쳐두고,
실행이 바로바로 가능한 코드들부터 처리하는 방식을 뜻한다.
이건 자바스크립트 언어 자체의 기능이 아니라,
자바스크립트 실행을 도와주는 웹브라우저 덕분에 해낼 수 있는 것이다.
잠깐 코드를 제쳐주는 대기실(Web API) 이란?
실행을 미루고 옆으로 잠깐 제쳐둘 수 있는 코드들은 미리 정해져있다.
위에서 말했던 setTimeout, addEventListener, ajax 관련 함수들이 있다. 이 함수들은 Web API에서 제공하는 함수들이다.
setTimeout, addEventListener, ajax관련 함수들은 몇초대기, 클릭대기 이런걸 하는 코드들인데
이런 코드들의 공통점은 읽는 시점과 동작 시점이 차이가 있다.
자바스크립트를 실행하고 해석하는 브라우저는 이런 특별한 코드들은 만나면
1. 잠깐 대기실에 제쳐두고
2. 준비가 완료되면 다시 실행시킨다.
console.log(1);
setTimeout(function(){}, 1000);
console.log(2);
웹 브라우저는 위의 코드를 읽다가 setTimeout~ 이런 코드를 만나면 잠시 Web API 라는 대기실로 옮겨서 대기시킨다.
그리고 1초의 대기시간이 지나고 setTimeout이 완료가 되면 대기실에서 코드를 꺼내서 코드가 실행되게 만들어준다.
이것 덕분에 setTimeout같이 대기 시간이 걸리는 코드들은 비동기식으로 처리할 수 있는 것이다.
그래서 자바스크립트는 평소에 별일 없으면 동기식으로 처리하는데 비동기를 지원하는 setTimeout 같은 함수를 이용하면 비동기식으로 동작하게 만들 수 있는 언어이다.
콜백함수 패턴을 이용한 순차적 실행
그럼 아까 예시로 돌아와서, 자바스크립트에서 1초 후에 코드를 실행하고 싶으면 어떻게 할까?
console.log(1);
setTimeout(function(){
console.log(2);
}, 1000);
console.log(3);
이렇게 하면 된다. 콘솔창에 1과 3이 찍히고 그 다음 1초 후에 2가 출력된다.
자바스크립트는 비동기상황에서 코드를 순차적으로 실행하고 싶을 때 콜백함수를 적극 활용한다.
여기서 콜백함수가 어떻게 순차적으로 실행되는지 알아보자. (콜백함수의 동작원리)
콜백함수 디자인
예를 들면 아래와 같은 함수가 있다고 치자.
function 첫째함수(){
setTimeout(() => { console.log(1)}, 0) // <- 비동기 코드임
}
function 둘째함수(){
console.log(2)
}
첫째함수();
둘째함수();
// 2
// 1
이렇게 짜면 순차적으로 실행될까? 둘째함수가 먼저 실행된다.
자바스크립트는 비동기라는 특수성으로 인해 이렇게 쓴다고 순차적으로 실행하는걸 보장하진 않는다.
순차적으로 실행하기 위해서는.. 아래와 같이 코드를 짜면된다.
function 첫째함수(callback){
setTimeout(() => {
console.log(1);
callback();
}, 0)
}
function 둘째함수(){
console.log(2)
}
첫째함수(둘째함수);
// 1
// 2
이런식으로 첫째함수에 파라미터를 넣어 둘째함수를 받을 수 있게 뚫어주면 순차적으로 실행된다.
콜백함수를 이용해 순차적으로 실행하게 만든 것이다.
이게 콜백함수의 디자인이다.
위처럼 미리 만든 함수를 인수로 넣어줄 수도 있고 직접 함수선언문을 집어넣을 수도 있다.
function 첫째함수(callback){
setTimeout(() => {
console.log(1);
callback();
}, 0)
}
첫째함수(function() {
console.log(2);
})
이렇게 순차적으로 실행하려고 콜백함수를 여러개 사용하면 단점이 있다. 코드의 가독성이 안좋아진다. (콜백 지옥)
첫째함수(function(){
둘째함수(function(){
셋째함수(function(){
넷째함수(function(){
다섯째함수(function(){
여섯째함수(function(){
일곱째함수(function() {
...
});
});
});
});
});
});
}):
첫째함수 둘째함수 셋째함수 ... 이렇게 차례로 실행해주는 코드이다.
이런게 보기 싫으면 ES6 문법인 Promise라는 기계를 만들어 사용하면 된다.
콜백대신 쓸 수 있는 Promise 디자인 패턴을 적용하면 어떻게 되냐면
첫째함수()
.then(function(){
그 담에 실행할거
}).then(function(){
그 담에 실행할거
});
코드가 조금 더 보기 좋아졌고 then 이라는 키워드 덕분에 순차적으로 실행된다는 느낌을 더 주게된다.
파인드가 제시하는 비동기적으로 처리된 작업들을 순차적으로 실행하는 방법이다.
2023.03.29 - [분류 전체보기] - Promise 패턴을 이용한 순차적실행 (2) 이 포스팅에서 프로미스에 대한 추가적인 설명을 한다.
'Front end > JavaScript' 카테고리의 다른 글
자바스크립트가 웹 브라우저에서 동작하는 원리 (0) | 2023.03.28 |
---|---|
import / export 를 왜,언제,어떻게 쓰는가? (0) | 2023.03.27 |
자바스크립트 Hoisting, 전역변수, 참조 (0) | 2023.03.27 |
자바스크립트 var, let, const 차이점 (1) (0) | 2023.03.27 |
Arrow function을 왜,언제,어떻게 쓰는가? (0) | 2023.03.27 |