3장. 노드 기본 기능 익히기

My_Code·2024년 1월 8일

Node.js 교과서

목록 보기
3/11
post-thumbnail

다음 내용은 인프런에서 공부한 내용을 복습하는 차원에서 기록한 것입니다.
출처 : https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-js-%EA%B5%90%EA%B3%BC%EC%84%9C


💻 3.1 REPL 사용하기

📌 REPL

✏️ 자바스크립트는 스크립트 언어라서 즉석에서 코드를 실행할 수 있음

  • REPL이라는 콘솔 제공
  • R(Read), E(Evaluate), P(Print), L(Loop)
  • 윈도에서는 명령 프롬프트, 맥이나 리눅스에서는 터미널에 node 입력

✏️ 프롬프트가 > 모양으로 바뀌면, 자바스크립트 코드 입력

✏️ 입력한 값의 결괏값이 바로 출력됨

  • 간단한 코드를 테스트하는 용도로 적합
  • 긴 코드를 입력하기에는 부적합
  • console.log()에 대한 출력은 기본적으로 undefined

💻 3.2 JS 파일 실행하기

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

✏️ 자바스크립트 파일을 만들어 통째로 코드를 실행하는 방법

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

💻 3.3 모듈로 만들기

📌 모듈

✏️ 노드는 자바스크립트 코드를 모듈로 만들 수 있음

  • 모듈: 특정한 기능을 하는 함수나 변수들의 집합
  • 모듈로 만들면 여러 프로그램에서 재사용 가능

📌 파일 간의 모듈 관계

✏️ node index로 실행

  • const { odd, even } 부분은 module.exports를 구조분해 할당한 것임(2장 참고)

📌 this

✏️ 노드에서 this를 사용할 때 주의점이 있음

  • 최상위 스코프의 this는 module.exports를 가리킴
  • 그 외에는 브라우저의 자바스크립트와 동일
  • 함수 선언문 내부의 this는 global(전역) 객체를 가리킴

📌 require의 특성

✏️ 몇 가지 알아둘 만한 속성이 있음

  • require가 제일 위에 올 필요는 없음
  • require.cache에 한 번 require한 모듈에 대한 캐슁 정보가 들어있음.
  • require.main은 노드 실행 시 첫 모듈을 가리킴

📌 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을 써야 함


💻 3.4 노드 내장 객체 알아보기

📌 process.env

✏️ 시스템 환경 변수들이 들어있는 객체

  • 비밀키(데이터베이스 비밀번호, 서드파티 앱 키 등)를 보관하는 용도로도 쓰임
  • 환경 변수는 process.env로 접근 가능
const secretId = process.env.SECRET_ID;
const secretCode = process.env.SECRET_CODE;
  • 일부 환경 변수는 노드 실행 시 영향을 미침
  • 예시) NODE_OPTIONS(노드 실행 옵션), UV_THREADPOOL_SIZE(스레드풀 개수)
    - max-old-space-size는 노드가 사용할 수 있는 메모리를 지정하는 옵션
NODE_OPTIONS = --max-old-space-size=8192
UV_THREADPOLL_SIZE=8

📌 마이크로태스크

✏️ Promise, nextTick 등

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

💻 3.5 노드 내장 모듈 알아보기

📌 url 모듈

✏️ 인터넷 주소를 쉽게 조작하도록 도와주는 모듈

  • url 처리에 크게 두 가지 방식이 있음(기존 노드 방식 vs WHATWG 방식)
  • 요즘은 WHATWG 방식만 사용함 (웹표준 방식으로 통일)
  • WHATWG 방식 주소 체계는 다음과 같음

📌 searchParams

✏️ WHATWG 방식에서 쿼리스트링(search) 부분 처리를 도와주는 객체

  • ?page=3&limit=10&category=nodejs&category=javascript 부분

📌 searchParams 예제 결과

✏️ 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 지원

📌 child_process

✏️ 노드에서 다른 프로그램을 실행하고 싶거나 명령어를 수행하고 싶을 때 사용

  • 현재 노드 프로세스 외에 새로운 프로세스를 띄워서 명령을 수행함.
  • 명령 프롬프트의 명령어인 dir을 노드를 통해 실행(리눅스라면 ls를 대신 적을 것)

✏️ 파이썬 프로그램 실행하기

  • 파이썬3이 설치되어 있어야 함.

📌 기타 모듈들

✏️ async_hooks: 비동기 코드의 흐름을 추적할 수 있는 실험적인 모듈입니다.

✏️ dgram: UPD와 관련된 작업을 할 때 사용합니다.

✏️ net: HTTP보다 로우 레벨인 TCP나 IPC 통신을 할 때 사용합니다.

✏️ perf_hooks: 성능 측정을 할 때 console.time보다 더 정교하게 측정합니다.

✏️ querystring: URLSearchParams가 나오기 이전에 쿼리스트링을 다루기 위해 사용했던 모듈입니다.

✏️ string_decoder: 버퍼 데이터를 문자열로 바꾸는 데 사용합니다.

✏️ tls: TLS와 SSL에 관련된 작업을 할 때 사용합니다.

✏️ tty: 터미널과 관련된 작업을 할 때 사용합니다.

✏️ v8: V8 엔진에 직접 접근할 때 사용합니다.

✏️ vm: 가상 머신에 직접 접근할 때 사용합니다.

✏️ wasi: 웹어셈블리를 실행할 때 사용하는 실험적인 모듈입니다.


💻 3.6 파일 시스템 접근하기

📌 fs

✏️ 파일 시스템에 접근하는 모듈

파일/폴더 생성, 삭제, 읽기, 쓰기 가능
웹 브라우저에서는 제한적이었으나 노드는 권한을 가지고 있음

const fs = require('fs');

fs.readFile('./readme.txt', (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
  console.log(data.toString());
});

📌 fs 프로미스

✏️ 콜백 방식 대신 프로미스 방식으로 사용 가능

  • require('fs').promises
  • 사용하기 훨씬 더 편해서 프로미스 방식을 추천
const fs = require('fs').promises;

fs.readFile('./readme.txt')
  .then((data) => {
    console.log(data);
  	console.log(data.toString());
  })
  .cath((err) => {
    console.error(err);
  });

📌 fs로 파일 만들기

✏️ 파일을 만드는 예제

  • writeFile()로 파일을 생성하고 프로미스에 의해서 then()이 순서대로 실행됨
  • 첫 번째 then()에서 return한 값이 두 번째 then()의 data로 전달
const fs = require('fs').promises;

fs.writeFile('./writeme.txt', '글이 입력됩니다.')
  .then(() => {
    return fs.readFile('./writeme.txt');
  })
  .then((data) => {
    console.log(data.toString());
  })
  .cath((err) => {
    console.error(err);
  });

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

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

  • 비동기는 코드의 순서와 실행 순서가
  • 일치하지 않는 것을 의미
  • 일부는 동기 방식으로 사용 가능

✏️ 동기와 비동기: 백그라운드 작업 완료 확인 여부

✏️ 블로킹과 논 블로킹: 함수가 바로 return 되는지 여부

✏️ 노드에서는 대부분 동기-블로킹 방식과 비동기-논 블로킹 방식임


📌 비동기 메서드로 순서 유지하기

✏️ 콜백 형식 유지

  • 코드가 우측으로 너무 들어가는 현상 발생(콜백 지옥)

✏️ 프로미스로 극복


📌 버퍼와 스트림 이해하기

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

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

✏️ 스트림: 데이터의 흐름

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

💻 3.7 이벤트 이해하기

📌 이벤트 만들고 호출하기

✏️ events 모듈로 커스텀 이벤트를 만들 수 있음

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

💻 3.8 예외 처리하기

📌 예외 처리

✏️ 예외(Exception): 처리하지 못한 에러

  • 노드 프로세스/스레드를 멈춤
  • 노드는 기본적으로 싱글 스레드라 스레드가 멈춘다는 것은 프로세스가 멈추는 것
  • 에러 처리는 필수

📌 try catch문

✏️ 기본적으로 try catch문으로 예외를 처리

  • 에러가 발생할 만한 곳을 try catch로 감쌈

📌 노드 비동기 메서드의 에러

✏️ 노드 비동기 메서드의 에러는 따로 처리하지 않아도 됨

  • 콜백 함수에서 에러 객체 제공

📌 프로미스의 에러

✏️ 프로미스의 에러는 따로 처리하지 않아도 됨

  • 버전이 올라가면 동작이 바뀔 수 있음
  • catch()를 넣지 않으면 경고 표시가 길게 출력됨
  • 그렇기에 then(), catch()형식을 지키는 것을 추천

📌 예측 불가능한 에러 처리하기

✏️ 최후의 수단으로 사용

  • 콜백 함수의 동작이 보장되지 않음
  • 따라서 복구 작업용으로 쓰는 것은 부적합
  • 에러 내용 기록 용으로만 쓰는 게 좋음

📌 프로세스 종료하기

✏️ 윈도우

  • netstat -ano | findstr 포트
  • taskkill /pid 프로세스아이디 /f
profile
조금씩 정리하자!!!

0개의 댓글