Unit10 - [JS/Node] 비동기

호박이와 칼림바·2023년 9월 25일

프론트엔드 코스

목록 보기
8/9
post-thumbnail

코드스테이츠 - 유어클래스 콘텐츠를 참고하여 작성하였습니다.

[Day 6]

2023년 7월 4일

📗목차

동기와 비동기


커피숍에서 커피를 주문하려고 줄을 서는 모습을 상상해보자.
커피숍 사정상, 커피를 먼저 주문한 A가 커피를 받을 때까지 줄 서 있는 B가 주문조차 할 수 없다고 하겠다. 이를 우리는 블로킹(blocking)이라 부른다. 하나의 작업이 끝날 때까지 이어지는 작업을 "막는 것"이다.

B는 A가 주문한 커피가 나오고 나서야 커피를 주문할 수 있다. A의 커피 주문 완료 시점과 B의 커피 주문 시작 시점이 같다. 이렇게 시작 시점과 완료 시점이 같은 상황을 "동기적(synchronous)이다."라고 한다.

효율적인 커피숍 운영을 위해서 아래와 같이 커피숍 주문 과정을 변경해보자.

  • 커피 주문이 블로킹(blocking) 되지 않고, 언제든지 주문을 받을 수 있다.
  • 커피가 완성되는 즉시 커피를 제공한다.
    • A의 주문 완료 시점과 B의 주문 시작 시점이 같을 필요가 없다.

Node.js를 만든 개발자도 위 대안이 합리적이라고 생각했다. 그래서 Node.js를 논 블로킹(non-blocking)하고 비동기적(asynchronous)으로 작동하는 런타임으로 개발하게 된다.

JavaScript의 비동기적 실행(Asynchronous execution)이라는 개념은 웹 개발에서 특히 유용하다. 특히 아래 작업은 비동기적으로 작동되어야 효율적이다.

  • 백그라운드 실행, 로딩 창 등의 작업
  • 인터넷에서 서버로 요청을 보내고, 응답을 기다리는 작업
  • 큰 용량의 파일을 로딩하는 작업

동기

JavaScript의 동기 처리란 '특정 코드의 실행이 완료될 때까지 기다리고 난 후 다음 코드를 수행하는 것'을 의미한다.

비동기

JavaScript의 비동기 처리는 ‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드들을 수행하는 것’을 의미한다.

JavaScript의 작동원리

JavaScript는 싱글 스레드 기반으로 동작하는 언어이다. 따라서 동기적으로 작동하게 된다. 그러나 방금까지 JavaScript에서도 비동기 처리가 가능하다고 배웠다. 어떻게 된 걸까? 그 이유는 JavaScript가 작동하는 환경(런타임)에서 비동기 처리를 도와주기 때문에 특별한 작업 없이 비동기 처리를 할 수 있는 것이다.

비동기 Web API


setTimeout(callback, millsecond)

일정 시간 후에 함수를 실행

  • 매개변수: 실행할 콜백 함수, 콜백 함수 실행 전 기다려야 할 시간(밀리초)
  • 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, millsecond)

일정 시간의 간격을 가지고 함수를 반복적으로 실행

  • 매개변수: 실행할 콜백 함수, 반복적으로 함수를 실행시키기 위한 시간 간격(밀리초)
  • 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이 종료됨.

Callback Hell

Callback 함수를 통해 비동기 코드의 순서를 제어할 수 있지만 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Callback Hell이 발생하는 단점이 있다.

// 터미널에 `node 파일명.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이 발생하는 단점이 있습니다.`
);

앞서 확인한 Callback Hell의 현상을 방지하기 위해 Promise가 사용되기 시작했다. Promise에 대해 알아보자.

Promise


비동기로 작동하는 코드를 제어할 수 있는 다른 방법은 Promise를 활용하는 방법이다. 또한 Callback Hell을 방지하는 역할도 수행한다.

new Promise

Promise는 class이기 때문에 new 키워드를 통해 Promise 객체를 생성한다. 또한 Promise는 비동기 처리를 수행할 콜백 함수(executor)를 인수로 전달받는데 이 콜백 함수는 resolve, reject 함수를 인수로 전달받는다.

Promise 객체가 생성되면 executor는 자동으로 실행되고 작성했던 코드들이 작동된다. 코드가 정상적으로 처리가 되었다면 resolve 함수를 호출하고 에러가 발생했을 경우에는 reject 함수를 호출하면 된다.

let promise = new Promise((resolve, reject) => {
	// 1. 정상적으로 처리되는 경우
    // resolve의 인자에 값을 전달할 수 있다.
    resolve(value);
    
    // 2. 에러가 발생하는 경우
    // reject의 인자에 에러메시지를 전달할 수도 있다.
    reject(error);
});
[예시] 프로미스가 정상적으로 처리된 경우의 프로미스 객체 [예시] 프로미스가 에러가 발생한 경우의 프로미스 객체

Promise 객체의 내부 프로퍼티

new Promise가 반환하는 Promise 객체는 state, result 내부 프로퍼티를 갖는다. 하지만 직접 접근할 수 없고 .then, .catch, .finally의 메서드를 사용해야 접근이 가능하다.

state

기본 상태는 pending(대기)입니다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동했다면 fulfilled(이행)로 변경이 되고, 에러가 발생했다면 rejected(거부)가 됩니다.

Result

처음은 undefined입니다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동하여 resolve(value)가 호출되면 value로, 에러가 발생하여 reject(error)가 호출되면 error로 변한다.

then, catch, finally

Then

executor에 작성했던 코드들이 정상적으로 처리가 되었다면 resolve 함수를 호출하고 .then메서드로 접근할 수 있다.

또한 .then 안에서 리턴한 값이 PromisePromise의 내부 프로퍼티 result를 다음 .then의 콜백 함수의 인자로 받아오고, Promise가 아니라면 리턴한 값을 .then의 콜백 함수의 인자로 받아올 수 있다.
아래의 .then과 Promise chaining의 예시를 살펴보면서 동작 방식을 확인해보자.

let promise = new Promise((resolve, reject) => {
  resolve("성공");
});

promise.then(value => {
  console.log(value);
  // "성공"
});

Catch

executor에 작성했던 코드들이 에러가 발생했을 경우에는 reject 함수를 호출하고 .catch 메서드로 접근할 수 있다.

let promise = new Promise(function(resolve, reject) {
  reject(new Error("에러"))
});

promise.catch(error => {
  console.log(error);
  // Error: 에러
});

Finally

executor에 작성했던 코드들의 정상 처리 여부와 상관없이 .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

Promise chaining가 필요하는 경우는 비동기 작업을 순차적으로 진행해야 하는 경우이다. Promise chaining이 가능한 이유는 .then, .catch, .finally의 메서드들은 Promise를 리턴하기 때문이다. 따라서 .then을 통해 연결할 수 있고, 에러가 발생할 경우 .catch로 처리하면 된다.

// 터미널에 `node 파일명.js`를 입력하여 비동기 코드가 작동하는 순서를 확인해보세요.
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
      console.log(string);
    }, Math.floor(Math.random() * 100) + 1);
  });
};

const printAll = () => {
  printString('A')
    .then(() => {
      return printString('B');
    })
    .then(() => {
      return printString('C');
    });
};

printAll();

console.log(
  `아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있습니다!`
);

// 터미널에 'node 파일명.js'을 입력하여 .then, .catch, .finally의 작동박식을 이해해보세요!

let promise = new Promise(function (resolve, reject) {
  resolve('성공');
  // reject("실패");
});

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()

const promiseOne = () => 
  new Promise((resolve, reject) => setTimeout(() => resolve('1초'), 1000));

const promiseTwo = () => 
  new Promise((resolve, reject) => setTimeout(() => resolve('2초'), 2000));

const promiseThree = () => 
  new Promise((resolve, reject) => setTimeout(() => resolve('3초'), 3000));

Promise.all()은 여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용한다.
인자로는 배열을 받는다. 해당 배열에 있는 모든 Promise에서 executor 내 작성했던 코드들이 정상적으로 처리가 되었다면 결과를 배열에 저장해 새로운 Promise를 반환해준다.

앞서 배운 Promise chaining을 사용했을 경우는 코드들이 순차적으로 동작되기 때문에 총 6초의 시간이 걸리게 되는데, 같은 코드가 중복되는 현상도 발생하게 된다.

// 기존
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()은 비동기 작업들을 동시에 처리합니다. 따라서 3초 안에 모든 작업이 종료된다. 또한 Promise chaining로 작성한 코드보다 간결해진 것을 확인할 수 있다.

// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
  .then((value) => console.log(value))
  // ['1초', '2초', '3초']
  .catch((err) => console.log(err));

추가적으로 Promise.all()은 인자로 받는 배열에 있는 Promise 중 하나라도 에러가 발생하면 나머지 Promise의 state와 상관없이 즉시 종료된다.
아래의 예시와 같이 1초 후에 에러가 발생하고 Error: 에러1이 반환된 후로는 더 이상 작동하지 않고 종료된다.

Promise.all([
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러1'))), 1000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러2'))), 2000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러3'))), 3000),
])
	.then((value) => console.log(value))
  .catch((err) => console.log(err));
	// Error: 에러1

Promise Hell

Promise를 통해 비동기 코드의 순서를 제어할 수 있지만 Callback 함수와 같이 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Promise Hell이 발생하는 단점이 있다. 아래의 코드를 살펴보면서 이해해보자.

// 터미널에 `node 파일명.js`를 입력하여 비동기 코드가 작동하는 순서를 확인해보세요.
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(string);
    }, Math.floor(Math.random() * 100) + 1);
  });
};

const printAll = () => {
  printString('A').then((value) => {
    console.log(value);

    printString('B').then((value) => {
      console.log(value);

      printString('C').then((value) => {
        console.log(value);

        printString('D').then((value) => {
          console.log(value);

          printString('E').then((value) => {
            console.log(value);

            printString('F').then((value) => {
              console.log(value);

              printString('G').then((value) => {
                console.log(value);

                printString('H').then((value) => {
                  console.log(value);

                  printString('I').then((value) => {
                    console.log(value);

                    printString('J').then((value) => {
                      console.log(value);

                      printString('K').then((value) => {
                        console.log(value);

                        printString('L').then((value) => {
                          console.log(value);

                          printString('M').then((value) => {
                            console.log(value);

                            printString('N').then((value) => {
                              console.log(value);

                              printString('O').then((value) => {
                                console.log(value);

                                printString('P').then((value) => {
                                  console.log(value);
                                });
                              });
                            });
                          });
                        });
                      });
                    });
                  });
                });
              });
            });
          });
        });
      });
    });
  });
};

printAll();

console.log(
  `아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있지만 Callback 함수와 같이 코드가 길어질수록 복잡해지고 가독성이 낮아지는 Promise Hell이 발생하는 단점이 있습니다.`
);

Async/Await

JavaScript는 ES8에서 async/await키워드를 제공하였다. 이를 통해 복잡한 Promise 코드를 간결하게 작성할 수 있게 되었다. 함수 앞에 async 키워드를 사용하고 async 함수 내에서만 await 키워드를 사용하면 된다. 이렇게 작성된 코드는 await 키워드가 작성된 코드가 동작하고 나서야 다음 순서의 코드가 동작하게 된다.

// 함수 선언식
async function funcDeclarations() {
	await 작성하고자 하는 코드
	...
}

// 함수 표현식
const funcExpression = async function () {
	await 작성하고자 하는 코드
	...
}

// 화살표 함수
const ArrowFunc = async () => {
	await 작성하고자 하는 코드
	...
}

아래의 코드를 살펴보면서 async/await를 이해해보자.

// 터미널에 `node 파일명.js`입력하여 비동기 코드가 작동하는 순서를 확인해보세요.
const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
      console.log(string);
    }, Math.floor(Math.random() * 100) + 1);
  });
};

const printAll = async () => {
  await printString('A');
  await printString('B');
  await printString('C');
};

printAll();

console.log(
  `Async/Await을 통해 Promise를 간결한 코드로 작성할 수 있게 되었습니다.`
);

Node.js

브라우저에서 사용할 수 있는 비동기 흐름은 타이머 혹은 DOM 이벤트와 관련된 상황으로 다소 한정적이지만, Node.js의 경우 많은 API가 비동기로 작성되어 있다. Node.js는 "비동기 이벤트 기반 JavaScript 런타임"이다.

Node.js 모듈을 사용하는 방법을 먼저 학습하고, 이를 통해 비동기 상황을 연출하고 연습해보자.

💭 모듈이 무엇인가?
어떤 기능을 조립할 수 있는 형태로 만든 부분이다. 그중 fs(File System) 모듈은, PC의 파일을 읽거나 저장하는 등의 일을 할 수 있게 도와준다.

Node.js 내장 모듈을 사용하는 방법

모든 모듈은 '모듈을 사용하기 위해 불러오는 과정'이 필요하다. 브라우저에서 다른 파일을 불러올 때에는 다음과 같이 <script> 태그를 이용했다.

<script src="불러오고싶은_스크립트.js"></script>

Node.js는 JavaScript 코드 가장 상단에 require 구문을 이용하여 다른 파일을 불러온다.

const fs = require('fs'); // 파일 시스템 모듈을 불러옵니다
const dns = require('dns'); // DNS 모듈을 불러옵니다

// 이제 fs.readFile 메서드 등을 사용할 수 있습니다!

3rd-party 모듈을 사용하는 방법

서드 파티 모듈(3rd-party module)은 해당 프로그래밍 언어에서 공식적으로 제공하는 빌트인 모듈(built-in module)이 아닌 모든 외부 모듈을 일컫는다. 예를 들어, Node.js에서 underscore는 Node.js 공식 문서에 없는 모듈이기 때문에 서드 파티 모듈이다. underscore와 같은 서드 파티 모듈을 다운로드하기 위해서는 npm을 사용해야 한다.

터미널에서 다음과 같이 입력해 underscore를 설치할 수 있다.

npm install underscore

이제 node_modules에 underscore가 설치되었다. 이제 Node.js 내장 모듈을 사용하듯 require 구문을 통해 underscore를 사용할 수 있다.

const _ = require('underscore');

fs.readFile(path[, options], callback)

메서드 fs.readFile은 비동기적으로 파일 내용 전체를 읽으며, 이 메서드를 실행할 때에는 전달인자 세 개를 받는다.

  • path \<string> | \<Buffer> | \<URL> | \<integer>
    path에는 파일 이름을 전달인자로 받는다. 네 가지 종류의 타입을 넘길 수 있지만 일반적으로 문자열(<string>)의 타입을 받는다.

다음은 'etc/passwd'라는 파일을 불러오는 예제이다.

  fs.readFile('/etc/passwd', ..., ...)
  • options \<Object> | \<string>
    대괄호로 감싼 두 번째 전달인자 options는 넣을 수도 있고, 넣지 않을 수도 있다. 대괄호는 선택적 전달인자를 의미한다.

options는 문자열 또는 객체 형태로 받을 수 있다. 문자열로 전달할 경우 인코딩을 받는다. 밑의 예제에서는 'utf8'을 두 번째 전달인자로 받는 것을 확인할 수 있다.

// /etc/passwd 파일을 'utf8'을 사용하여 읽습니다.
fs.readFile('/etc/passwd', 'utf8', ...);

[코드] 두 번째 전달인자 options에 문자열을 전달한 경우

let options = {
  encoding: 'utf8', // utf8 인코딩 방식으로 엽니다
  flag: 'r' // 읽기 위해 엽니다
}

// /etc/passwd 파일을 options를 사용하여 읽습니다.
fs.readFile('/etc/passwd', options, ...) 

[코드] 두 번째 전달인자 options에 객체를 전달한 경우

  • callback \<Function>
    • err \<Error> | \<AggregateError>
    • data \<string> | \<Buffer>
      콜백 함수를 전달한다. 파일을 읽고 난 후에 비동기적으로 실행되는 함수이다.

콜백 함수에는 두 가지 매개변수가 존재하는데, 에러가 발생하지 않으면 err는 null 이 되며, data에 문자열이나 Buffer라는 객체가 전달된다. data는 파일의 내용입니다.

💭 data에는 문자열이나 Buffer 가 전달된다. 어떤 경우에 문자열로 전달되는 걸까? 힌트는, 공식 문서의 다음 내용에 나와 있다.

If no encoding is specified, then the raw buffer is returned.
→ 인코딩을 지정하지 않으면 원시 버퍼가 반환됩니다.

예제 코드를 통해 직접 코드를 작성하고 실험해 보자.
JavaScript 파일이 실행되는 디렉토리에, 적당한 텍스트 파일(test.txt)을 새롭게 생성한 후 실행해보자.

fs.readFile('test.txt', 'utf8', (err, data) => {
  if (err) {
    throw err; // 에러를 던집니다.
  }
  console.log(data);
});

fetch를 이용한 네트워크 요청

비동기 요청의 가장 대표적인 사례는 단연 네트워크 요청이다. 네트워크를 통해 이루어지는 요청은 그 형태가 다양하다. 그중에서 URL로 요청하는 경우가 가장 흔한데 URL로 요청하는 것을 가능하게 해 주는 API가 바로 fetch API입니다.

흔히 볼 수 있는 사이트를 예시로 들어보겠다.

이 사이트는 시시각각 변하는 정보와, 늘 고정적인 정보가 따로 분리되어 있는 것을 확인할 수 있다. 이 중에서 최신 뉴스나 날씨/미세먼지 정보가 바로 동적으로 데이터를 받아야 하는 정보이다.

이럴 때 많은 웹사이트에서는 해당 정보만 업데이트하기 위해 요청 API를 이용하는데, 그중 대표적인 fetch API를 이용해 해당 정보를 원격 URL로부터 불러오는 경우를 설명한다.

다음은 원격 URL로부터 정보를 받아와서 특정 DOM 엘리먼트를 업데이트하는 콘셉트를 도식화한 그림입니다.

fetch API는 위와 같이, 특정 URL로부터 정보를 받아오는 역할을 한다. 이 과정이 비동기로 이루어지기 때문에, 경우에 따라 다소 시간이 걸릴 수 있다. 이렇게 시간이 소요되는 작업을 요구할 경우에는 blocking이 발생하면 안 되므로, 특정 DOM에 정보가 표시될 때까지 로딩 창을 대신 띄우는 경우도 있다.

fetch API

크롬 브라우저의 새 탭을 연 후, 개발자 도구의 콘솔에 다음과 같이 입력해 보자.

let url =
  "https://koreanjson.com/posts/1";
fetch(url)
  .then((response) => response.json())
  .then((json) => console.log(json))
  .catch((error) => console.log(error));

Axios 란?

앞서 fetch API를 통해 특정 URL로부터 정보를 받아오는 연습을 했다.
이번에는 fetch API와 비슷한 역할을 하는 라이브러리인 Axios에 대해 알아보자. Axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리이다. Axios는 Fetch API보다 사용이 간편하면서 추가적인 기능들이 포함되어 있다.

Fetch API vs Axios

AxiosFetch API
써드파티 라이브러리로 설치가 필요합니다. 빌트인 API라 별도의 설치 필요 없습니다.
자동으로 JSON데이터 형식으로 변환됩니다. .json() 메서드를 사용해야 합니다.

Axois 사용법

Axios는 써드파티 라이브러리이기 때문에 사용하기 위해서는 설치해야 한다.
npm install axios

GET 요청
GET 요청은 일반적으로 정보를 요청하기 위해 사용되는 메서드이다. 첫 번째 인자에는 url주소가 들어간다. (url주소는 필수) 두 번째 인자에는 요청 시 사용할 수 있는 옵션들을 설정하게 된다. (옵션의 경우 필수는 아님)

axios.get("url"[,config])

아래는 fetch API와 axios GET 요청의 예시이다. 이를 통해 fetch API와 axios의 사용법과 차이점을 확인해 보자. 또한, Promise와 Async / Await의 차이점도 같이 확인해 보지.

// Promise ver
fetch('https://koreanjson.com/users/1', { method: 'GET' })
  .then((response) => response.json())
  .then((json) => console.log(json))
  .catch((error) => console.log(error));

// Async / Await ver
// async function request() {
//   const response = await fetch('https://koreanjson.com/users/1', {
//     method: 'GET',
//   });
//   const data = await response.json();
//   console.log(data);
// }

// request();

const appDiv = document.getElementById('app');
appDiv.innerHTML = `
<h1>Fetch API 😊</h1>
<h3>console 창을 확인해주세요! 👇👇👇</h3>
`;

fetch GET 요청


// axios를 사용하기 위해서는 설치한 axios를 불러와야 합니다.
import axios from 'axios';

// Promise ver
axios
  .get('https://koreanjson.com/users/1')
  .then((response) => {
    console.log(response);
    const { data } = response;
    console.log(data);
  })
  .catch((error) => console.log(error));

// Async / Await ver
// async function request() {
//   const response = await axios.get('https://koreanjson.com/users/1');
//   const { data } = response;
//   console.log(data);
// }

// request();

const appDiv = document.getElementById('app');
appDiv.innerHTML = `
<h1>Axios ☺️</h1>
<h3>console 창을 확인해주세요! 👇👇👇</h3>
`;

Axios GET 요청

POST 요청
POST 요청은 서버에게 데이터를 보내기 위해 사용되는 메서드이다. 첫 번째 인자에는 url주소가 들어간다. (url주소는 필수) 두 번째 인자에는 요청 시 보낼 데이터를 설정하게 된다. 옵션의 경우 필수는 아니지만 상황에 따라 설정해주어야 한다.

axios.post("url"[, data[, config]])

아래는 fetch API와 axios POST요청의 예시이다. 이를 통해 fetch API와 axios의 사용법과 차이점을 확인해 보자. 또한, Promise와 Async / Await의 차이점도 같이 확인해 보자.

// Promise ver
fetch('https://koreanjson.com/users', {
  method: 'POST',
  headers: {
    // JSON의 형식으로 데이터를 보내준다고 서버에게 알려주는 역할입니다.
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ nickName: 'ApeachIcetea', age: 20 }),
})
  .then((response) => response.json())
  .then((json) => console.log(json))
  .catch((error) => console.log(error));

// Async / Await ver
// async function request() {
//   const response = await fetch('https://koreanjson.com/users', {
//     method: 'POST',
//     headers: {
//       'Content-Type': 'application/json',
//     },
//     body: JSON.stringify({ nickName: 'ApeachIcetea', age: 20 }),
//   });
//   const data = await response.json();
//   console.log(data);
// }

// request();

const appDiv = document.getElementById('app');
appDiv.innerHTML = `
<h1>Fetch API 😊</h1>
<h3>console 창을 확인해주세요! 👇👇👇</h3>
`;

fetch POST 요청

// axios를 사용하기 위해서는 설치한 axios를 불러와야 합니다.
import axios from 'axios';

// Promise ver
axios
  .post('https://koreanjson.com/users', { nickName: 'ApeachIcetea', age: '20' })
  .then((response) => {
    const { data } = response;
    console.log(data);
  })
  .catch((error) => console.log(error));

// Async / Await ver
// async function request() {
//   const response = await axios.post('https://koreanjson.com/users', {
//     name: 'ApeachIcetea',
//     age: '20',
//   });
//   const { data } = response;
//   console.log(data);
// }

// request();

const appDiv = document.getElementById('app');
appDiv.innerHTML = `
<h1>Axios ☺️</h1>
<h3>console 창을 확인해주세요! 👇👇👇</h3>
`;

Axios POST 요청

profile
프론트엔드 개발자입니다.

0개의 댓글