node.js - 비동기 프로그래밍 / callback / promise / async & await 본문
비동기적 프로그래밍
자바스크립트는 동기적 실행이 기본적이지만, 비동기적 실행이 필요할 때가 있다.
예를 들어, 스크립트에서 A와 B 두 가지의 API 를 요청한다고 했을 때,
두 API 끼리 상호 간 연결고리가 없다라고 한다면
A의 요청과 응답이 끝날 때까지 B를 가만히 두는 것은 시간 낭비이기 때문.
따라서 위와 같은 문제를 해소하기 위해 상호 간 응답을 기다리지 않고
코드를 진행시키는 방식을 비동기적 프로그래밍이라고 한다.
비동기적 프로그래밍 유형은 세 가지 정도로 볼 수 있다.
- 콜백 함수 (callback)
- promise (프로미스 객체)
- ansync & await
콜백 함수(callback)
콜백 함수에 대해 가볍게 정의하자면, '함수에 인자로 넘겨지는 함수'라고 볼 수 있다.
예를 들면 아래와 같다.
function main(callback, data) {
1. console.log(data) // data
2. callback(data) {
conole.log("data가 출력되었습니다.") // "data가 출력되었습니다."
}
callback(data)
}
main(callback, data)
위와 같이 코드를 작성해주면,
먼저 처리하고자 하는 1번 코드줄이 실행된 이후, 2번 코드가 실행되는 것을 확인할 수 있다.
콜백 지옥
특정 메서드나 명령어를 사용하지 않다보니, 구조 자체는 심플해보이나
사용함에 있어 코드가 불필요하게 길어지는 문제를 마주할 수 있는데 이를 콜백 지옥이라고 한다.
callback 지옥 예시
const callbackHell = () => {
axios
.get(`url1`)
.then((res) => {
return axios
.get(`url2`)
.then((res)=>{
axios
.get(`url3`)
.then((res)=>{
console.log("모두 완료")
})
})
});
};
다만, 요청과 응답을 하기 위한 get / then 로 예시를 들자면
url1 에 대한 요청과 응답, url2 에 대한 요청과 응답, url3 에 대한 응답과 요청이 줄줄이 이어져
- 코드가 한눈에 보기에 가독성이 떨어지고
- 어디에 문제가 생겼는지 쉽게 파악하기 힘들다.
promise chaining (프로미스 체이닝)
위와 같은 문제를 해결하기 위해 등장한 것이 프로미스 체이닝이다.
// 프로미스체이닝 // 실행 순서를 이해하기 어려움
const PromiseChaining = () => {
console.log("1번째로 실행")
axios
.get(`url1`)
.then((res) => {
console.log("2번째로 실행")
return axios.get(`url2`)
})
.then((res)=>{
console.log("3번째로 실행")
return axios.get(`url3`)
})
.then((res)=>{
console.log("모두 완료! 4번째로 실행")
})
console.log("5번째로 실행")
};
이는 promise.then 을 사용한 경우 promise가 반환되기 때문에 사용할 수 있는 방법인데,
위 콜백 지옥에 비해 가독성이 훌륭하긴 하나 실행 순서를 이해하기 어렵다는 단점을 가진다.
예시로 위 코드의 경우, 실행 순서는 생각과 달리 1-5-2-3-4으로 이루어지는데 왜 이렇게 실행되는지에 대해서는 다음에 다뤄본다.
Promise (promise 객체)
Promise 는 비동기 처리를 하기 위해 사용되는 객체이다.
'성공했을 때 실행시킬 함수와 실패했을 때 실행시킬 함수를 요소로 받으며,
이를 try와 catch를 통해 상황에 따라 원하는 함수를 실행시킬 수 있다.
** 추가로 promise 객체는 then / catch 사용이 모두 가능하다.(axios 또한 promise 객체이기 때문에 가능)
new Promise((성공했을때실행시킬함수, 실패했을때실행시킬함수)=>{
try {
// API 요청을 한다면?
const response = "철수" // 백엔드에서 '철수' 데이터 받아옴
성공했을때실행시킬함수(response) // 성공하면 실행
}catch(error){
실패했을때실행시킬함수("실패했습니다!") // 실패하면 실행
}})
.then((res)=>{
console.log(res) // 철수
})
.catch((err)=>{
console.log(err) // 실패했습니다
})
async & await
async & await 를 이해하기 위해서는 async / await 의 역할에 대해 알아볼 필요가 있다.
async 는 function 앞에 위치하며, 해당 함수를 promise로 반환하게 한다.
await 은 async 가 덮고 있는 함수 안에서만 동작이 가능하며,
asnyc 내 promise가 처리될 때까지 기다린 후 작동하게 된다.
async & await 은 앞에서 언급한 promise.then 보다 더 심플하게 비동기적 프로그래밍을 실행할 수 있는 방법이지만,
에러가 발생한 경우 찾기 쉽지 않기 때문에, try / catch 를 사용하는 것이 좋다.
const myAsyncAwait = async () => {
await axios.get(`url`);
};
// then, catch 생략
2023.01.17 - [코딩/node.js] - node.js - async-await / axios 활용 문자&메일 발송 / 환경변수
위는 async-await을 활용한 방식이다.
'개발 > node.js' 카테고리의 다른 글
node.js - package.json(의존성 모듈) (0) | 2023.01.19 |
---|---|
node.js - 데이터베이스 / mongoDB(&GUI) / docker-compose / mongoose 설치 (1) | 2023.01.19 |
node.js - 가상 머신 / Docker / 포트포워딩 (0) | 2023.01.17 |
node.js - async-await / axios 활용 문자&메일 발송 / 환경변수 (0) | 2023.01.17 |
node.js - axios / CORS / apollo-server / graphQL-API(&docs) 생성 (0) | 2023.01.14 |