동기 (Syncronous)와 비동기 (Asynchronous)는 프로그래밍 언어에서 중요한 개념이다
동기
- 동기는 요청 후 응답을 받아야 다음 동작을 실행하는 방식을 말한다. 즉, 요청과 결과가 동시에 일어나기 때문에 코드가 직관적이고 이해하기 쉽다.
- 코드가 짜여진 순서대로 실행된다.
비동기
- 비동기는 요청을 보낸 후 응답과 관계없이 다음 동작을 실행하는 방식이다. 즉, 결과가 나올 때 까지 기다리지 않고 다른 일을 처리할 수 있기 때문에 코드나 순서는 이해하기 어려워도 자원 사용을 좀 더 효율적으로 할 수 있다.
- 코드가 짜여진 순서대로 실행되지 않는다.
자바스크립트에서 동기와 비동기
자바스크립트는 단일 스레드 프로그래밍 언어로 단일 호출 스택이 있어 한 번에 하나의 일을 처리할 수 있다. 그러므로 자바스크립트는 동기 방식으로 진행이 된다. 하나의 호출 스택만 있기 때문에 하나의 함수를 처리하는데 매우 오랜 시간이 걸린다면 다음 실행해야할 함수에 지장을 줄 수 있다는 문제가 발생한다. 이 부분이 바로 비동기의 필요성이다. 단일 호출 스택을 가진 자바스크립트에서 비동기를 구현할 수 있게 하는 방법을 알아보자
해결방안
Callback 함수
- callback 함수는 다른 함수의 인자로써 이용될때나 어떤 이벤트에 의해 호출되어질때 사용하는 함수로, 비동기 처리의 해결방안이 될 수 있지만, callback 함수 안에 callback 함수를 계속 중첩으로 사용하다 보면 코드의 가독성이 매우 나빠지고 로직변경도 어려운 콜백지옥에 빠질 수 있다.
Promise
- 동기적으로 보이는, 비동기 처리 방식
- 프로미스 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다.
- 프로미스를 사용할 때 알아야 하는 가장 기본적인 개념이 바로 프로미스의 상태이다. 여기서 상태란 프로미스의 처리 과정을 의미한다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖는다
- Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
- Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
- Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
Pending (대기)
new Promise();
- new Promise() 메서드를 호출하면 대기 상태가 된다
new Promise(function(resolve, reject) {
// ...
});
- new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve, reject이다.
Fulfilled (이행)
new Promise(function(resolve, reject) {
resolve();
});
- 여기서 콜백 함수의 인자 resolve를 실행하면 이행(Fulfilled) 상태가 된다
그리고 이행 상태가 되면 아래와 같이 then()을 이용하여 처리 결과 값을 받을 수 있다
function getData() {
return new Promise(function(resolve, reject) {
var data = 100;
resolve(data);
});
}
// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
console.log(resolvedData); // 100
});
Rejected (실패)
new Promise()로 프로미스 객체를 생성하면 콜백 함수 인자로 resolve와 reject를 사용할 수 있다고 했다. 여기서 reject를 아래와 같이 호출하면 실패(Rejected) 상태가 된다
new Promise(function(resolve, reject) {
reject();
});
그리고, 실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를 catch()로 받을 수 있다.
function getData() {
return new Promise(function(resolve, reject) {
reject(new Error("Request is failed"));
});
}
// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
console.log(err); // Error: Request is failed
});
Promise 함수를 이용해 비동기 처리를 해보면
function getData() {
return new Promise(function(resolve, reject) {
$.get('url', function(response) {
if (response) {
resolve(response);
}
reject(new Error("Request is failed"));
});
});
}
// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
console.log(data); // response 값 출력
}).catch(function(err) {
console.error(err); // Error 출력
});
- 서버에서 제대로 응답을 받아오면 resolve() 메서드를 호출하고, 응답이 없으면 reject() 메서드를 호출한다. 호출된 메서드에 따라 then()이나 catch()로 분기하여 응답 결과 또는 오류를 출력할 수도 있다.
Async / Await
async/await 은 Promise를 더욱 쉽게 사용할 수 있도록 해 주는 문법이다.
사용하려면 함수의 앞부분에 async 키워드를 추가하고, 해당 함수 내부에서 Promise 앞 부분에 await 키워드를 사용한다.
이렇게 하면 Promise가 끝날 때까지 기다리고, 결과 값을 특정 변수에 담을 수 있다.
function getData(callback) {
return new Promise((resolve)=> {
$.get('url', (response)=> {
resolve(response);
});
});
}
async function callData() {
try {
let result = await getData();// 프로미스 결과를 기다립니다.
console.log(result)
} catch(error) {
console.log(error)
}
}
React 비동기 처리
이런 비동기 처리를 React에서 그나마 편하게 하기 위해 제공하는 훅이 있다.
useState와 useEffect이다.
useState : 변수의 상태를 추적해준다.
const [currentUser, setCurrentUser] = useState(초기에 지정할 내용)
위 코드는 currentUser라는 변수를 useState로 관리한다는 뜻이고 useState가 제공하는 핵심 기능은 추적의 기능을 사용할 수 있어 currentUser라는 변수의 내용이 변하면 자동으로 jsx가 재 렌더링 되어 변화된 변수가 화면에 반영된다.
React에서 이렇게 변수를 useState가 아닌
const currentUser = "hello"
이런 식으로 저장하게 되면 스크립트 내부에서 currentUser변수에 변화가 있어도 jsx는 변수의 변화를 감지하지 못하기 때문에 항상 초기 상태만 표시하게 될 것이다.
useEffect : 변수의 상태를 추적해 뭔가를 하게 해준다.
useEffect(() => {
const load = async () => {
try {
if (user !== undefined) {
setCurrentUser(user);
}
} catch (error) {
console.log("하하");
}
};
load();
console.log("Hello");
}, [user]);
useState와 비슷한 기능의 훅이다. useState는 변수를 추적해 변화가 생긴다면 재 렌더링 하는 기능이라면 useEffect는 변수를 추적해 변화가 생기면 어떠한 기능을 수행할 수 있게 해 준다.
출처 : 아래의 사이트들을 보면서 큰 공부 하였습니다
https://chiefcoder.tistory.com/14
https://higher77.tistory.com/72
'Front-End > React' 카테고리의 다른 글
API를 호출할 때 useState 대신 useSWR을 사용해야 하는 이유 (0) | 2023.01.09 |
---|---|
[React] useEffect와 sideEffect (1) | 2022.08.22 |
[React] 상태관리 (Local State, Global State, Cross Component State) (0) | 2022.08.10 |
[React] Router (0) | 2022.06.06 |
[React] React-Query (0) | 2022.06.06 |