🔸 동기 : 특정 코드의 실행이 완료될 때까지 기다리고 난 후 다음 코드를 수행하는 것.
🔸 비동기 : 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드들을 수행하는 것. 동기적으로 운영하는 경우보다 훨씬 효율적.
🔸 JavaScript의 작동원리 : 싱글 스레드 기반으로 동작하는 언어 (한번에 한 가지 동작만 처리할 수 있음), 따라서 동기적으로 작동. JavaScript가 작동하는 환경(런타임)에서 비동기 처리를 도와주기 때문에 특별한 작업 없이 비동기 처리를 할 수 있음.
🔸 일정 시간(millisecond
) 후에 함수(callback
)를 실행
🔸 return : timeoutID
. 생성된 타이머를 식별할 때 사용.
🔸 timerId
를 입력받아 setTimeout()
타이머를 종료
🔸 return : 없음
🔸 일정 시간(millisecond
)의 간격을 가지고 함수(callback
)를 반복적으로 실행
🔸 return : timeoutID
🔸 timerId
를 입력받아 setInterval()
타이머를 종료
🔸 return : 없음
🔸 비동기 작업은 언제 끝날지 모른다는 특징을 가지며, 코드의 실행순서가 뒤죽박죽이 될 수 있음.
🔸 예를 들어, 네트워크 통신 같은 비동기 작업이 완료되고 나서, 받아온 데이터를 처리하는 코드가 수행되도록 해야한다면, 즉 특정 비동기 코드가 끝나고 나서 후처리를 하고 싶으면 Callback 함수를 이용해 비동기 코드를 동기화 시키면 됨.
🔸 이런 Callback 함수를 비동기 Callback이라고 부름.
// 1. 로그인 function login(username, callback) { setTimeout(() => { callback(username) }, 1000) } // 2. 장바구니에 넣기 function addToCart(product, callback) { setTimeout(() => { callback(product) }, 1000) } // 3. 함수 실행 시, 1초 후 로그인 함수가 실행되고 그다음 1초뒤에 장바구니 함수가 실행됨 login('탁구', (username) => { console.log(`${username}님 안녕하세요`) addToCart('사료', (product) => { console.log(`${product}를 장바구니에 넣었습니다`) }) })
🔸 비동기 코드의 순서를 제어할 수 있지만 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Callback Hell이 발생함.
const printString = (string, callback) => { setTimeout(function () { console.log(string); callback(); }, Math.floor(Math.random() * 100) + 1); }; const printAll = () => { printString('A', () => { printString('B', () => { printString('C', () => { printString('D', () => { printString('E', () => { printString('F', () => { printString('G', () => { printString('H', () => { printString('I', () => { printString('J', () => { printString('K', () => { printString('L', () => { printString('M', () => { printString('N', () => { printString('O', () => { printString('P', () => {}); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }; printAll(); console.log( );
🔸 Callback Hell의 현상을 방지하기 위해 Promise가 사용되기 시작
🔸 비동기 처리에 사용되는 자바스크립트 객체로 비동기 작업이 맞이할 성공 혹은 실패를 나타냄
🔸 대기(pending) : 이행하지도, 거부하지도 않은 초기 상태. undefined
🔸 이행(fulfilled) : 연산이 성공적으로 완료됨. 결과값
🔸 거부(rejected) : 연산이 실패함. Error
🔸 Promise
는 Class
이기 때문에 new
키워드를 통해 Promise
객체를 생성
const promise = new Promise()
🔸 또한 Promise
는 비동기 처리를 수행할 콜백 함수(executor
)를 인수로 전달받는데 이 콜백 함수는 resolve
, reject
함수를 인수로 전달받음.
resolve(result)
: 비동기 작업이 완료되면 결과 값을 처리할 함수. 성공적으로 이행되면 Promise
객체는 fullfilled
상태를 가짐.reject(error)
: 비동기 작업이 거부되면 에러처리 할 함수. rejected
상태를 가진 Promise
객체를 반환.const promise = new Promise((resolve, reject) => { setTimeout(() => { const data = { name : '탁구'} if(data) { console.log('네트워크 요청 성공') resolve(data) } else { console.log('네트워크 요청 실패') reject(new Error('네트워크 문제')) } }, 1000) })
🔸
promise
객체가 생성되면,executor
함수가 즉시 실행되기 때문에, 이를 방지하기 위해서 특정 함수 안에promise
객체를 생성해주면 됨.function getDate() { const promise = new Promise() // 위 코드와 동일 return promise }
🔸 Promise
가 fullfilled
상태가 되면, .then
메서드가 실행되고, 콜백 함수를 호출. 콜백 함수는 Promise
의 결과값을 매개변수로 전달 받을 수 있음
getData().then((data) => { const name = data.name console.log(`${name}님 안녕하세요`) })
executor
에 작성했던 코드들이 정상적으로 처리가 되었다면resolve
함수를 호출하고,.then
메서드로 접근 가능..then
안에서 리턴한 값이Promise
면Promise
의 내부 프로퍼티result
를 다음.then
의 콜백 함수의 인자로 받아올 수 있음.Promise
가 아니라면 리턴한 값을.then
의 콜백 함수의 인자로 받아올 수 있음.
🔸 에러가 발생했을 경우, Promise
객체는 rejected
상태가 되고, .catch
메서드가 실행. 전달된 콜백 함수는 에러를 처리.
getData().then((data) => { const name = data.name console.log(`${name}님 안녕하세요`) }).catch((error) => { //... })
🔸 Promise
가 처리되고 성공 여부와 상관없이 지정된 콜백 함수가 실행됨.
🔸 .then()
은 항상 새로운 Promise
객체를 리턴하기 때문에 연속해서 .then
메서드를 사용할 수 있음. 이를 Promise chaining이라고 함
🔸 따라서 비동기 작업을 순차적으로 진행해야 하는 경우 사용.
const pormise = getData() promise .then((data) => getData()) .then((data) => getData()) // ... })
💡
.then
내에서 다른 값으로 리턴해줘도.then
은 항상Promise
를 리턴. 리턴된 다른 값은 곧바로Promise
로 감싸져서resolve
가 된 상태로 되고 다음.then
메서드에 전달됨. 따라서Promise
가resolve
될 때까지 기다릴 필요없이 즉시 사용할 수 있음.
🔸 Promise.all(iterable)
: 여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용.
🔸 인자로는 배열을 받아, 해당 배열에 있는 모든 Promise
에서 executor
내 작성했던 코드들이 정상적으로 처리가 되었다면 결과를 배열에 저장해 새로운 Promise
를 반환.
🔸 인자로 받는 배열에 있는 Promise
중 하나라도 에러가 발생하게 되면 나머지 Promise
의 상태와 상관없이 즉시 종료.
🔸 Promise.allSettled(iterable)
: 주어진 모든 Promise
를 이행하거나 거부한 후, 각 Promise
에 대한 결과를 나타내는 객체 배열을 반환.
🔸 성공 여부에 관련 없는 여러 비동기 작업을 수행해야 하거나, 항상 각 Promise
의 실행결과를 알고 싶을 때 사용.
🔸 Promise.any(iterable)
: iterable
안에 있는 Promise
중에 가장 먼저 resolve
가 된 Promise
를 반환.
🔸 배열로 들어간 Promise
가 모두 reject
되어야만 반환된 Promise
가 reject
됨.
🔸 Promise.race(iterable)
: iterable
안에 있는 Promise
중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부.
🔸 JavaScript는 ES8에서 async/await
키워드를 제공. 이를 통해 복잡한 Promise
코드를 간결하게 작성 가능.
🔸 async
: 함수 앞에 키워드를 작성. 항상 Promise
를 반환하는 비동기 함수가 됨.
💡
async
함수 내에Promise
를 직접 리턴하면,Promise
로 두번 감싸지는 것이 아니라, 그대로Promise
로 리턴됨.
🔸 await
: async
함수 내에서 코드 앞에 await
키워드를 작성. await
키워드가 작성된 코드가 동작하고 나서야 다음 순서의 코드가 동작함.
// 함수 선언식
async function funcDeclarations() {
await 작성하고자 하는 코드
...
}
// 함수 표현식
const funcExpression = async function () {
await 작성하고자 하는 코드
...
}
// 화살표 함수
const ArrowFunc = async () => {
await 작성하고자 하는 코드
...
}
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
console.log(string);
}, Math.floor(Math.random() * 100) + 1);
});
};
const printAll = async () => {
await printString('A');
await printString('B');
await printString('C');
};
printAll();
console.log(
`Async/Await을 통해 Promise를 간결한 코드로 작성할 수 있게 되었습니다.`
);
🔸 try-catch
: 에러가 날 수 있는 부분을 try
문 안에 작성하고, catch
로 에러 처리.
async function getData() {
let user
try {
user = await getUser()
} catch(err) {
// 에러처리
}
}
🔸 비동기 이벤트 기반 JavaScript 런타임
🔸 모듈 : 어떤 기능을 조립할 수 있는 형태로 만든 부분.
fs(File System)
: PC의 파일을 읽거나(readFile
) 저장하는(writeFile
) 등의 일을 할 수 있게 도와줌.DNS
: 파일 시스템 모듈이 파일을 읽거나 저장하는 기능을 구현할 수 있도록 도움🔸 모든 모듈은 '모듈을 사용하기 위해 불러오는 과정'이 필요. JavaScript 코드 가장 상단에 require
구문을 이용하여 다른 파일을 불러올 수 있음
const fs = require('fs'); // 파일 시스템 모듈을 불러옵니다
const dns = require('dns'); // DNS 모듈을 불러옵니다
// 이제 fs.readFile 메서드 등을 사용 가능
🔸 서드 파티 모듈(3rd-party module) : 해당 프로그래밍 언어에서 공식적으로 제공하는 빌트인 모듈(built-in module)이 아닌 모든 외부 모듈
🔸 다운로드하기 위해서는 npm install 모듈명
을 사용
// 1. 터미널에 npm install
npm install 모듈명
// 2. Node.js에서 require구문으로 불러옴
const 모듈명 = require('모듈명')
🔸 로컬에 존재하는 파일을 비동기적으로 읽어옴.
🔸 fs.readFile(path[, options], callback)
path
(string | Buffer | URL | integer) : 파일 이름을 작성.options
(Object | string) : encoding, flag, signal을 필요에 따라 작성callback
: 파일을 읽은 뒤 콜백함수가 비동기적으로 실행됨🔸 fetch(URL)
: Web API 중 하나로, 특정 URL
로 네트워크 요청을 보내는 비동기 함수.
🔸 Promise
를 리턴함
🔸 json()
: 본문 텍스트를 JSON으로 입력받아 파싱하여 JavaSctipt 객체로 이행하는 Promise
를 반환
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => {
return response.json()
}).then((data) => {
console.log(data)
})
// 📍 async-await
async function fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com')
const data = await response.json()
console.log(data)
}
fetchData()