🧠 핵심 개념

전통적인 비동기 방식: 콜백 지옥

fs.readFile('file.txt', (err, data) => {
  if (err) return console.error(err);
  console.log(data);
});

프로미스 기반

fs.promises.readFile('file.txt')
  .then(data => console.log(data))
  .catch(err => console.error(err));
 

✅ async/await 기반 (가장 가독성 좋음)

async function readFile() {
  try {
    const data = await fs.promises.readFile('file.txt');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}
 

✅ 요약

문법의미
async 이 함수 안에서 await 쓸 거야
await 비동기 작업이 끝날 때까지 기다릴게. 이후에 무조건 promise로 반환된 값이 와야해.
Promise 비동기 작업 결과를 담는 객체
 

 

🧠 Promise란?

Promise는 **"미래에 결과를 제공할 수 있는 객체"**입니다.
성공 또는 실패 결과를 나중에 한 번만 전달해주는 약속(promise) 같은 거예요.


📦 구조

const promise = new Promise((resolve, reject) => {
  // 비동기 작업 실행
  if (성공) {
    resolve(값);   // 성공 시
  } else {
    reject(에러);  // 실패 시
  }
});
 

✅ 예제: 1초 후 "끝"을 출력하는 Promise

function wait(ms) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('끝!');
    }, ms);
  });
}

wait(1000).then((result) => {
  console.log(result); // 1초 후에 "끝!" 출력됨
});
 

🪄 왜 좋은가?

기존의 콜백 지옥을 피할 수 있기 때문입니다.

❌ 콜백 지옥 예시

getUser(id, (user) => {
  getPosts(user.id, (posts) => {
    getComments(posts[0].id, (comments) => {
      // 너무 깊어짐
    });
  });
});
 

✅ Promise로 개선

getUser(id)
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => {
    // 훨씬 깔끔함
  })
  .catch(err => console.error(err));
 

📌 상태 3가지

Promise는 항상 3가지 상태 중 하나를 가집니다:

상태설명
pending 대기 중 (아직 결과 없음)
fulfilled resolve() 호출됨 (성공)
rejected reject() 호출됨 (실패)
 

🔄 그리고 async/await은…

const result = await wait(1000); // 내부적으로 .then()을 기다림

await는 사실상 promise.then(...)을 동기 코드처럼 보이게 하는 문법이에요.

 

💡 간단한 예제

function wait(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function main() {
  console.log("1초 기다리는 중...");
  await wait(1000); // 1초 대기
  console.log("끝났어요!");
}

main();


실행 결과:

1초 기다리는 중...
(1초 후)
끝났어요!

 

만약 async await를 사용하지 않는다면

function wait(ms) {
  return setTimeout(ms);
}

function main() {
  console.log("1초 기다리는 중...");
  wait(1000); // 1초 대기
  console.log("끝났어요!");
}

main();


실행 결과:

1초 기다리는 중...
끝났어요!
(1초 후)
 


🧩 어떤 함수들이 Promise 콜백에 들어갈 수 있을까?

✅ 대표적인 콜백 기반 함수들:

이들은 기본적으로 콜백을 인자로 받아서 처리하므로 Promise로 감싸서 사용할 수 있어요.

비동기 함수설명
setTimeout() 일정 시간 후 실행
setInterval() 일정 주기 반복 실행 (보통 clearInterval()과 함께 씀)
fs.readFile() (Node.js) 파일 읽기
fs.writeFile() (Node.js) 파일 쓰기
navigator.geolocation.getCurrentPosition() (브라우저) 위치 정보 요청
XMLHttpRequest (구버전) HTTP 요청
child_process.exec() (Node.js) 셸 명령 실행
 

🧪 예시: fs.readFile()을 Promise로 감싸기

 
const fs = require('fs'); 
function readFilePromise(path) { 
   return new Promise((resolve, reject) => { 
      fs.readFile(path, 'utf8', (err, data) => { 
         if (err) reject(err); else resolve(data); 
      }); 
   }); 
}

🎁 팁: 요즘은 Promise 버전이 따로 있어요

많은 API가 이미 Promise 버전이 존재합니다:

예시설명
fetch() 브라우저의 HTTP 요청 (Promise 기반)
fs.promises.readFile() Node.js의 Promise 버전
mysql2/promise MySQL 모듈의 Promise 버전
axios.get() Axios는 내부적으로 Promise 사용
 

 

참고로! 하위에서 async로 비동기처리를 해주었다면, 그 상위 함수들에서도 모두 async로 기다려줘야해요

// 가장 하위 함수 (Promise 반환)
function daughter() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('👧 daughter: 일 끝났어!');
      resolve('결과 from daughter');
    }, 1000);
  });
}

// 중간 함수 (async 함수로 daughter 호출)
async function mother() {
  console.log('👩 mother: daughter에게 부탁할게.');
  const result = await daughter();
  console.log(`👩 mother: daughter가 준 결과 -> ${result}`);
  return `mother가 받은: ${result}`;
}

// 최상위 함수 (async 함수로 mother 호출)
async function grandmother() {
  console.log('👵 grandmother: mother에게 부탁할게.');
  const finalResult = await mother();
  console.log(`👵 grandmother: 최종 결과 -> ${finalResult}`);
}

// 실행
grandmother();



 

 

 

 

 

 

 

 

 

 

+ Recent posts