JavaScript & TypeScript

[JS] 비동기, Node.js 모듈, fetch API

반응형

하나의 작업이 끝날 때까지, 이어지는 작업을 "막는 것" blocking 이라 하고 이와 같은 경우에 예시를 들자면,

박해커는 김코딩이 주문한 커피가 나오고 나서야 커피를 주문할 수 있다고 할 때에. 김코딩의 커피 주문 완료 시점과 박해커의 커피 주문 시작 시점이 같습니다. 이렇게 시작 시점과 완료 시점이 같은 상황을 "동기적(synchronous)"이다 라고 합니다.

 

하지만 보통 커피숍은 이렇게 운영하지 않습니다. 굉장히 비효율 적이기 때문입니다.

보통 커피숍은 

  • 커피 주문이 blocking 되지 않고, 언제든지 주문을 받을 수 있습니다.
  • 커피가 완성되는 즉시 커피를 제공합니다.
  • 김코딩의 주문 완료 시점과 박해커의 주문 시작 시점이 같을 필요가 없습니다.

Node.js를 만든 개발자도 위 대안이 합리적이라고 생각했습니다. 그래서 Node.js를 non-blocking하고 비동기적(asynchronous)으로 작동하는 런타임으로 개발하게 됩니다. JavaScript의 비동기적 실행(Asynchonous execution)이라는 개념은 웹 개발에서 특히 유용합니다.

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

비동기 흐름은 callback, promise, async/await 중 하나의 문법을 이용하여 구현할 수 있습니다.

 

 

1. 비동기 호출 (Asynchronous call)

Callback, Promise, async/await

비동기란 어떻게 보면 순서를 제어 할 수 없다는 것과 같음을 의미하고.  Callback 으로 제어가 가능 합니다.

 

Callback, Promise, async/await

https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/

 

자바스크립트 비동기 처리와 콜백 함수

(중급) 중급 자바스크립트 개발자가 되기 위한 자바스크립트 비동기 처리와 콜백 함수 이해하기. 콜백 지옥과 해결 방법 등

joshua1988.github.io

 

Reference

A. MDN

B. Google developer web fundamentals

웹의 최신 기술을 전반적으로 학습할 때, 지속적으로 읽을 수 있는 좋은 자료

C. The Modern JavaScript Tutorial

D. 그밖에...

 

 타이머 API

setTimeout(callback, millisecond)

일정 시간 후에 함수를 실행

  • arguments: 실행할 callback 함수, callback 함수 실행 전 기다려야 할 시간 (밀리초)
  • return value: 임의의 타이머 ID
setTimeout(function () {
  console.log('1초 후 실행');
}, 1000);
// 123

setInterval(callback, millisecond)

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

  • arguments: 실행할 callback 함수, 반복적으로 함수를 실행시키기 위한 시간 간격 (밀리초)
  • return value: 임의의 타이머 ID
setInterval(function () {
  console.log('1초마다 실행');
}, 1000);
// 345

clearInterval(timerId)

반복 실행중인 타이머를 종료

  • arguments: 타이머 ID
  • return value: 없음
const timer = setInterval(function () {
  console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// 더 이상 반복 실행되지 않음

setTimeout에 대응하는 clearTimeout도 있음

 

 

 

 

2. Node.js 모듈 사용법

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

 

Node.js 소개 문서의 첫 단락은 Node.js의 정의부터 시작합니다. Node.js는 "비동기 이벤트 기반 자바스크립트 런타임"입니다.

Node.js는 로컬 환경에서 자바스크립트를 실행할 수 있는 자바스크립트 런타임입니다. 그리고 Node.js는 브라우저에서 불가능한 몇 가지 일이 가능합니다.

 

모듈이란 건축으로부터 비롯된 모듈이라는 단어는, 어떤 기능을 조립할 수 있는 형태로 만든 부분입니다. fs(File System) 모듈은, PC의 파일을 읽거나 저장하는 등의 일을 할 수 있게 도와줍니다.

 

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

Node.js 내장 모듈 목록은 다음 링크에서 찾을 수 있습니다. Node.js v14.17.0 Documentation

이해하는 범위만큼 모듈을 사용할 수 있습니다.

예를 들어, DNS에 대한 지식을 알고 있다면, DNS 모듈 사용법 문서에서 관련 메소드를 사용할 수 있습니다. 당장 DNS가 무엇인지 모를 수는 있지만, 파일 시스템 모듈은 파일을 읽거나 저장하는 기능을 구현할 수 있도록 돕습니다. 메소드 목록을 살펴보면, 파일을 읽을 때에 쓸법한 메소드 이름을 찾을 수 있습니다. 물론, 처음부터 필요한 메소드를 정확하게 찾는 일은 쉽지 않습니다.

파일을 읽을 때에는 readFile이라는 메소드가 적합합니다. 파일의 저장은? saveFile 이라는 메소드는 찾을 수 없지만, 비슷해보이는 메소드가 있습니다. 파일을 저장할 때에는 writeFile을 쓰면 됩니다.

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

<script src="불러오고싶은_스크립트.js"></script>
//HTML에서 JavaScript 파일을 불러오는 script 태그


Node.js 에서는 자바스크립트 코드 가장 상단에 require 구문을 이용하여 다른 파일을 불러옵니다.

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

// 이제 fs.readFile 메소드 등을 사용할 수 있습니다!
//Node.js에서 다른 파일을 불러오는 require 구문(CommonJS)

 

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');

Node.js의 3rd-party 'underscore'를 사용할 수 있습니다.

 

fs.readFile을 통해 알아보는 Node.js 공식문서 가이드

메소드 fs.readFile 은 로컬에 존재하는 파일을 읽어옵니다. 14.x 버전 기준으로, fs.readFile의 공식 API 문서 에 안내되어 있는 항목을 설명합니다. 공식 문서와 이 내용을 동시에 놓고 보면, 공식 문서의 구성을 이해하는 데 도움이 됩니다.

 

 

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

메소드 fs.readFile 은 비동기적으로 파일 내용 전체를 읽습니다. 이 메소드를 실행할 때에는 인자 세 개를 넘길 수 있습니다.

Asynchronously reads the entire contents of a file.

 

 

  • path \<string> | \<Buffer> | \<URL> | \<integer>

 

path 에는 파일 이름을 인자로 넘길 수 있습니다. 네 가지 종류의 타입을 넘길 수 있지만 일반적으로 문자열(<string>)의 타입으로 넘깁니다.

fs.readFile('/etc/passwd', ..., ...)
//   /etc/passwd 라는 파일을 불러오는 예제

 

 

 

  • options \<Object> | \<string>

대괄호로 감싼 두번째 인자 options는 넣을 수도 있고, 넣지 않을수도 있습니다.

대괄호는 선택적 인자를 의미합니다. 공식 문서에서도 인자를 세 개를 넣는 경우와, 두 개를 넣는 경우를 예제와 함께 소개하고 있습니다.

options는 객체 형태 또는 문자열로 넘길 수 있습니다. 문자열로 전달할 경우 인코딩을 넘깁니다. 인코딩은 두번째 예제를 참고하세요. 두번째 예제에서는 'utf8' 을 두번째 인자로 전달하는 것을 확인할 수 있습니다.

 

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

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

 

 

 

  • callback \<Function>

콜백 함수를 전달합니다. 파일을 읽고 난 후에 비동기적으로 실행되는 함수입니다.

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

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

 

 

 

 

3. fetch API

 

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

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

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

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

 

 

fetch API 사용법

다음은 원격으로 요청하고, 데이터를 받아올 수 있는 URL이 있습니다.

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

 

let url =
  "https://v1.nocodeapi.com/codestates/google_sheets/YbFMAAgOPgIwEXUU?tabId=최신뉴스";
fetch(url)
  .then((response) => response.json())
  .then((json) => console.log(json))
  .catch((error) => console.log(error));
  
  
  //개발자 도구의 콘솔에서 fetch API를 사용하여 데이터를 요청합니다.

위 예제 유추할 수 있듯이, fetch API는 Promise의 형식으로 이루어져 있습니다.

fetch(url)
  .then((response) => response.json()) // 자체적으로 json() 메소드가 있어, 응답을 JSON 형태로 변환시켜서 다음 Promise로 전달합니다
  .then((json) => console.log(json)) // 콘솔에 json을 출력합니다
  .catch((error) => console.log(error)); // 에러가 발생한 경우, 에러를 띄웁니다

개발자도구의 콘솔에서 fetch API를 사용하여 데이터를 요청합니다.(주석포함)

반응형

'JavaScript & TypeScript' 카테고리의 다른 글

[Node.js] 특징  (0) 2021.08.04
[JS] method 정리  (0) 2021.07.25
[JS] 객체 지향  (1) 2021.06.14
[JS] 고차함수  (1) 2021.06.06
[JS] DOM  (6) 2021.06.06