| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 디자인챌린지
- Be
- 디자인강의
- baekjoon
- 백엔드개발자
- 백준
- 부트캠프
- 국비지원취업
- 오블완
- OPENPATH
- 오픈패스
- 디자인교육
- 국비지원
- JPA
- UXUI기초정복
- Spring
- Java
- 오픈챌린지
- KDT
- 시스템설계
- 내일배움카드
- 국비지원교육
- 환급챌린지
- UXUI챌린지
- API
- 패스트캠퍼스
- UXUIPrimary
- 티스토리챌린지
- mysql
- 백엔드 부트캠프
- Today
- Total
군만두의 IT 개발 일지
[DAY7] JS/Node 비동기 본문
목차
🚀 진행기간: 2023년 6월 26일 ~ 2023년 7월 13일
⭐요약
JavaScript의 동기/비동기 개념, 비동기 제어 방법(Callback, Promise, Async/Await), Node.js 모듈 시스템, fetch API와 Axios를 이용한 네트워크 요청에 대해 정리한다.
| 동기 / 비동기 | 동기는 작업을 순차적으로 처리하고, 비동기는 이전 작업이 끝나지 않아도 다음 작업을 바로 실행함. JavaScript는 싱글 스레드 기반이지만, 런타임 환경에서 비동기 처리를 지원함. |
| 타이머 API | setTimeout은 일정 시간 후 한 번 실행하고, setInterval은 일정 간격으로 반복 실행함.clearTimeout/clearInterval로 각각 종료할 수 있음. |
| Callback / Promise | Callback은 비동기 제어가 가능하나 중첩이 깊어지면 Callback Hell이 발생함. Promise는 .then(), .catch(), .finally()로 비동기 흐름을 제어하며 chaining이 가능함. |
| Async / Await | 복잡한 Promise 코드를 간결하게 작성할 수 있음.async 함수 내에서 await 키워드로 Promise 작업이 끝날 때까지 실행을 일시 정지함. |
| Node.js 모듈 | require로 내장 모듈 또는 서드 파티 모듈을 불러올 수 있음.서드 파티 모듈은 npm install로 먼저 설치해야 함. |
| fetch API / Axios | fetch는 브라우저 내장 API로 특정 URL로부터 비동기적으로 데이터를 받아옴.Axios는 Promise 기반의 HTTP 통신 라이브러리로 fetch보다 더 많은 기능을 제공함. |
⭐비동기(Asynchronous)
1. 동기와 비동기
🚀 동기(Synchronous)
- 동기: 특정 코드의 실행이 완료될 때까지 기다린 후 다음 코드를 수행하는 방식이다.
| 장점 | 모든 작업이 순차적으로 이루어지므로 코드를 단순한 구조로 작성할 수 있고, 실행 흐름을 쉽게 예측할 수 있음 |
| 단점 | 앞의 작업이 끝나기 전까지 다음 코드가 실행되지 않으므로 이후 작업들이 지연됨 |
🚀 비동기(Asynchronous)
- 비동기: 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 수행하는 방식이다.
| 장점 | 앞의 작업이 끝나지 않아도 바로 다음 작업을 실행할 수 있어 효율적임 |
| 단점 | 코드가 예측한 대로 실행되지 않을 수 있으므로, Callback이나 Promise 등으로 순서를 제어해야 함 |
JavaScript는 싱글 스레드 기반으로 동작하는 언어로 기본적으로는 동기적으로 작동한다. 그러나 JavaScript가 실행되는 런타임 환경(브라우저, Node.js)에서 비동기 처리를 지원한다.
2. 타이머 관련 API
🚀 setTimeout(callback, millisecond): 일정 시간 후에 함수를 한 번 실행한다.
- 매개변수: 실행할 콜백 함수, 콜백 함수 실행 전 기다려야 할 시간 (밀리초)
- return 값: 임의의 타이머 ID
setTimeout(function () {
console.log('1초 후 실행');
}, 1000);
// 123
🚀 clearTimeout(timerId): setTimeout 타이머를 종료한다.
- 매개변수: 타이머 ID
- return 값: 없음
const timer = setTimeout(function () {
console.log('10초 후 실행');
}, 10000);
clearTimeout(timer);
// setTimeout이 종료됨.
🚀 setInterval(callback, millisecond): 일정 시간 간격으로 함수를 반복적으로 실행한다.
- 매개변수: 실행할 콜백 함수, 반복적으로 함수를 실행시키기 위한 시간 간격 (밀리초)
- return 값: 임의의 타이머 ID
setInterval(function () {
console.log('1초마다 실행');
}, 1000);
// 345
🚀 clearInterval(timerId): setInterval 타이머를 종료한다.
- 매개변수: 타이머 ID
- return 값: 없음
const timer = setInterval(function () {
console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// setInterval이 종료됨.
3. Callback
- Callback은 비동기로 작동하는 코드의 실행 순서를 제어할 수 있는 방법 중 하나이다.
// 터미널에 `node index.js`를 입력하여 비동기 코드가 작동하는 순서를 확인해보세요.
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 함수를 통해 비동기 코드의 순서를 제어할 수 있지만 코드가 길어질 수록 복잡해지고 가독성이 낮아지는 Callback Hell이 발생하는 단점이 있습니다.`
);
4. Promise
- Promise: 비동기 코드를 제어할 수 있는 방법 중 하나로, Callback Hell을 방지하는 역할을 한다.
new Promise로 Promise 객체를 생성하며, 비동기 처리를 위한 콜백 함수를 인수로 전달받는다. 콜백 함수는(resolve, reject)를 인수로 전달받는다.
resolve: 작업이 성공했을 때 실행하는 함수로,.then()을 이용해 결과값을 전달한다.reject: 작업이 실패했을 때 실행하는 함수로,.catch()를 이용해 에러를 전달한다.
let promise = new Promise((resolve, reject) => {
// 1. 정상적으로 처리되는 경우
// resolve의 인자에 값을 전달할 수도 있습니다.
resolve(value);
// 2. 에러가 발생하는 경우
// reject의 인자에 에러메세지를 전달할 수도 있습니다.
reject(error);
});
🚀 Promise 객체의 내부 프로퍼티: state와 result 내부 프로퍼티를 가진다. 직접 접근할 수 없으며 .then, .catch, .finally 메서드를 사용해야 접근할 수 있다.
| 프로퍼티 | 초기값 | resolve 호출 시 | reject 호출 시 |
| state | pending (대기) | fulfilled (이행) | rejected (거부) |
| result | undefined | resolve(value)의 value | reject(error)의 error |
🚀 .then(): 작업이 성공했을 때 결과값을 받아 처리한다. 리턴한 값이 Promise이면 그 결과값을 다음 .then()의 인자로 전달한다.
let promise = new Promise((resolve, reject) => {
resolve("성공");
});
promise.then(value => {
console.log(value);
// "성공"
})
🚀 .catch(): 에러가 발생했을 때 reject 함수가 호출되며, .catch() 메서드로 에러를 처리한다.
let promise = new Promise(function(resolve, reject) {
reject(new Error("에러"))
});
promise.catch(error => {
console.log(error);
// Error: 에러
})
🚀 .finally(): 성공·실패 여부와 관계없이 무조건 실행된다.
let promise = new Promise(function(resolve, reject) {
resolve("성공");
});
promise
.then(value => {
console.log(value);
// "성공"
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("성공이든 실패든 작동!");
// "성공이든 실패든 작동!"
})
🚀 Promise chaining: 비동기 작업을 순차적으로 진행해야 하는 경우 .then()을 연달아 연결하여 사용한다.
let promise = new Promise(function(resolve, reject) {
resolve('성공');
});
promise
.then((value) => {
console.log(value);
return '성공';
})
.then((value) => {
console.log(value);
return '성공';
})
.then((value) => {
console.log(value);
return '성공';
})
.catch((error) => {
console.log(error);
return '실패';
})
.finally(() => {
console.log('성공이든 실패든 작동!');
});
🚀 Promise.all(): 여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용한다. 배열 안의 Promise 중 하나라도 에러가 발생하면 즉시 종료된다.
// 기존 방식
const result = [];
promiseOne()
.then(value => {
result.push(value);
return promiseTwo();
})
.then(value => {
result.push(value);
return promiseThree();
})
.then(value => {
result.push(value);
console.log(result);
// ['1초', '2초', '3초']
})
// Promise.all() 사용
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
.then((value) => console.log(value))
// ['1초', '2초', '3초']
.catch((err) => console.log(err));
⚠️ Promise Hell: Promise를 통해 비동기 코드의 순서를 제어할 수 있지만, .then()이 깊이 중첩되면 Callback Hell과 유사하게 코드가 복잡해지고 가독성이 낮아지는 Promise Hell이 발생할 수 있다.
5. Async / Await
- Async/Await: 복잡한 Promise 코드를 더 간결하게 작성할 수 있도록 해준다.
- 함수 앞에
async키워드를 사용하고,async함수 내에서만await키워드를 사용할 수 있다. await키워드가 작성된 코드가 동작을 완료하고 나서야 다음 순서의 코드가 동작한다.
🚀 async 함수의 실행 흐름
await를 만나면 async 함수의 실행을 잠시 멈춘다.- Promise 작업이 끝나길 기다린다.
- 작업이 완료되면 async 함수를 다시 실행한다.
// 함수 선언식
async function funcDeclarations() {
await 작성하고자 하는 코드
...
}
// 함수 표현식
const funcExpression = async function () {
await 작성하고자 하는 코드
...
}
// 화살표 함수
const ArrowFunc = async () => {
await 작성하고자 하는 코드
...
}
⭐Node.js
1. Node.js 모듈 사용법
🚀 require: JavaScript 코드 상단에 require 구문을 이용하여 다른 파일이나 모듈을 불러온다.
const fs = require('fs'); // 파일 시스템 모듈을 불러옵니다
const dns = require('dns'); // DNS 모듈을 불러옵니다
// 이제 fs.readFile 메서드 등을 사용할 수 있습니다!
🚀 서드 파티(3rd-party) 모듈: 해당 프로그래밍 언어에서 공식적으로 제공하는 빌트인 모듈(built-in module)이 아닌 모든 외부 모듈을 말한다. 사용 전에 반드시 npm install로 설치해야 한다.
npm install underscore
설치 후에는 내장 모듈과 동일하게 require 구문으로 불러와 사용할 수 있다.
const _ = require('underscore');
⭐fetch API
1. fetch를 이용한 네트워크 요청
- fetch API: 특정 URL로부터 정보를 비동기적으로 받아오는 브라우저 내장 API이다.
fetch()는 Promise를 반환하므로.then(),.catch()로 결과를 처리한다.
let url = "https://koreanjson.com/posts/1";
fetch(url)
.then((response) => response.json())
.then((json) => console.log(json))
.catch((error) => console.log(error));
[코드] 개발자 도구의 콘솔에서 fetch API를 사용하여 데이터를 요청하는 예시
function getNewsAndWeather() {
return fetch(newsURL)
.then((response) => response.json())
.then((news) => {
return fetch(weatherURL)
.then((res) => res.json())
.then((weather) => {
return {news: news.data, weather}
})
})
}
[코드] fetch를 중첩하여 두 개의 URL에서 데이터를 순차적으로 받아오는 예시
2. Axios
- Axios: 브라우저와 Node.js 환경 모두에서 사용 가능한 Promise 기반의 HTTP 비동기 통신 라이브러리이다.
- Axios는 서드 파티 라이브러리이므로 사용 전에 반드시 설치가 필요하다.
npm install axios
🚀 Axios 주요 메서드
| 메서드 | 용도 | 사용법 |
| GET | 정보를 요청할 때 사용함 | axios.get("url"[, config]) |
| POST | 서버에 데이터를 보낼 때 사용함 | axios.post("url"[, data[, config]]) |
⭐후기
- 동기와 비동기의 차이를 단순히 개념으로만 알고 있었는데, 타이머 API 예시를 통해 실제로 코드가 어떤 순서로 실행되는지 체감할 수 있었다.
- fetch와 Axios의 차이를 정리하면서, 자동 JSON 변환과 에러 처리가 편리한 Axios를 많이 선호한다는 것을 알게 되었다.
⭐참고자료
1) MDN Web Docs, "Using Promises", https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises
2) MDN Web Docs, "async function", https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/async_function
3) MDN Web Docs, "Fetch API", https://developer.mozilla.org/ko/docs/Web/API/Fetch_API
4) Axios 공식 문서, https://axios-http.com/kr/docs/intro
이 글은 코드스테이츠 x KNU가 주최한 직무역량캠프에서 공부한 내용을 작성한 것입니다.
'개발일지 > SW직무역량 부트캠프' 카테고리의 다른 글
| [DAY9] React State & Props (0) | 2023.07.10 |
|---|---|
| [DAY8] React SPA (0) | 2023.07.10 |
| [DAY6] JS/브라우저 DOM (0) | 2023.07.07 |
| [DAY6] JavaScript 고차 함수 (0) | 2023.07.06 |
| [DAY 5] JavaScript 핵심 개념과 주요 문법 (0) | 2023.07.06 |