Node.js 교과서 - 03 ( 노드 기능 알아보기 )

몽슈뜨·2023년 1월 20일
0

Node.js 교과서

목록 보기
3/4
post-thumbnail
post-custom-banner

✨REPL

  • 자바스크립트는 스크립트 언어라서
    즉석에서 코드를 실행할 수 있음
    • REPL이라는 콘솔 제공
    • R(Read), E(Evaluate), P(Print), L(Loop)
    • 윈도에서는 명령 프롬프트, 맥이나 리눅스에서는 터미널에 node 입력

  • 프롬프트가 > 모양으로 바뀌면, 자바스크립트 코드 입력
  • 입력한 값의 결괏값이 바로 출력됨.
    • 간단한 코드를 테스트하는 용도로 적합
    • 긴 코드를 입력하기에는 부적합

✨JS 파일을 만들어 실행하기

  • 자바스크립트 파일을 만들어 통째로 코드를 실행하는 방법
    • 아무 폴더(디렉터리)에서 helloWorld.js를 만들어보자
    • node [자바스크립트 파일 경로]로 실행
    • 실행 결괏값이 출력됨

✨모듈

  • 노드는 자바스크립트 코드를 모듈로 만들 수 있음
    • 모듈: 특정한 기능을 하는 함수나 변수들의 집합
    • 모듈로 만들면 여러 프로그램에서 재사용 가능

  • 같은 폴더 내에 var.js, func.js, index.js 만들기
    • 파일 끝에 module.exports로 모듈로 만들 값을 지정
    • 다른 파일에서 require(파일 경로)로 그 모듈의 내용 가져올 수 있음



  • node index로 실행
    • const { odd, even } 부분은 module.exports를 구조분해 할당한 것임

  • module.exports 외에도 exports로 모듈을 만들 수 있음
    • 모듈 예제의 var.js를 다음과 같이 바꾼 후 실행
    • 동일하게 동작함
    • 동일한 이유는 module.exports와 exports가 참조 관계이기 때문
    • exports에 객체의 속성이 아닌 다른 값을 대입하면 참조 관계가 깨짐

  • 노드에서 this를 사용할 때 주의점이 있음
    • 최상위 스코프의 this는 module.exports를 가리킴
    • 그 외에는 브라우저의 자바스크립트와 동일
    • 함수 선언문 내부의 this는 global(전역) 객체를 가리킴

  • 몇 가지 알아둘 만한 속성이 있음 < require >
    • require가 제일 위에 올 필요는 없음
    • require.cache에 한 번 require한 모듈에 대한 캐슁 정보가 들어있음.
    • require.main은 노드 실행 시 첫 모듈을 가리킴.


  • 모듈 A가 B를 require하고, B가 다시 A를 require 하는 경우
    무한 반복을 막기 위해 순환 참조 대상이 빈 객체가 됨


ES 모듈

  • 자바스크립트 자체 모듈 시스템 문법이 생김
    • mjs 확장자를 사용하거나 package.json에 type: “module”을 추가해야 함.
    • 크게는 require => import,
      module.exports => export default,
      exports => export를 쓰는 것으로 바뀜


  • CommonJS와 ES 모듈의 차이

다이내믹 임포트, top level await

  • 코드 중간에 동적으로 불러올 수 있음
    • Commonjs에서는 require()
    • ES 모듈에서는 import()
  • mjs 파일에서 최상위 스코프에선 async 없이 await할 수 있음

__filename, __dirname

  • __filename: 현재 파일 경로
  • __dirname: 현재 폴더(디렉터리) 경로
  • ES 모듈에서는 쓸 수 없어서 import.meta.url을 써야 함

✨노드 내장 객체


global

  • 노드의 전역 객체
    • 브라우저의 window같은 역할
    • 모든 파일에서 접근 가능
    • window처럼 생략도 가능(console, require도 global의 속성)


global 속성 공유

  • global 속성에 값을 대입하면 다른 파일에서도 사용 가능

console 객체

  • 브라우저의 console 객체와 매우 유사
    • console.time, console.timeEnd: 시간 로깅
    • console.error: 에러 로깅
    • console.log: 평범한 로그
    • console.dir: 객체 로깅
    • console.trace: 호출스택 로깅

  • node console로 실행

  • 타이머 메서드

  • set 메서드에 clear 메서드가 대응됨

    • set 메서드의 리턴 값(아이디)을 clear 메서드에 넣어 취소
    • setTimeout(콜백 함수, 밀리초): 주어진 밀리초(1000분의 1초) 이후에 콜백 함수를 실행합니다.
    • setInterval(콜백 함수, 밀리초): 주어진 밀리초마다 콜백 함수를 반복 실행합니다.
    • setImmediate(콜백 함수): 콜백 함수를 즉시 실행합니다.
    • clearTimeout(아이디): setTimeout을 취소합니다.
    • clearInterval(아이디): setInterval을 취소합니다.
    • clearImmediate(아이디): setImmediate를 취소합니다.
  • setTimeout(콜백, 0)보다 setImmediate 권장


process

  • 현재 실행중인 노드 프로세스에 대한 정보를 담고 있음

process.env

  • 시스템 환경 변수들이 들어있는 객체
    • 비밀키 (데이터베이스 비밀번호, 서드파티 앱 키 등)
      를 보관하는 용도로도 쓰임
    • 환경 변수는 process.env로 접근 가능

    • 일부 환경 변수는 노드 실행 시 영향을 미침
    • 예시) NODE_OPTIONS(노드 실행 옵션),
      UV_THREADPOOL_SIZE(스레드풀 개수)
      max-old-space-size는 노드가 사용할 수 있는 메모리를 지정하는 옵션

process.nextTick(콜백)

  • 이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를
    우선적으로 처리함
    • 너무 남용하면 다른 콜백 함수들 실행이 늦어짐
    • 비슷한 경우로 promise가 있음(nextTick처럼 우선순위가 높음)
    • 아래 예제에서 setImmediate, setTimeout보다
      promise와 nextTick이 먼저 실행됨

마이크로태스크

  • Promise, nextTick 등
    setImmediate, setTimeout보다 promise와 nextTick이 먼저 실행됨

process.exit

  • 현재의 프로세스를 멈춤
    코드가 없거나 0이면 정상 종료
    이외의 코드는 비정상 종료를 의미함

✨노드 내장 모듈

OS

  • 운영체제의 정보를 담고 있음
    모듈은 require로 가져옴(내장 모듈이라 경로 대신 이름만 적어줘도 됨)

os 모듈 메서드

  • os.arch(): process.arch와 동일합니다.
  • os.platform(): process.platform과 동일합니다.
  • os.type(): 운영체제의 종류를 보여줍니다.
  • os.uptime(): 운영체제 부팅 이후 흐른 시간(초)을 보여줍니다.
    process.uptime()은 노드의 실행 시간이었습니다.
  • os.hostname(): 컴퓨터의 이름을 보여줍니다.
  • os.release(): 운영체제의 버전을 보여줍니다.
  • os.homedir(): 홈 디렉터리 경로를 보여줍니다.
  • os.tmpdir(): 임시 파일 저장 경로를 보여줍니다.
  • os.cpus(): 컴퓨터의 코어 정보를 보여줍니다.
  • os.freemem(): 사용 가능한 메모리(RAM)를 보여줍니다.
  • os.totalmem(): 전체 메모리 용량을 보여줍니다.

path

  • 폴더와 파일의 경로를 쉽게 조작하도록 도와주는 모듈
    운영체제별로 경로 구분자가 다름(Windows: ‘\’, POSIX: ‘/’)

path 모듈 메서드

  • path.sep: 경로의 구분자입니다. Windows는 \, POSIX는 /입니다.

  • path.delimiter: 환경 변수의 구분자입니다. process.env.PATH를 입력하면 여러 개의 경로가 이 구분자로 구분되어 있습니다. Windows는 세미콜론(;)이고 POSIX는 콜론(:)입니다.

  • path.dirname(경로): 파일이 위치한 폴더 경로를 보여줍니다.

  • path.extname(경로): 파일의 확장자를 보여줍니다.

  • path.basename(경로, 확장자): 파일의 이름(확장자 포함)을 보여줍니다. 파일의 이름만 표시하고 싶다면 basename의 두 번째 인자로 파일의 확장자를 넣어주면 됩니다.

  • path.parse(경로): 파일 경로를 root, dir, base, ext, name으로 분리합니다.

  • path.format(객체): path.parse()한 객체를 파일 경로로 합칩니다.

  • path.normalize(경로): /나 \를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환해줍니다.

  • path.isAbsolute(경로): 파일의 경로가 절대경로인지 상대경로인지 true나 false로 알려줍니다.

  • path.relative(기준경로, 비교경로): 경로를 두 개 넣으면 첫 번째 경로에서 두 번째 경로로 가는 방법을 알려줍니다.

  • path.join(경로, .. .): 여러 인자를 넣으면 하나의 경로로 합쳐줍니다. 상대경로인 ..(부모 디렉터리)과 .(현 위치)도 알아서 처리해줍니다.

  • path.resolve(경로, .. .): path.join()과 비슷하지만 차이가 있습니다. 차이점은 다음에 나오는 Note에서 설명합니다.


    url 모듈
  • 인터넷 주소를 쉽게 조작하도록 도와주는 모듈
    url 처리에 크게 두 가지 방식이 있음(기존 노드 방식 vs WHATWG 방식)
    요즘은 WHATWG 방식만 사용함
    WHATWG 방식 주소 체계는 다음과 같음



searchParams

  • WHATWG 방식에서 쿼리스트링(search) 부분 처리를 도와주는 객체
    ?page=3&limit=10&category=nodejs&category=javascript 부분
  • getAll(키): 키에 해당하는 모든 값들을 가져옵니다. category 키에는 두 가지 값, 즉 nodejs와 javascript의 값이 들어 있습니다.
  • get(키): 키에 해당하는 첫 번째 값만 가져옵니다.
  • has(키): 해당 키가 있는지 없는지를 검사합니다.
  • keys(): searchParams의 모든 키를 반복기(iterator, ES2015 문법) 객체로 가져옵니다.
  • values(): searchParams의 모든 값을 반복기 객체로 가져옵니다.
  • append(키, 값): 해당 키를 추가합니다. 같은 키의 값이 있다면 유지하고 하나 더 추가합니다.
  • set(키, 값): append와 비슷하지만 같은 키의 값들을 모두 지우고 새로 추가합니다.
  • delete(키): 해당 키를 제거합니다.
  • toString(): 조작한 searchParams 객체를 다시 문자열로 만듭니다. 이 문자열을 search에 대입하면 주소 객체에 반영됩니다.

dns

  • DNS를 다룰 때 사용하는 모듈
    도메인을 통해 IP나 DNS 레코드를 얻고자 할 때 사용
    A(ipv4 주소), AAAA(ipv6 주소), NS(네임서버), SOA(도메인 정보),
    CNAME(별칭, 주로 www가 붙은 주소는 별칭인 경우가 많습니다),
    MX(메일 서버)

단방향 암호화(crypto)

  • 암호화는 가능하지만 복호화는 불가능
    • 암호화: 평문을 암호로 만듦
    • 복호화: 암호를 평문으로 해독
  • 단방향 암호화의 대표 주자는 해시 기법
    • 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식
    • abcdefgh 문자열 -> qvew

Hash 사용하기(sha512)

  • createHash(알고리즘): 사용할 해시 알고리즘을 넣어줍니다.
    • md5, sha1, sha256, sha512 등이 가능하지만, md5와 sha1은 이미 취약점이 발견되었습니다.
    • 현재는 sha512 정도로 충분하지만, 나중에 sha512마저도 취약해지면 더 강화된 알고리즘으로 바꿔야 합니다.
  • update(문자열): 변환할 문자열을 넣어줍니다.
  • digest(인코딩): 인코딩할 알고리즘을 넣어줍니다.
    • base64, hex, latin1이 주로 사용되는데, 그중 base64가 결과 문자열이 가장 짧아 애용됩니다. 결과물로 변환된 문자열을 반환합니다.

pbkdf2

  • 컴퓨터의 발달로 기존 암호화 알고리즘이 위협받고 있음
    sha512가 취약해지면 sha3으로 넘어가야함
    현재는 pbkdf2나, bcrypt, scrypt 알고리즘으로 비밀번호를 암호화
    Node는 pbkdf2와 scrypt 지원

  • 컴퓨터의 발달로 기존 암호화 알고리즘이 위협받고 있음
    crypto.randomBytes로 64바이트 문자열 생성 -> salt 역할
    pbkdf2 인수로 순서대로 비밀번호, salt, 반복 횟수, 출력 바이트, 알고리즘
    반복 횟수를 조정해 암호화하는 데 1초 정도 걸리게 맞추는 것이 권장됨

양방향 암호화

  • 대칭형 암호화(암호문 복호화 가능)
    Key가 사용됨
    암호화할 때와 복호화 할 때 같은 Key를 사용해야 함

  • crypto.createCipheriv(알고리즘, 키, iv): 암호화 알고리즘과 키, 초기화벡터를 넣어줍니다.
    • 암호화 알고리즘은 aes-256-cbc를 사용했습니다.
      다른 알고리즘을 사용해도 됩니다.
    • 사용 가능한 알고리즘 목록은 crypto.getCiphers()를 하면 볼 수 있습니다.
    • 키는 32바이트, 초기화벡터(iv)는 16바이트로 고정입니다.
  • cipher.update(문자열, 인코딩, 출력 인코딩): 암호화할 대상과 대상의 인코딩, 출력 결과물의 인코딩을 넣어줍니다.
    • 보통 문자열은 utf8 인코딩을, 암호는 base64를 많이 사용합니다.
  • cipher.final(출력 인코딩): 출력 결과물의 인코딩을 넣어주면 암호화가 완료됩니다.
  • crypto.createDecipheriv(알고리즘, 키, iv): 복호화할 때 사용합니다. 암호화할 때 사용했던 알고리즘과 키, iv를 그대로 넣어주어야 합니다.
  • decipher.update(문자열, 인코딩, 출력 인코딩): 암호화된 문장, 그 문장의 인코딩, 복호화할 인코딩을 넣어줍니다.
    • createCipher의 update()에서 utf8, base64 순으로 넣었다면 createDecipher의 update()에서는 base64, utf8 순으로 넣으면 됩니다.
  • decipher.final(출력 인코딩): 복호화 결과물의 인코딩을 넣어줍니다.

util

  • 각종 편의 기능을 모아둔 모듈
    deprecated와 promisify가 자주 쓰임

  • util.deprecate: 함수가 deprecated 처리되었음을 알려줍니다.
    • 첫 번째 인자로 넣은 함수를 사용했을 때 경고 메시지가 출력됩니다.
    • 두 번째 인자로 경고 메시지 내용을 넣으면 됩니다. 함수가 조만간 사라지거나 변경될 때 알려줄 수 있어 유용합니다.
  • util.promisify: 콜백 패턴을 프로미스 패턴으로 바꿔줍니다.
    • 바꿀 함수를 인자로 제공하면 됩니다. 이렇게 바꾸어두면 async/await 패턴까지 사용할 수 있어 좋습니다.
    • 3.5.5.1절의 randomBytes와 비교해보세요. 프로미스를 콜백으로 바꾸는 util.callbackify도 있지만 자주 사용되지는 않습니다.
    worker_threads
  • 노드에서 멀티 스레드 방식으로 작업할 수 있음.
    isMainThread: 현재 코드가 메인 스레드에서 실행되는지, 워커 스레드에서 실행되는지 구분
  • 메인 스레드에서는 new Worker를 통해 현재 파일(__filename)을 워커 스레드에서 실행시킴
  • worker.postMessage로 부모에서 워커로 데이터를 보냄
  • parentPort.on(‘message’)로 부모로부터 데이터를 받고, postMessage로 데이터를 보냄

여러 워커스레드 사용하기

  • new Worker 호출하는 수만큼 워커 스레드가 생성됨

child_process

  • 노드에서 다른 프로그램을 실행하고 싶거나 명령어를 수행하고 싶을 때 사용
    • 현재 노드 프로세스 외에 새로운 프로세스를 띄워서 명령을 수행함.
    • 명령 프롬프트의 명령어인 dir을 노드를 통해 실행
      (리눅스라면 ls를 대신 적을 것)

  • async_hooks: 비동기 코드의 흐름을 추적할 수 있는 실험적인 모듈입니다.
  • dgram: UPD와 관련된 작업을 할 때 사용합니다.
  • net: HTTP보다 로우 레벨인 TCP나 IPC 통신을 할 때 사용합니다.
  • perf_hooks: 성능 측정을 할 때 console.time보다 더 정교하게 측정합니다.
  • querystring: URLSearchParams가 나오기 이전에 쿼리스트링을 다루기 위해 사용했던 모듈입니다.
  • string_decoder: 버퍼 데이터를 문자열로 바꾸는 데 사용합니다.
  • tls: TLS와 SSL에 관련된 작업을 할 때 사용합니다.
  • tty: 터미널과 관련된 작업을 할 때 사용합니다.
  • v8: V8 엔진에 직접 접근할 때 사용합니다.
  • vm: 가상 머신에 직접 접근할 때 사용합니다.
  • wasi: 웹어셈블리를 실행할 때 사용하는 실험적인 모듈입니다.

✨파일 시스템 접근하기

  • 파일 시스템에 접근하는 모듈
    파일/폴더 생성, 삭제, 읽기, 쓰기 가능
    웹 브라우저에서는 제한적이었으나 노드는 권한을 가지고 있음
    파일 읽기 예제(결과의 버퍼는 뒤에서 설명함)
  • 콜백 방식 대신 프로미스 방식으로 사용 가능
    require(‘fs’).promises
    사용하기 훨씬 더 편해서 프로미스 방식을 추천함


동기 메서드와 비동기 메서드

  • 노드는 대부분의 내장 모듈 메서드를 비동기 방식으로 처리

    • 비동기는 코드의 순서와 실행 순서가 일치하지 않는 것을 의미

    • 일부는 동기 방식으로 사용 가능

    • 우측 코드 콘솔 예측해보기


    버퍼와 스트림 이해하기

  • 버퍼: 일정한 크기로 모아두는 데이터

    • 일정한 크기가 되면 한 번에 처리
    • 버퍼링: 버퍼에 데이터가 찰 때까지 모으는 작업
  • 스트림: 데이터의 흐름

    • 일정한 크기로 나눠서 여러 번에 걸쳐서 처리
    • 버퍼(또는 청크)의 크기를 작게 만들어서 주기적으로 데이터를 전달
    • 스트리밍: 일정한 크기의 데이터를 지속적으로 전달하는 작업


  • 노드에서는 Buffer 객체 사용
  • from(문자열): 문자열을 버퍼로 바꿀 수 있습니다. length 속성은 버퍼의 크기를 알려줍니다. 바이트 단위입니다.
  • toString(버퍼): 버퍼를 다시 문자열로 바꿀 수 있습니다. 이때 base64나 hex를 인자로 넣으면 해당 인코딩으로도 변환할 수 있습니다.
  • concat(배열): 배열 안에 든 버퍼들을 하나로 합칩니다.
  • alloc(바이트): 빈 버퍼를 생성합니다. 바이트를 인자로 지정해주면 해당 크기의 버퍼가 생성됩니다.

✨이벤트 이해하기

  • events 모듈로 커스텀 이벤트를 만들 수 있음
    • 스트림에 쓰였던 on(‘data’), on(‘end’) 등과 비교
    • on(이벤트명, 콜백): 이벤트 이름과 이벤트 발생 시의 콜백을 연결해줍니다. 이렇게 연결하는 동작을 이벤트 리스닝이라고 부릅니다. event2처럼 이벤트 하나에 이벤트 여러 개를 달아줄 수도 있습니다.
    • addListener(이벤트명, 콜백): on과 기능이 같습니다.
    • emit(이벤트명): 이벤트를 호출하는 메서드입니다. 이벤트 이름을 인자로 넣어주면 미리 등록해뒀던 이벤트 콜백이 실행됩니다.
    • once(이벤트명, 콜백): 한 번만 실행되는 이벤트입니다.
    • myEvent.emit('event3')을 두 번 연속 호출했지만 콜백이 한 번만 실행됩니다.
    • removeAllListeners(이벤트명): 이벤트에 연결된 모든 이벤트 리스너를 제거합니다.event4가 호출되기 전에 리스너를 제거했으므로 event4의 콜백은 호출되지 않습니다.
    • removeListener(이벤트명, 리스너): 이벤트에 연결된 리스너를 하나씩 제거합니다. 역시event5의 콜백도 호출되지 않습니다.
    • off(이벤트명, 콜백): 노드 10 버전에서 추가된 메서드로, removeListener와 기능이 같습니다.
    • listenerCount(이벤트명): 현재 리스너가 몇 개 연결되어 있는지 확인합니다.

✨예외 처리하기

  • 예외(Exception): 처리하지 못한 에러
    • 노드 프로세스/스레드를 멈춤
    • 노드는 기본적으로 싱글 스레드라 스레드가 멈춘다는 것은 프로세스가 멈추는 것
    • 에러 처리는 필수

try catch문

  • 기본적으로 try catch문으로 예외를 처리
    에러가 발생할 만한 곳을 try catch로 감쌈


✅개념정리












profile
개발자되면 맥북사줄께
post-custom-banner

0개의 댓글