티스토리 뷰
동기(Synchronous) & 비동기(Asynchronous)
📌 동기(Synchronous) : 각 함수와 코드들이 위에서 아래로 차례로 동작
자바스크립트는 싱글 스레드 언어이기 때문에 한 번에 하나의 작업만 수행할 수 있다.
한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 자신의 차례를 기다린다.
즉, 이전 작업이 완료되어야 다음 작업을 수행할 수 있게 된다.
간단하고 직관적이지만, 작업이 오래 걸리거나 응답이 늦어지는 경우에는 전체적인 성능과 사용자 경험에 영향을 줄 수 있다.
예를 들어 서버에 데이터를 요청하고 응답을 받아야 하는 작업이 있다면, 응답이 올 때까지 다른 작업을 하지 못하고 대기해야 한다. 이렇게 되면 프로그램의 흐름이 멈추거나 지연되게 된다.
📌 비동기(Synchronous) : 특정 작업의 완료를 기다리지 않고 다른 작업을 동시에 수행
메인 스레드가 작업을 다른 곳에 인가하여 처리되게 하고, 그 작업이 완료되면 콜백 함수를 받아 실행하는 방식이다.
쉽게 말해 작업을 백그라운드에 요청하여 처리하고 멀티로 작업을 동시에 처리하는 것으로 보면 된다.
응답이 오는 것과 상관없이 다른 작업을 계속 이어나가 병렬로 작업을 동시 처리가 가능해져 프로그램의 흐름이 멈추거나 지연되지 않게 된다.
비동기 - 콜백 함수
비동기 방식은 요청과 응답의 순서를 보장하지 않는다.
따라서 응답의 처리 결과에 의존하는 경우에는 콜백 함수를 이용하여 작업 순서를 간접적으로 끼워 맞출 수 있다.
즉, 비동기 처리가 끝난 후에 해야 할 작업에 대해 순서를 보장해줄 수 있다.
function getDB(callback) {
// 데이터베이스로부터 3초 후에 데이터 값을 받아온 후, 콜백 함수 호출
setTimeout(() => {
const value = 100;
callback(value);
}, 3000);
}
function main() {
// 호출할 작업에 콜백 함수를 넘긴다
getDB(function(value) {
let data = value * 2;
console.log('data의 값 : ', data);
});
}
main();
하지만 콜백 함수를 사용하면 코드가 복잡하고 가독성이 떨어지는 문제가 있다.
특히, 여러 개의 비동기 작업을 순차적으로 수행해야 할 때는 콜백 함수가 중첩되어 코드의 깊이가 깊어지는 현상이 발생한다.
비동기 - Promise 객체
비동기 작업의 최종 완료 또는 실패를 나타내는 Array나 Object 처럼 독자적인 객체이다.
비동기 작업이 끝날 때까지 결과를 기다리는 것이 아니라, 결과를 제공하겠다는 '약속'을 반환한다.
Promise 객체를 생성하려면 new 키워드와 Promise 생성자 함수를 사용하면 된다.
이때 Promise 생성자 안에 두개의 매개변수를 가진 콜백 함수를 넣게 된다.
첫 번째 인수는 작업이 성공했을 때 성공(resolve)임을 알려주는 객체이며, 두 번째 인수는 작업이 실패했을 때 실패(reject)임을 알려주는 오류 객체이다.
const myPromise = new Promise((resolve, reject) => {
// 비동기 작업 수행
const data = fetch('서버로부터 요청할 URL');
if(data)
resolve(data); // 만일 요청이 성공하여 데이터가 있다면
else
reject("Error"); // 만일 요청이 실패하여 데이터가 없다면
})
myPromise
.then((value) => { // 성공적으로 수행했을 때 실행될 코드
console.log("Data: ", value); // 위에서 return resolve(data)의 data값이 출력된다
})
.catch((error) => { // 실패했을 때 실행될 코드
console.error(error); // 위에서 return reject("Error")의 "Error"가 출력된다
})
.finally(() => { // 성공하든 실패하든 무조건 실행될 코드
})
위에서 사용한 것 처럼 Promise 객체를 바로 변수에 할당할 수도 있지만, 보통 함수로 감싸서 사용한다.
함수를 만들고 그 함수를 호출하면 프로미스 생성자를 return 함으로서, 곧바로 생성된 프로미스 객체를 함수 반환값으로 얻어 사용하는 기법이다.
// 프로미스 객체를 반환하는 함수 생성
function myPromise() {
return new Promise((resolve, reject) => {
if (/* 성공 조건 */) {
resolve(/* 결과 값 */);
} else {
reject(/* 에러 값 */);
}
});
}
// 프로미스 객체를 반환하는 함수 사용
myPromise()
.then((result) => {
// 성공 시 실행할 콜백 함수
})
.catch((error) => {
// 실패 시 실행할 콜백 함수
});
👉 더 자세하게는 인파님 블로그 참고하기
📚 자바스크립트 Promise 개념 & 문법 정복하기
콜백 지옥을 탈출하는 새로운 문법 자바스크립트에서 '비동기 처리' 란 현재 실행중인 작업과는 별도로 다른 작업을 수행하는 것을 말한다. 예를 들어 서버에서 데이터를 받아오는 작업은 시간
inpa.tistory.com
비동기 - Async/Await
프로미스가 여러 개 연결되면 지나친 then 핸들러 함수의 남용으로 인해 코드가 길어지고 복잡해질 수 있다는 것이다.
async/await는 프로미스를 기반으로 하지만, 마치 동기 코드처럼 작성할 수 있게 해준다.
비동기 작업을 쉽게 읽고 이해할 수 있게 해주기 때문에 비동기 작업을 처리할 일이 있다면 대게 async/await 방식을 쓰는 것이 보통이다.
async/await가 Promise를 대체하기 위한 기능은 아니다.
내부적으로는 여전히 Promise를 사용해서 비동기를 처리한다. 프로그래머가 유지보수하게 편하게 보이는 문법만 다르게 해줄 뿐이다.
await는 키워드 이름에서 보듯이 Promise 비동기 처리가 완료될때 까지 코드 실행을 일시 중지하고 wait 한다라는 뜻으로 보면 된다.
await 키워드를 사용하여 이 Promise가 처리될 때까지 코드 실행을 일시 중지하고, Promise가 처리되면 결과 값을 반환하여 변수에 할당하는 식이다.
// 프로미스 객체 반환 함수
function delay(ms) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`${ms} 밀리초가 지났습니다.`);
resolve()
}, ms);
});
}
// 기존 Promise.then() 형식
function main() {
delay(1000)
.then(() => {
return delay(2000);
})
.then(() => {
return Promise.resolve('끝');
})
.then(result => {
console.log(result);
});
}
// async/await 방식
async function main() {
await delay(1000);
await delay(2000);
const result = await Promise.resolve('끝');
console.log(result);
}
// 메인 함수 호출
main();
async/await 비동기 처리에 대한 에러를 처리할 필요가 생기면 try/catch문을 씌우면 된다.
코드가 동기적으로 보일 수 있게 됐다 !
// async/await 방식
async function func() {
try {
const res = await fetch(url); // 요청을 기다림
const data = await res.json(); // 응답을 JSON으로 파싱
// data 처리
console.log(data);
} catch (err) {
// 에러 처리
console.error(err);
}
}
func();
👉 더 자세하게는 인파님 블로그 참고하기
📚 자바스크립트 Async/Await 개념 & 문법 정복
자바스크립트 비동기 처리 3가지 방식 자바스크립트는 싱글 스레드 프로그래밍 언어기 때문에 멀티 작업을 하기 위해선 비동기 처리 방식이 자주 쓰인다. 비동기 처리는 백그라운드로 동작되기
inpa.tistory.com
브라우저의 내부 구성
자바스크립트를 실행하는 소프트웨어로는 우리가 잘 알고 있는 웹브라우저와 런타임인 Node.js 가 있다.
싱글 스레드인 자바스크립트 엔진이 어느 곳을 거쳐 비동기 작업을 수행하는지 웹브라우저의 구성도를 통해 알아보자.
브라우저는 웹 사이트를 화면에 보여주기 위해 여러가지 역할을 하는 부품들로 이루어져 있다.
그 중 비동기와 관련된 구성 요소 는 Web APIs, Event Table, Callback Queue, Event Loop 등이 있다.
Call Stack : 자바스크립트 엔진이 코드 실행을 위해 사용하는 메모리 구조
Heap : 동적으로 생성된 자바스크립트 객체가 저장되는 공간
Web APIs: 브라우저에서 제공하는 API 모음으로, 비동기적으로 실행되는 작업들을 전담하여 처리
Callback Queue : 비동기적 작업이 완료되면 실행되는 함수들이 대기하는 공간
Event Loop : 비동기 함수들을 적절한 시점에 실행시키는 관리자
📌 Web APIs
Web API는 브라우저에서 멀티스레드로 구현되어 있어서, 브라우저가 비동기 작업에 대해 메인 스레드를 차단하지 않고 다른 스레드를 사용하여 동시에 처리할 수 있게 한다.
DOM : HTML 문서의 구조와 내용을 표현하고 조작할 수 있는 객체
XMLHttpRequest: 서버와 비동기적으로 데이터를 교환할 수 있는 객체. AJAX기술의 핵심.
Timer API: 일정한 시간 간격으로 함수를 실행하거나 지연시키는 메소드들을 제공
Console API : 개발자 도구에서 콘솔 기능을 제공
Canvas API: <canvas> 요소를 통해 그래픽을 그리거나 애니메이션을 만들 수 있는 메소드들을 제공
Geolocation API: 웹 브라우저에서 사용자의 현재 위치 정보를 얻을 수 있는 메소드들을 제공
모든 Web API들이 비동기로 동작되는 것이 아니다.
예를 들어 DOM API나 Console API는 동기적으로 처리되고, XMLHttpRequest나 Timer API는 비동기적으로 처리된다.
📌 Callback Queue
여러가지 Queue를 묶어 Callback Queue라고 한다.
Task Queue : setTimeout, setInterval, fetch, addEventListener 와 같이 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 (macrotask queue 는 보통 task queue 라고 부른다)
Microtask Queue : promise.then, process.nextTick, MutationObserver 와 같이 우선적으로 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 (처리 우선순위가 높음)
일반적으로 microtask queue가 가장 우선순위가 높아 먼저 microtask queue를 처리하여 먼저 비우고 task queue의 콜백을 처리한다.
📌 이벤트 루프
이벤트 루프는 브라우저 내부의 Call Stack, Callback Queue, Web APIs 등의 요소들을 모니터링하면서 비동기적으로 실행되는 작업들을 관리하고, 이를 순서대로 처리하여 프로그램의 실행 흐름을 제어한다.
간단히 표현하자면 브라우저의 동작 타이밍을 제어하는 관리자라고 보면 된다.
이벤트 루프의 동작 과정을 간단히 살펴보자면, 자바스크립트의 setTimeout이나 fetch 와 같은 비동기 자바스크립트 코드를 브라우저 Web APIs에게 맡기고, 백그라운드 작업이 끝난 결과를 콜백 함수 형태로 큐(Callback Queue)에 넣고 처리 준비가 되면 호출 스택(Call Stack)에 넣어 마무리 작업을 진행한다.
Promise, async/await 내부 동작 과정은 인파님 블로그 확인 ! 설명이 정말 잘 되어있다.
🔄 자바스크립트 이벤트 루프 동작 구조 & 원리 끝판왕
자바스크립트 비동기와 이벤트 루프 브라우저의 멀티 스레드로 작업을 동시에 Javascript는 싱글 스레드 언어라고 들어본 적이 있을 것이다. '싱글' 스레드라 한 번에 하나의 작업만 수행이 가능하
inpa.tistory.com
✨ 이벤트 루프 시각화 코드 확인 사이트
http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7%21%21%21PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D
latentflip.com
참고
'WEB > JavaScript' 카테고리의 다른 글
정규표현식 (Regex, Regular Expression) (0) | 2024.08.05 |
---|---|
[JavaScript] Web APIs - Location, History (0) | 2024.07.01 |
[JavaScript] 배열 내 객체의 특정 키 값 유효성 검사하기 (0) | 2024.06.10 |
[JavaScript] 객체와 JSON (0) | 2024.05.31 |
[JavaScript] 표준 내장 객체 - 배열 (1) | 2024.01.04 |
- Total
- Today
- Yesterday
- figma
- echarts
- x축스크롤
- javascript
- Location
- 객체복사
- vscode
- package
- 환경설정
- piechart
- Figma 기초
- chartjs
- BarChart
- npm
- 객체
- package-lock
- Chart
- Figma Style
- 프론트엔드
- web
- Legend
- Figma 버튼
- npm install
- 얕은복사
- VUE
- 깊은복사
- SCSS
- Vscode단축키
- SASS
- frontend
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |