끄적끄적 코딩
article thumbnail
728x90

비동기 작업의 이해

동기 vs 비동기

동기(synchronous)

- 동기는 데이터의 요청과 결과가 한 자리에서 동시에 일어나는것을 말함
- 요청을 하면 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 함

비동기(Asynchronous)

- 비동기는 동시에 일어나지 않음
- 요청한 결과는 동시에 일어나지 않을 것이라는 약속

동기와 비동기의 장단점

동기

  • 장점 : 설계가 매우 간단하고 직관적
  • 단점 : 결과가 주어질 때까지 아무것도 못하고 대기해야함

비동기

  • 장점 : 요청에 따른 결과가 반환되는 시간 동안 다른 작업을 수행할 수 있음 (자원을 효율적으로 사용 가능)
  • 단점 : 동기식보다 설계가 복잡


웹 애플리케이션을 만들다 보면 처리할 때 시간이 걸리는 작업이 있다. ( 예 : 서버쪽 데이터가 필요해 Ajax 기법을 사용하여 서버의 API를 호출하는 경우, setTimeout 함수를 사용하여 특정 작업을 예약할 때 )


콜백 함수

1초에 걸쳐서 10, 20, 30, 40과 같은 형태로 숫자를 더해서 반환 해주고 싶은 경우

<code />
function increase(number, callback) { setTimeout(() => { const resuilt = number + 10; if (callback) { callback(result); } }, 1000) } increase(0, result => { console.log(result); }); console.log('작업 시작'); increase(0, result => { console.log(result); increase(0, result => { console.log(result); increase(0, result => { console.log(result); increase(0, result => { console.log(result); }); }); }); });

 

실행 결과

이러한 콜백 중첩은 가독성이 나빠짐 ⇒ 이러한 형태의 코드를 ‘콜백 지옥' 이라고 부름 (지양해야 할 코드)

 

Promise

Promise는 콜백 지옥 같은 코드가 형성되지 않게 하는 방안으로 ES6에 도입된 기능

<code />
function increase(number) { const promise = new Promiose((resolve, reject) => { // resolve는 성공, reject는 실패 setTimeout(() => { const result = number + 10; if (result > 50) { // 50보다 높으면 에러 발생시키기 const e = new Error('NumberTooBig'); return reject(e); } resolve(result); // number 값에 +10 후 성공 처리 }, 1000); }); return promise; } increse(0) .then(number => { // Promise에서 resolve된 값은 .then을 통해 받아 올 수 있음 console.log(number); return increase(number); // Promise를 리턴하면 }) .then(number => { // 또 .then으로 처리 가능 console.log(number); return increase(number); }) .then(number => { console.log(number); return increase(number); }) .then(number => { console.log(number); return increase(number); }) .then(number => { console.log(number); return increase(number); }) .catch(e => { // 도중에 에러가 발생한다면 .catch를 통해 알 수 있음 console.log(e); });
  • 함수를 여러 번 감싸는 것이 아니라 .then을 사용하여 그 다음 작업을 설정하기 때문에 콜백 지옥이 형성되지 않음


async/await

async/await는 Promise를 더욱 쉽게 사용할 수 있도록 해 주는 ES2017(ES8)문법

이 문법을 사용하려면 함수의 앞부분에 async 키워드를 추가하고, 해당 함수 내부에서 Promise 앞부분에 await 키워드를 사용

<code />
function increase(number) { const promise = new Promiose((resolve, reject) => { // resolve는 성공, reject는 실패 setTimeout(() => { const result = number + 10; if (result > 50) { // 50보다 높으면 에러 발생시키기 const e = new Error('NumberTooBig'); return reject(e); } resolve(result); // number 값에 +10 후 성공 처리 }, 1000); }); return promise; } async function runTasks() { try { // try/catch 구문을 사용하여 에러를 처리합니다. let result = await increase(0); console.log(result); result = await increase(result); console.log(result); result = await increase(result); console.log(result); result = await increase(result); console.log(result); result = await increase(result); console.log(result); result = await increase(result); console.log(result); result = await increase(result); console.log(result); } catch (e) { console.log(e); } }

 

axios로 API 호출해서 데이터 받아 오기

axios는 현재 가장 많이 사용되고 있는 자바스크립트 HTTP 클라이언트이다. 이 라이브러리의 특징은 HTTP 요청을 Promise 기반으로 처리한다는 점이다.

axios

axios 요청(request) 파라미터 옵션

<code />
/* axios 파라미터 문법 예시 */ axios({ method: "get", // 통신 방식 url: "www.naver.com", // 서버 headers: {'X-Requested-With': 'XMLHttpRequest'} // 요청 헤더 설정 params: { api_key: "1234", langualge: "en" }, // ?파라미터를 전달 responseType: 'json', // default maxContentLength: 2000, // http 응답 내용의 max 사이즈 validateStatus: function (status) { return status >= 200 && status < 300; // default }, // HTTP응답 상태 코드에 대해 promise의 반환 값이 resolve 또는 reject 할지 지정 proxy: { host: '127.0.0.1', port: 9000, auth: { username: 'mikeymike', password: 'rapunz3l' } }, // proxy서버의 hostname과 port를 정의 maxRedirects: 5, // node.js에서 사용되는 리다이렉트 최대치를 지정 httpsAgent: new https.Agent({ keepAlive: true }), // node.js에서 https를 요청을 할때 사용자 정의 agent를 정의 }) .then(function (response) { // response Action });

axios 응답(response) 데이터

<javascript />
axios({ method: "get", // 통신 방식 url: "www.naver.com", // 서버 }) .then(function(response) { console.log(response.data) console.log(response.status) console.log(response.statusText) console.log(response.headers) console.log(response.config) })
<code />
response.data: {}, // 서버가 제공한 응답(데이터) response.status: 200, // `status`는 서버 응답의 HTTP 상태 코드 response.statusText: 'OK', // `statusText`는 서버 응답으로 부터의 HTTP 상태 메시지 response.headers: {}, // `headers` 서버가 응답 한 헤더는 모든 헤더 이름이 소문자로 제공 response.config: {}, // `config`는 요청에 대해 `axios`에 설정된 구성(config) response.request: {} // `request`는 응답을 생성한 요청 // 브라우저: XMLHttpRequest 인스턴스 // Node.js: ClientRequest 인스턴스(리디렉션)

 

Axios

 

Axios

브라우저와 node.js를 위한 Promise 기반 HTTP 클라이언트 라이브러리 Axios는 브라우저와 node.js를 위한 간단한 Promise 기반 HTTP 클라이언트입니다. Axios는 확장 가능한 인터페이스를 가진 작은 패키지로

axios-http.com

 

정리

리액트 컴포넌트에서 API를 연동하여 개발할 때 절때 잊지 말아야 할 유의 사항

  • useEffect에 등록하는 함수는 async로 작성하면 안됨 (대신 함수 내부에 async 함수를 따로 만들어 주어야 함)
<code />
// useEffect 를 async await 로 만든 예 useEffect(async () => { const data = await fetchUser(userId); setUser(data); }, [userId]);

async await 함수는 프로미스 객체를 반환하므로 부수효과 함수가 될 수 없다.

부수 효과 함수는 함수만 반환 할 수 있으며, 반환된 함수는 부수 효과 함수가 호출되기 직전과 컴포넌트가 사라지기 직전에 호출된다.


부수 효과 함수란?

  • Side Effect (부수 효과)를 발생시키는 함수
  • Side Effect란?
    • 사이드 이펙트란 사전적 의미로 원래의 목적과 다르게 다른 효과가 발생하는 것
    • 리액트에서 사이드 이펙트란 변경이나 효과가 일어날 때 다른 효과가 발생할 수 있도록 설정하는 것

 

<code />
// 함수 내부에 async 함수를 따로 만든 예 useEffect(() => { async function fetchAndSetUser() { // 1 const data = await fetchUser(userId); setUser(data); } fetchAndSetUser(); // 2 },[userId]);
  1. useEffect 내에서 async await 함수를 만들고
  2. 그 함수를 바로 호출한다.

'React' 카테고리의 다른 글

[React] 리덕스 라이브러리  (0) 2023.07.01
[React] Context API  (0) 2023.06.30
[React] immer  (0) 2023.06.28
[React] 컴포넌트 스타일링  (0) 2023.06.27
[React] 컴포넌트 스타일링  (0) 2023.06.22

검색 태그