브라우저에서 사용할 수 있는 비동기 흐름은 타이머 혹은 DOM 이벤트와 관련된 상황으로 다소 한정적이지만, Node.js의 경우 많은 API가 비동기로 작성되어 있습니다.
Node.js 소개 문서의 첫 단락은 Node.js의 정의부터 시작합니다.
Node.js는 "비동기 이벤트 기반 JavaScript 런타임"입니다.
Node.js 모듈을 사용하는 방법을 먼저 학습하고, 이를 통해 비동기 상황을 연출하고 연습합니다.
모듈이 뭔가요? 건축으로부터 비롯된 모듈이라는 단어는, 어떤 기능을 조립할 수 있는 형태로 만든 부분입니다. 그중 fs(File System) 모듈은, PC의 파일을 읽거나 저장하는 등의 일을 할 수 있게 도와줍니다.
개발자는 자신이 이해하는 범위만큼 모듈을 사용할 수 있습니다.
예를 들어, DNS에 대한 지식을 알고 있다면, DNS 모듈 사용법 문서에서 관련 메서드를 사용할 수 있습니다.
당장 DNS가 무엇인지 몰라도 괜찮습니다. 파일 시스템 모듈이 파일을 읽거나 저장하는 기능을 구현할 수 있도록 돕는다는 것만 아시면 됩니다.
메서드 목록을 살펴보면, 파일을 읽을 때에 쓸법한 메서드 이름을 찾을 수 있습니다. 물론, 처음부터 필요한 메서드를 정확하게 찾는 일은 쉽지 않습니다.
파일을 읽을 때에는 readFile이라는 메서드가 적합합니다. 파일의 저장은 어떨까요? saveFile이라는 메서드는 찾을 수 없지만, 비슷해 보이는 메서드가 있습니다. 파일을 저장할 때에는 writeFile을 쓰면 됩니다.
모든 모듈은 '모듈을 사용하기 위해 불러오는 과정'이 필요합니다. 브라우저에서 다른 파일을 불러올 때에는 다음과 같이 script 태그를 이용했습니다.
<script src="불러오고싶은_스크립트.js"></script>
Node.js는 JavaScript 코드 가장 상단에 require 구문을 이용하여 다른 파일을 불러옵니다.
const fs = require('fs'); // 파일 시스템 모듈을 불러옵니다
const dns = require('dns'); // DNS 모듈을 불러옵니다
// 이제 fs.readFile 메서드 등을 사용할 수 있습니다!
서드 파티 모듈(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');
비동기 요청의 가장 대표적인 사례는 단연 네트워크 요청입니다. 네트워크를 통해 이루어지는 요청은 그 형태가 다양합니다. 그중에서 URL로 요청하는 경우가 가장 흔합니다. URL로 요청하는 것을 가능하게 해 주는 API가 바로 fetch API입니다.
다음은 흔히 볼 수 있는 포털 사이트입니다.
이 사이트는 시시각각 변하는 정보와, 늘 고정적인 정보가 따로 분리되어 있는 것을 확인할 수 있습니다. 이 중에서 최신 뉴스나 날씨/미세먼지 정보가 바로 동적으로 데이터를 받아야 하는 정보입니다.
이럴 때 많은 웹사이트에서는 해당 정보만 업데이트하기 위해 요청 API를 이용합니다. 그중 대표적인 fetch API를 이용해 해당 정보를 원격 URL로부터 불러오는 경우를 설명합니다. 다음은 원격 URL로부터 정보를 받아와서 특정 DOM 엘리먼트를 업데이트하는 콘셉트를 도식화한 그림입니다.
fetch API는 위와 같이, 특정 URL로부터 정보를 받아오는 역할을 합니다. 이 과정이 비동기로 이루어지기 때문에, 경우에 따라 다소 시간이 걸릴 수 있습니다. 이렇게 시간이 소요되는 작업을 요구할 경우에는 blocking이 발생하면 안 되므로, 특정 DOM에 정보가 표시될 때까지 로딩 창을 대신 띄우는 경우도 있습니다.
et url =
"https://koreanjson.com/posts/1";
fetch(url)
.then((response) => response.json())
.then((json) => console.log(json))
.catch((error) => console.log(error));
앞서 fetch API를 통해 특정 URL로부터 정보를 받아오는 연습을 하셨습니다.
이번에는 fetch API와 비슷한 역할을 하는 라이브러리인 Axios에 대해 알아보겠습니다.
Axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리입니다.
Axios는 Fetch API보다 사용이 간편하면서 추가적인 기능들이 포함되어 있습니다.
Axios는 써드파티 라이브러리이기 때문에 사용하기 위해서는 설치해야 합니다.
npm install axios
Axios는 fetch API와 기본 원리는 같습니다. 다음은 GET, POST 요청에 대해서 알아보도록 하겠습니다.
GET 요청은 일반적으로 정보를 요청하기 위해 사용되는 메서드입니다. 첫 번째 인자에는 url주소가 들어갑니다. url주소는 필수입니다. 두 번째 인자에는 요청 시 사용할 수 있는 옵션들을 설정하게 됩니다. 옵션의 경우 필수는 아닙니다.
axios.get("url"[,config])
아래는 fetch API와 axios GET 요청의 예시입니다. 이를 통해 fetch API와 axios의 사용법과 차이점을 확인해 보세요. 또한, Promise 버전과 Async / Await 버전도 있으니 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>
`;
// 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>
`;
POST 요청은 서버에게 데이터를 보내기 위해 사용되는 메서드입니다. 첫 번째 인자에는 url주소가 들어갑니다. url주소는 필수입니다. 두 번째 인자에는 요청 시 보낼 데이터를 설정하게 됩니다. 옵션의 경우 필수는 아니지만 상황에 따라 설정해주어야 합니다.
axios.post("url"[, data[, config]])
// 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>
`;
// 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>
`;