문제
어제에 이어 자바스크립트의 비동기적 처리에 대해 정리해보려고 한다.
서버 개발 실습을 하는데 route에 async를 붙여 비동기적 처리를 하는 경우가 많더라.
아직까지 이게 서버 동작에 어떤 차이를 주는지 이해가 잘 안가서
더 공부가 필요하다.
시도
요즘 구글링보단 chat gpt를 사용하는 빈도가 늘었다.
검색을 하고 괜찮은 자료들을 찾는 수고를 조금이나마 덜어주는 것 같아서 좋다.
promise에 대해 g선생이 설명한 내용을 정리하자면,
Promise는 javascript에서 비동기 처리를 할 수 있게 해주는 객체이다.
(객체는 모다? key : value 값을 갖는다. 일반적으로!)
예시 코드를 쓰자면,
const getData = () => {
return new Promise((resolve, reject) => {
// 비동기적으로 데이터를 가져오는 작업
const data = { id: 1, name: "John Doe", email: "johndoe@example.com" };
// 데이터를 가져오는데 성공하면 resolve를 호출합니다.
if (data) {
resolve(data);
} else {
// 데이터를 가져오는데 실패하면 reject를 호출합니다.
reject("Error fetching data");
}
});
};
위 코드에서 getData 함수는 새로운 Promise 객체를 반환한다.
이 Promise 객체는 resolve와 reject 함수를 갖고 있으며, 데이터를 가져오는 작업이 완료되면
resolve 함수를 호출하고 오류가 발생하면 reject 함수를 호출한다.
그런데 문득 궁금증이 생겼다.
실습할 때 따라서 작성한 코드에는 promise라는 구문이 없었는데
비동기적 처리를 했다. 그리고 promise를 사용하기 위해선 꼭 new 연산자를 사용하는지도 궁금했다.
그래서 지선생에게 두가지 질문을 해보았다.
Q. promise에는 반드시 new를 써야해?
A. 네, Promise 객체를 생성하려면 new 연산자를 사용해야 합니다. Promise 생성자는 new Promise()와 같은 형태로 호출됩니다.
Promise 생성자는 함수를 인자로 받으며, 이 함수는 resolve와 reject 함수를 인자로 받습니다. 이 함수 내에서 비동기 작업을 수행하고, 작업이 성공하면 resolve 함수를 호출하고, 작업이 실패하면 reject 함수를 호출합니다. 이렇게 생성된 Promise 객체는 비동기 작업의 결과를 나타내며, .then() 메서드나 .catch() 메서드를 사용하여 비동기 작업의 성공 또는 실패에 따른 후속 처리를 수행할 수 있습니다.
따라서, new 연산자 없이 Promise 객체를 생성할 수는 없습니다.
그렇단다. 하지만 납득이 안가서 다음 질문을 해보았다.
const Goods = require("../schemas/goods.js"); router.post("/goods/", async (req, res) => { const { goodsId, name, thumbnailUrl, category, price } = req.body; const goods = await Goods.find({ goodsId }); if (goods.length) { return res.status(400).json({ success: false, errorMessage: "이미 존재하는 GoodsId입니다.", }); } const createGoods = await Goods.create({ goodsId, name, thumbnailUrl, category, price }); res.json({ goods: createGoods }); });
Q. 위 코드에서 promise의 예를 들 수 있어?
A. 네, 위 코드에서 Promise의 예시를 들 수 있습니다.
async와 await 키워드를 사용하여 Promise를 다룰 수 있습니다.
async 키워드는 비동기 함수를 정의하는 데 사용되며,
await 키워드는 Promise가 처리될 때까지 함수 실행을 일시 중지하고, Promise가 처리되면 해당 값을 반환합니다.
위 코드에서는 async 키워드를 사용하여 router.post() 함수를 비동기 함수로 만들고,
await 키워드를 사용하여 Promise가 처리될 때까지 대기합니다.
예를 들어, await Goods.find({ goodsId })는 Goods 모델에서 goodsId를 찾는 Promise를 반환합니다.
이 Promise가 처리될 때까지 함수 실행을 일시 중지하고, Promise가 처리되면 해당 값을 반환합니다.
그리고 이후의 if (goods.length) 문과 await Goods.create({ goodsId, name, thumbnailUrl, category, price })도
Promise를 반환합니다.
이들 Promise가 처리될 때까지 함수 실행을 일시 중지하고, Promise가 처리되면 해당 값을 반환합니다.
따라서, 위 코드에서 Promise를 다루고 있으며, await 키워드를 사용하여 Promise의 처리 결과에 따른 후속 처리를 수행하고 있습니다.
갑자기 짜증이 나서 따져보았다.
Q. promise를 사용하기 위해서는 반드시 'new' 연산자가 필요하다고 했는데
위의 코드에는 'new' 연산자를 찾을 수 없어.
A. 네, 알려드린 것처럼 Promise 객체를 생성하려면 new 연산자를 사용해야 합니다.
그러나 new Promise() 구문이 코드에 직접 나타나지 않아도,
JavaScript 내부적으로 Promise 객체를 생성하고 반환하는 비동기 함수를 호출하는 것만으로도
Promise 객체를 사용할 수 있습니다.
위 코드에서 사용된 await 키워드는 Promise 객체의 처리 결과를 기다리는 것으로,
await 키워드를 사용하면 Promise 객체를 생성하는 new Promise() 구문이 필요하지 않습니다.
대신, await 키워드 뒤에 비동기 함수가 오면 해당 함수가 반환하는 Promise 객체의 처리 결과를 반환합니다.
따라서, 위 코드에서는 명시적으로 new Promise()를 사용하지는 않았지만,
await 키워드를 사용하여 내부적으로 생성된 Promise 객체의 처리 결과를 다루고 있습니다.
자, 이제 최종장이야.
Q. 그렇다면 비동기 함수의 예를 들어줘.
A.
async function fetchData(url) { try { const response = await fetch(url); // Promise 객체를 반환하는 비동기 함수 호출 const data = await response.json(); // Promise 객체를 반환하는 비동기 함수 호출 return data; // 비동기 처리 결과를 반환 } catch (error) { console.error(error); // 에러 발생 시 에러 로그 출력 } }
위 코드에서 fetchData() 함수는 async 키워드를 사용하여 비동기 함수로 정의되어 있습니다.
이 함수 내부에서 await 키워드를 사용하여 Promise 객체가 처리될 때까지 함수 실행을 일시 중지하고,
Promise가 처리되면 해당 값을 반환합니다.
fetchData() 함수는 fetch() 함수를 호출하여 데이터를 가져옵니다.
fetch() 함수는 Promise 객체를 반환하며,
이 Promise 객체가 처리될 때까지 await 키워드를 사용하여 함수 실행을 일시 중지합니다.
그리고 response.json() 메서드를 호출하여 가져온 데이터를 JSON 형식으로 변환합니다.
json() 메서드도 Promise 객체를 반환하며,
이 Promise 객체가 처리될 때까지 await 키워드를 사용하여 함수 실행을 일시 중지합니다.
마지막으로 data 변수에 저장된 데이터를 반환합니다.
이때, 함수의 반환값은 Promise 객체를 반환하게 되며,
Promise 객체가 처리될 때까지 await 키워드를 사용하여 함수 실행을 일시 중지합니다.
따라서, fetchData() 함수는 비동기 함수이며, await 키워드를 사용하여 Promise 객체의 처리 결과를 다루고 있습니다.
해결
챗 gpt와의 질의를 통해 비동기 함수와 await, promise의 관계를 이해할 수 있었다.
아래에서 최대한 간결하게 정리해 보겠다.
알게된 것
Promise는 JavaScript에서 비동기적 처리를 할 수 있도록 해주는 객체이다.
기본적으로 new 연산자를 이용해 생성할 수 있다.
하지만 비동기 함수와 await이 함께라면 new 연산자 없이도 promise 객체 처리 결과를 반환 할 수 있다.
'Development > TIL' 카테고리의 다른 글
this에 대하여 (0) | 2023.04.18 |
---|---|
mongoose objectId와 new 키워드 (0) | 2023.04.18 |
JS의 비동기적 처리 (근데 이제 Non - Blocking을 곁들인) (0) | 2023.04.14 |
TIL(feat.프로그래머스 1차 비밀지도) (0) | 2023.04.13 |
소수 구하기 (feat.에라토스테네스의 체) (0) | 2023.04.12 |