Sprint - Async & Promise part 2

조 은길·2022년 1월 19일
0

Sprint

목록 보기
15/19
post-thumbnail

node.js module 사용법

브라우저에서 사용할 수 있는 비동기 흐름은 타이머 혹은 DOM 이벤트와 관련된 상황으로 다소 한정적이지만, node.js의 경우 많은 부분의 API가 비동기로 작성되어 있습니다. node.js 소개 문서의 첫 단락은 "비동기 이벤트 기반 자바스크립트 런타임"이라는 정의로부터 시작하죠.

앞서 Immersive Prep 시간을 통해 node.js가 자바스크립트 환경이라는 것은 이해하셨으리라 생각합니다. 이제 브라우저에서는 불가능하지만, node.js에서만 가능한 몇가지 일들을 살펴볼 것입니다. 이를 통해 비동기 상황을 연습해볼 것이고요, 그에 앞서 어떻게 node.js 모듈을 사용하는 방법을 알아봅시다.

모듈이 뭔가요? 건축으로부터 비롯된 모듈이라는 단어는, 어떤 기능을 떼서 조립할 수 있는 형태로 만든 부분입니다. fs(File System) 모듈은, 파일을 읽거나 저장하는 등의 일을 할 수 있게 돕는 node.js의 한 부분입니다.

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

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

Node.js v12.18.1 Documentation

우리가 이해하는 컴퓨터 지식의 범위만큼 모듈을 사용할 수 있습니다. 예를 들어, DNS에 대한 지식을 알고 있다면, DNS 모듈 사용법 문서에서 관련 메소드를 사용할 수 있습니다. 당장 DNS가 무엇인지 모를 수는 있지만, 파일 시스템 모듈 같은 경우에는 여러분들도 잘 알고 있겠죠. 예를 들어, 파일을 읽거나 저장하는 개념은 이해하고 있으리라 생각됩니다. 메소드 목록을 살펴보면 파일을 읽을 때에 쓸법한 메소드 이름을 찾게 될겁니다. 물론 처음엔 도움이 필요할 것입니다.

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

무엇이든 간에, 모듈을 사용하기 위해서는 이를 불러오는 과정이 필요합니다. 브라우저에서는 다음과 같이 <script> 태그를 이용했다면,

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

node.js 에서는 자바스크립트 코드 가장 상단에 require 구문을 이용하는 것으로 시작합니다.

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

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

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

3rd-party라는 용어는 프로그래밍 세계에서, 공식적으로 제공하는 것이 아닌 다른 모든 "제3자"의 것을 의미합니다. node.js 문서에 존재하지 않는 것은 node.js에서 공식적으로 제공하지 않는 것이므로 나머지는 전부 3rd-party라고 할 수 있죠. 예를 들어, node.js에서 underscore를 사용한다고 가정해봅시다. 이 때에는, 모듈을 다운로드받기 위해 npm을 이용해야 합니다.

다음과 같이 underscore를 설치할 수 있습니다.

$ npm install underscore

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

const _ = require('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에는 파일 이름을 인자로 넘길 수 있습니다. 네 가지 종류의 타입을 넘길 수 있지만 보통은 문자열()로 넘깁니다.

filename or file descriptor

  • options <Object> | <string>

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

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

    options는 객체 형태 또는 문자열로 넘길 수 있습니다. 문자열로 전달할 경우 인코딩을 넘깁니다. (두번째 예제 참고, 'utf8'로 넘기는 것을 확인할 수 있습니다.)

If options is a string, then it specifies the encoding:

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

// /etc/passed 파일을 옵션을 사용하여 읽습니다.
fs.readFile('/etc/passwd', options, ...) 
  • callback <Function>
    • err <Error>
    • data <string> | <Buffer>

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

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

질문:

data 에는 문자열이나 Buffer가 전달됩니다. 어떤 경우에 문자열로 전달되는 것일까요? 힌트는, 공식 문서의 다음 내용에 나와 있습니다.

If no encoding is specified, then the raw buffer is returned.

이제, 예제 코드를 통해 직접 코드를 작성하고 실험해봅시다. js 파일이 실행되는 디렉토리에 적당한 텍스트 파일(test.txt)을 하나 만든 후 실행해봅시다.

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

자 이제 여러분은, fs.readFile의 사용법을 숙지했습니다.


Part II - fs module

다시 브라우저 환경을 떠나 node.js 환경, 그중에서도 fs module을 살펴봅시다. 브라우저 환경과는 다르게 node.js 앱은 내 컴퓨터에서 직접적으로 실행되므로, 파일을 불러오거나 저장하는 등의 액션이 가능합니다. fs(File System) module 사용법을 잘 익힌다면 "파일 열기", "파일 저장하기" 등을 직접 구현할 수 있습니다. node.js 에서는 파일을 읽는 비동기 함수를 제공합니다. 이를 통해 callback, Promise 구현을 실습해봅시다.

Bare minimum requirements

주어진 테스트를 전부 통과하십시오.

npm run test:part-2 명령으로 테스트를 실행할 수 있습니다.

Getting started

파일 이름에 표시된 번호 순서대로 진행해주세요.

callBack ➡️ promiseConstructor ➡️ basicChaining ➡️ promiseAll ➡️ asyncAwait

  1. part-2/01_callBack.js 파일을 구현하고, 테스트를 통과합니다. 그리고 파일을 불러오는 메소드인 fs.readFile의 공식 API 문서 , 그리고 유어클래스에 제공되는 node.js 공식 문서 가이드를 참고하세요.

    • 테스트를 통과하는 것도 중요하지만, 실제로 getDataFromFile 을 직접 사용해서, 어떻게 작동되는지도 파악해보세요.
  // part-2/01_callBack.js
const fs = require("fs");

const getDataFromFile = function (filePath, callback) {
  // 구현하세요
};

// 다음 코드를 추가해 넣은 후, js 파일을 실행해보세요.
getDataFromFile('README.md', (err, data) => {
  console.log(data)
});

module.exports = {
  getDataFromFile
};
  > node part-2/01_callback.js
  1. part-2/02_promiseConstructor.js 파일을 구현하고, 테스트를 통과합니다. 앞서 callback 이라는 파라미터 대신, Promise의 reject, resolve 함수를 이용하세요.

  2. part-2/03_basicChaining.js은, 앞서 작성한 getDataFromFilePromise를 이용해서 풀어야 합니다.

    • fs 모듈을 직접 사용하는 것이 아닙니다.
    • getDataFromFilePromise을 이용해, files/user1.json 파일과 files/user2.json 파일을 불러오고, 두 파일을 합쳐서 최종적으로 두 객체가 담긴 배열을 만드는 것이 목표입니다.
    • 파일 경로를 찾을 때, user1Path 및 user2Path를 이용하세요. 좀 더 자세한 설명은 Reference를 참고하세요.
    • then이 어떠한 파라미터를 전달받는지에 대한 이해가 있어야 합니다.
    • then의 리턴이 무엇을 의미하는지 이해하고 있어야 합니다.
    • 파일 읽기의 결과가 문자열이므로, JSON.parse를 사용해야 문제를 해결할 수 있을 것입니다.
  3. part-2/04_promiseAll.js은, 마찬가지로 readAllUsersChaining과 정확히 같은 결과를 리턴합니다. 다만, Promise.all을 반드시 사용해서 풀어야 합니다.

    • Promise.all 은 동시에 두 개 이상의 Promise 요청을 한꺼번에 실행하는 함수입니다.

질문

  • Promise.all의 인자는 어떠한 형태인가요?
  • Promise.all을 사용할 경우에 then 메소드의 파라미터는 어떠한 형태인가요?
  • Promise.all의 두 개의 Promise 요청이 전달될 때, 만일 그 중 하나가 rejected 상태가 되는 경우, then메소드를 따라가나요, 아니면 catch 메소드를 따라가나요?
  1. part-2/05_asyncAwait.js은, 앞서 진행한 readAllUsersChaining, readAllUsers과 같은 결과를 리턴합니다. 이번에는 asyncawait 키워드를 사용해서 풀어야 합니다.

해당 github 주소

profile
좋은 길로만 가는 "조은길"입니다😁

0개의 댓글