본문 바로가기
개발

[Node.js] 3장

by jwcs 2024. 2. 4.
728x90
반응형

3장 노드 기능 알아보기

노드를 직접 사용하며 익혀보자.

 

3.1 REPL 사용하기

REPL(Read-Eval-Print Loop)은 사용자로부터 입력을 받아서 실행(read), 그 결과를 평가(eval), 결과를 출력(Print)하고, 이 과정을 반복(Loop)하는 대화형 프로그래밍 환경을 의미한다. REPL 환경은 개발자가 즉시 코드를 실행해보고 결과를 볼 수 있게 해준다. 따라서 실험, 디버깅, 학습에 매우 유용하다. REPL 환경의 종류는 아래와 같다.

  • 브라우저 콘솔
  • Node.js REPL
  • 온라인 REPL 플랫폼

3.2 JS파일 실행하기

 명령 프롬프트에 node를 입력시켜 사용하기에는 여러 줄의 코드를 실행하기에는 불편하다. JS 파일을 만들어 사용하면 이 문제를 해소할 수 있다. 콘솔에서 node [JS 파일 경로]를 입력해서 실행시킬 수 있다. 확장자는 생략가능하다.

 

3.3 모듈로 만들기

 자바스크립트 모듈은 재사용 가능한 코드의 조각을 별도의 파일로 분리하여 관리할 수 있게 해주는 시스템이다. 모듈 시스템을 사용하면 큰 프로젝트를 작고 관리하기 쉬운 부분으로 나눌 수 있으며, 필요한 부분만을 불러와 사용함으로써 코드의 재사용성과 유지보수성을 높일 수 있다.

 

모듈의 기본 사용법

모듈 정의하기: 모듈은 `.js` 파일 하나에 해당하며, 이 파일 내에서 `export` 키워드를 사용하여 모듈 외부에서 사용할 수 있는 변수, 함수, 클래스 등을 지정할 수 있다.

모듈 불러오기: 다른 파일에서 해당 모듈의 기능을 사용하려면 `import` 키워드를 사용하여 해당 모듈을 불러온다. 

math.js(모듈 파일)
app.js (모듈 사용 파일)

 

3.3.1 CommonJS 모듈

 CommonJS 모듈은 자바스크립트를 위한 모듈 하나로, 주로 서버 사이드 자바스크립트 환경인 Node.js에서 사용된다. CommonJS 모듈 시스템은 자바스크립트 코드를 모듈 단위로 분리하여 재사용성을 높이고, 의존성 관리를 용이하게 하며, 코드의 구성을 개선하는 데 도움을 준다.

 

CommonJS 모듈의 기본 작동 원리

  • 모듈 내보내기: 모듈에서 외부로 내보내고자 하는 객체, 함수, 변수등을 `module.exports` 객체에 할당한다. 이 객체가 모듈을 불러올 때 반환되는 값이다.
  • 모듈 불러오기: 다른 모듈에서 필요한 모듈을 사용하려면 `require()` 함수를 사용하여 해당 모듈을 불러온다. `require()` 함수는 모듈의 경로를 인자로 받고, 해당 모듈의 `module.exports` 객체를 반환한다.

math.js (모듈 파일)
app.js (모듈 사용 파일)

 

모듈 순환참조: 순환참조(Circular Dependency)는 두 모듈이 서로를 직접적이거나 간접적으로 참조하는 상황이다. 이는 모듈 A가 모듈 B를 불러오고, 동시에 모듈 B도 모듈 A를 불러올 때 발생한다. 순환 참조는 종종 복잡한 모듈 시스템에서 발생하며, 의존성 관리를 어렵게 만들고, 예기치 않은 버그나 실행 순서 문제를 야기할 수 있다.

a.js
b.js
app.js

 

3.3.2 ECMAScript 모듈

ECMAScript 모듈은 자바스크립트의 공식 모듈 시스템이다.

ES 모듈의 주요 특징

  • 정적 구조: `import`와 `export`문은 파일의 최상위 수준에서 사용되어야 하며, 조건부로 실행될 수 없다. 이는 모듈 구조가 분석 시점에 결정되어, 빌드 도구와 자바스크립트 엔진이 최적화를 수행하기 용이하게 한다.
  • 단일 값 또는 다중 값 내보내기: ES 모듈은 단일 값 또는 여러 값을 내보낼 수 있으며, 다른 모듈에서 이를 `import`하여 사용할 수 있다.
  • 실시간 바인딩: 내보낸 값은 실시간으로 바인딩되어, 내보낸 모듈의 값이 변경되면 이를 불러온 모듈에서도 변경된 값이 반영된다.
  • .mjs 확장자 사용: Node.js는 ES 모듈을 지원하기 위해 `.mjs` 확장자를 도입했다. `.mjs` 확장자를 사용하면 해당 파일이 ES 모듈임을 명시적으로 Node.js에 알린다. 이 방법은 Node.js가 CommonJS 모듈 시스템과 ES 모듈 시스템을 함께 지원하는 상황에서 모듈 형식의 명확한 구분을 제공한다.

3.3.3 다이내믹 임포트

다이내믹 임포트(Dynamic Import)는 조건부로 모듈을 불러오는 것을 의미한다. 하지만 ES모듈은 if문 안에서 import하는 것이 불가능하다. 이럴 경우 어떻게 해야할까?

ES모듈 다이내믹 임포트 예시

import는 Promise를 반환하기 때문에 await 혹은 then을 사용해야한다. 위 예시에서는 async를 사용하지 않았는데, ES 모듈의 최상위 스코프에서는 async 함수 없이도 await를 사용할 수 있다. 다만 CommonJS 모듈에서는 안된다.

 

3.3.4 __filename, __dirname

 노드에서는 파일 사이에 모듈 관계가 있는 경우가 많다. 이러한 경우에 __filename과 __dirname을 사용할 수 있다. 이 두 변수는 Node.js의 CommonJS 모듈 시스템에서 사용되는 전역 변수이다.

  • __filename: 현재 실행 중인 스크립트의 파일명을 담고 있는 문자열이다. 이 값은 실행 중인 파일의 절대 경로를 포함한다.
  • __dirname: 현재 실행 중인 스크립트가 위치한 디렉토리의 경로를 담고 있는 문자열이다.

이 두 변수는 스크립트가 실행될 때 Node.js에 의해 자동으로 정의된다

 ES 모듈에서는 __filename과 __dirname라는 전역 변수가 없다. 그러나 현재 파일의 경로 정보를 얻으려면 다음과 같은 방법을 사용할 수 있다.

import.meta.url
URL 객체와 path 모듈

 

3.4 노드 내장 객체 알아보기

내장 객체를 알아보겠다.

 

3.4.1 global

브라우저의 window와 같은 전역 객체이다. 전역 객체이므로 모든 파일에서 접근할 수 있으며, window.open 메서드를 그냥 open으로 호출할 수 있는 것처럼 global도 생략할 수 있다. require 함수도 global.require에서 global이 생략된 것이다.

전역 변수 예시

 

3.4.2 console

지금까지 사용했던 console도 노드에서는 window 대신 global 객체 안에 들어있다. 브라우저에서의 console과 거의 비스하다.

  • console.log(message[, ...optionalParams]): 기본적인 로깅에 사용되며, 문자열, 숫자, 객체 등 어떤 타입의 데이터도 인자로 받을 수 있다.
  • console.info(message[, ...optionalParams]): 정보 로깅에 사용되며, console.log와 유사하게 다양한 타입의 데이터를 인자로 받는다.
  • console.warn(message[, ...optionalParams]): 경고 메시지 로깅에 사용되며, 주의가 필요한 상황을 알릴 때 사용된다.
  • console.error(message[, ...optionalParams]): 에러 메시지 로깅에 사용되며, 에러 객체나 에러 메시지를 인자로 받는다.
  • console.debug(message[, ...optionalParams]): 디버깅 메시지 로깅에 사용되며, 디버깅 정보를 인자로 받는다.
  • console.table(data[, columns]): 테이블 형태로 데이터를 출력할 때 사용되며, 배열이나 객체를 첫 번째 인자로 받는다.
  • console.assert(condition, message[, ...data]): 조건이 거짓일 경우 메시지를 출력하며, 첫 번째 인자로 조건식을, 두 번째 인자로 로깅할 메시지를 받는다.
  • console.trace(message[, ...optionalParams]): 함수 호출 스택을 출력할 때 사용되며, 특정 지점에서의 호출 스택을 확인하고 싶을 때 사용된다.
  • console.time(label) 및 console.timeEnd(label): 코드 실행 시간을 측정할 때 사용되며, 타이머의 레이블을 인자로 받는다.
  • console.dir(obj[, options]): 함수는 객체의 JSON 표현을 출력하기 위해 사용된다.

3.4.3 타이머

타이머 기능은 비동기 작업을 예약하거나 반복하기 위해 사용된다.

 

`setTimeout(callback, delay[, ...args])`:

  • 지정된 지연 시간(`delay`, 밀리초 단위)이 지난 후에 콜백 함수(`callback`)를 한 번 실행한다.
  • 선택적으로 `delay` 이후에 `callback` 함수에 전달될 추가 인자(`...args`)를 지정할 수 있다.
  • 이 함수는 타이머를 식별하는 고유한 타이머 ID를 반환한다.

`clearTimeout(timeoutId)`:

  • `setTimeout`에 의해 생성된 타이머를 취소한다.
  • 인자로는 `setTimeout`이 반환한 타이머 ID를 받는다.

`setInterval(callback, delay[, ...args])`:

  • 지정된 지연 시간(`delay`, 밀리초 단위)마다 콜백 함수(`callback`)를 반복 실행한다.
  • `setTimeout`과 마찬가지로, 선택적으로 `callback`에 전달할 추가 인자(`...args`)를 지정할 수 있다
  • 이 함수도 타이머를 식별하는 고유한 타이머 ID를 반환한다.

`clearInterval(intervalId)`:

  • `setInterval`에 의해 생성된 타이머를 취소한다.
  • 인자로는 `setInterval`이 반환한 타이머 ID를 받는다.

`setImmediate(callback,[, ...args])`:

  • 현재 이벤트 루프 사이클이 완료된 직후에 콜백 함수(`callback`)를 실행한다.
  • 이 함수는 I/O 사이클이나 타이머와 같이 비동기 작업이 완료된 후 즉시 실행되어야 하는 작업에 유용하다.
  • 선택적으로 `callback` 함수에 전달될 인자(`...args`)를 지정할 수 있다.
  • `setImmediate`는 고유한 ID를 반환한다.

`clearImmediate(immediateId)`:

  • `setImmediate`에 의해 생성된 스케쥴된 작업을 취소한다.
  • 인자로는 `setImmediate`에 의해 반환된 ID를 받는다.

3.4.4 process

현재 실행 중인 Node.js 프로세스에 대한 정보와 제어를 위한 인터페이스를 제공하는 글로벌 객체이다. 이 객체는 프로그램 실행에 관련된 환경 정보, 실행 중인 프로세스의 상태, 시스템 정보등을 담고 있으며, 프로그램을 종료하거나 현재 실행 환경을 조작하는 데 사용할 수 있는 메소드들을 포함하고 있다.

 

속성

  • process.argv: 프로그램을 실행할 때 명령줄에서 전달된 인수들의 배열이다.
  • process.env: 사용자 환경의 정보를 담고 있는 객체이다. 환경 변수에 접근할 때 사용된다.
  • process.cwd(): 현재 작업 디렉토리를 반환한다
  • process.version: Node.js의 버전을 나타낸다
  • process.versions: Node.js와 그 종속성들의 버전을 담고 있는 객체이다
  • process.pid: 현재 프로세스의 PID(프로세스ID)이다.
  • process.platform: 프로세스가 실행 중인 운영 체제의 플랫폼을 나타낸다

메서드

  • process.exit([code]): 프로세스를 종료한다. 선택적으로 종료 코드를 지정할 수 있다
  • process.nextTick(callback[, ...args]): 이벤트 루프의 현재 단계가 완료된 후, 다음 이벤트 루프 단계가 시작되기 전에 `callback` 함수를 실행한다
  • process.stdout.write(data[, encoding][, callback]): 표준 출력(stdout) 스트림에 데이터를 씁니다
  • process.stderr.write(data[, encodeing][, callback]): 표준 에러(stderr) 스트림에 데이터를 쓴다.
  • process.chdir(directory): 현재 작업의 디렉토리를 변경한다

3.4.5 기타 내장 객체

여기서 언급하지 않은 많은 내장 객체들이 존재한다. 필요할 때 찾아보며 공부하자.

 

3.5 노드 내장 모듈 사용하기

노드는 웹 브라우저에서 사용되는 자바스크립트보다 더 많은 기능을 제공한다. 운영체제 정보에도 접근할 수 있고, 클라이언트가 요청한 주소에 대한 정보도 가져올 수 있다. 노에서 이러한 기능을 하는 모듈을 제공한다.

 

3.5.1 OS

Node.js의 `os` 모듈은 운영 체제와 관련된 유틸리티 메서드와 속성을 제공하는 내장 모듈이다. 이 모듈을 사용하면 시스템의 아키텍처, 사용 가능한 메모리, 운영 체제의 이름등과 같은 운영 체제에 대한 정보를 가져올 수 있으며, 시스템의 환경 변수에 접근하거나, 시스템의 평균 로드, CPU 정보, 네트워크 인터페이스 등을 확인할 수 있다.

 

`os` 모듈을 사용하기 위해서는 먼저 `require()` 함수를 이용해 모듈을 불러와야 한다.

사용 예시

메서드

  • os.arch(): 시스템의 아키텍처를 반환한다. (예: x64, arm, ia32)
  • os.cpus(): 시스템의 CPU 정보를 담고 있는 객체 배열을 반환한다. 각 CPU 코어에 대한 정보를 포함한다.
  • os.freemem(): 시스템에서 사용 가능한 메모리(바이트 단위)를 반환한다.
  • os. totalmem(): 시스템의 총 메모리 양(바이트 단위)을 반환한다.
  • os.homedir(): 현재 사용자의 홈 디렉토리의 경로를 반환한다.
  • os.hostname(): 시스템의 호스트 이름을 반환한다.
  • os.networkInterfaces(): 네트워크 인터페이스에 대한 정보를 담고 있는 객체를 반환한다.
  • os.platform(): 운영 체제의 플랫폼을 반환한다.(예: linux, darwin(macOS), win32(WINDOWS))
  • os.release(): 운영 체제의 버전을 반환한다
  • os.tmpdir(): 기본 임시 파일 디렉토리의 경로를 반환한다
  • os.type(): 운영 체제의 이름을 반환한다(예: linux, Darwin, Windows_NT 등)
  • os.uptime(): 시스템이 마지막으로 부팅된 이후로 경과한 시간(초 단위)을 반환한다.
  • os.userInfo( [options] ): 현재 활성 사용자의 정보를 반환한다.

속성

  • os.EOL: 운영 체제의 개행 문자를 나타낸다. 윈도우에서는 `\r\n`, POSIX에서는 `\n`

사용 예씨

`os` 모듈은 시스템의 기본적인 정보를 조회하거나, 시스템 리소스의 사용 상태를 모니터링하는 데 사용된다. 예를 들어, 애플리케이션의 성능을 모니터링하거나, 특정 운영 체제에 대한 조건부로 로직을 구현할 때 유용하게 사용할 수 있다.

 

3.5.2 path

Node.js의 `path` 모듈은 파일 시스템 경로를 처리하는 데 사용되는 유틸리티를 제공한다. 이 모듈은 경로 문자열을 쉽게 조작하도록 도와줌으로써, 운영 체제 간의 경로 차이를 추상화하고 다루는 코드를 보다 간결하게 만들 수 있게 한다. `path` 모듈을 사용하기 위해서는 먼저 `require()` 함수를 사용하여 모듈을 불러와야 한다.

사용 예시

주요 메서드

  • path.basename(path[, ext]): 경로의 마지막 부분을 반환한다. 선택적으로 확장자 `ext`를 제거할 수 있다.
  • path.dirname(path): 경로에서 디렉토리 이름 부분을 반환한다.
  • path.extname(path): 경로에서 확장자 부분을 반환한다
  • path.join([...paths]): 여러 인수를 받아 하나의 경로로 조합한다. 인수 사이에 플랫폼별 구분자를 삽입한다.
  • path.normalize(path): 경로를 정규화한다. 예를 들어, `.` 또는 `..`과 같은 상대적 경로 지정자를 처리한다.
  • path.resolve([...paths]): 절대 경로를 생성한다. 인수로 주어진 경로들을 오른쪽에서 왼쪽으로 처리하여, 현재 작업 디렉토리를 기준으로 한 절대 경로를 생성한다.
  • path.sep: 현재 플랫폼의 경로 구분자를 나타낸다. 윈도우에서는 `\`, POSIX 시스템에서는 `/`이다.
  • path.isAbsolute(path): 주어진 경로가 절대 경로인지 여부를 반환한다.
  • path.relative(from, to): 한 경로에서 다른 경로로 가는 상대적 경로를 계산한다.

사용 예시

 

3.5.3 url

URL을 처리하고 구문 분석하는 데 사용되는 유틸리티를 제공한다. 이 모듈은 URL을 쉽게 조작하고 분석할 수 있도록 도와줌으로써, 웹 애플리케이션 개발 시 필수적인 작업을 간편하게 만들어준다. `url` 모듈에는 주로 두 가지 방식의 API가 있다. 레거시 API와 WHATWG URL API이다.

 

레거시 API

Node.js가 초기에 제공하던 방식으로, URL 문자열을 구문 분석하고 조작하는 데 사용되는 함수들을 포함한다.

  • url.parse(urlString[, parseQueryString[, slashesDenoteHost]]): URL 문자열을 URL 객체로 분석한다. 선택적으로 쿼리 문자열을 객체로 분석할지, 두 개의 슬래시가 호스트를 나타내는지 여부를 결정할 수 있다.
  • url.format(urlObject): URL 객체를 URL 문자열로 변환한다.

WHATWG URL API

웹 브라우저가 사용하는 URL 표준과 호환되는 API이다. 이 API는 `URL` 클래스를 중심으로 구성되어 있으며, 더 현대적이고 강력한 기능을 제공한다.

  • new URL(url[, base]): URL 문자열을 파싱하여 URL 객체를 생성한다. 선택적으로 기준 URL을 제공할 수 있으며, 이는 상대 URL을 절대 URL로 변환하는 데 사용된다.

URL 객체의 속성

  • href: 전체 url 문자열이다.
  • protocol: 프로토콜을 나타낸다.(예: http)
  • host: 호스트 이름과 포트 번호를 포함한다.
  • hostname: 호스트 이름을 나타낸다.
  • pathname: URL의 경로를나타낸다.
  • search: 쿼리 문자열을 나타낸다.
  • hash: 앵커(프래그먼트) 부분을 나타낸다.

3.5.4 dns

DNS를 다룰 때 사용하는 모듈이다. 주로 도메인을 통해 IP나 기타 DNS 정보를 얻고자 할 때 사용한다.

  • dns.resolve(hostname, [rtype], callback): 이 함수는 DNS 레코드 타입을 지정하여 호스트 이름에 대한 배열을 반환한다.
  • dns.resolve4(hostname, callback): IPv4 주소를 조회한다
  • dns.resolve6(hostname, callback): IPv6 주소를 조회한다
  • dns.reverse(ip, callback): 주어진 IP 주소에 대한 PTR 레코드를 조회하여, 이 IP 주소에 연결된 호스트 이름을 찾아낸다.

 

3.5.5 crypto

암호화 기능을 제공하여 데이터의 보안을 강화하는 데 사용된다. 이 모듈은 다양한 암호화 기술을 지원하며, 해시 생성, HMAC(Hash-based Message Authentication Code), 공개키/개인키 기반의 암호화 및 서명, 대칭키 암호화 등을 포함한다. crypto 모듈을 사용하기 위해서는 먼저 `require()` 함수를 이용해 모듈을 불러와야 한다.

사용법

 

해시 생성: 데이터의 해시 값을 생성한다. 해시 함수는 임의 길이의 데이터를 고정된 길이의 해시 값으로 매핑한다. 일반적으로 메시지의 무결성을 검증하는 데 사용된다.

사용법

 

HMAC 생성: 키를 사용한 해시 메시지 인증 코드(HMAC)를 생성한다. 이는 데이터의 무결성과 인증을 동시에 제공한다.

사용법

 

대칭키 암호화: 같은 키를 암호화와 복호화에 사용하는 암호화 방식이다. 데이터를 안전하게 전송하거나 저장할 때 사용된다.

사용법

 

비대칭키 암호화: 공개키와 개인키를 사용하는 암호화 방식이다. 공개키는 데이터를 암호화하고, 개인키는 암호화된 데이터를 복호화한다.

사용법

 

디지털 서명: 메시지의 발신자를 인증하고, 메시지가 전송 중에 변경되지 않았음을 보증하는 데 사용된다.

사용법

 

키 파생: 비밀번호와 같은 정보에서 안전하게 키를 생성하는 과정이다. PBKDF2, scrypt와 같은 알고리즘이 사용된다.

사용법

3.5.7 worker_threads

노드의 worker_threads 모듈은 멀티 스레딩을 지원하며, 노드 애플리케이션에서 CPU 집약적인 작업을 병렬로 처리할 수 있게 해준다. 이 모듈을 사용하면, 주 스레드가 I/O 작업이나 네트워크 통신 등에 집중할 수 있도록, CPU를 많이 사용하는 작업을 백그라운드 스레드로 오프로드할 수 있다. 이는 Node.js의 비동기, 이벤트 주도 모델을 보완하여 성능과 활용도를 향상시킨다. worker_threads 모듈을 사용하기 위해서는 먼저 모듈을 불러와야 한다. 그 후, worker 클래스를 사용하여 새로운 워커 스레드를 생성할 수 있다.

사용법

worker_threads 모듈은 Node.js에서 멀티스레딩을 구현할 때 필수적인 도구로, 애플리케이션의 성능을 크게 향상시킬 수 있다.

 

3.5.8 child_process

새로운 프로세스를 생성하고 관리할 수 있게 해주는 기능을 제공한다. 이 모듈을 사용하여 Node.js 애플리케이션에서 다른 애플리케이션을 실행할 수 있으며, 이를 통해 Node.js 프로세스와는 독립적으로 실행되는 자식 프로세스를 생성할 수 있다. 

 

주요 함수

  • exec(command, [options], callback): 셸을 사용하여 명령어를 실행하고, 완료될 때 콜백을 호출한다. 콜백 함수는 `error`, `stdout`, `stderr` 인자를 받는다. 이 함수는 주로 간단한 셸 명령을 실행할 때 사용된다.
  • execFile(file, [args], [options], callback): 셸을 거치지 않고 직접 파일을 실행한다. 이는 `exec`보다 약간 더 효율적이다. 특히 사용자 입력을 파일이나 명령어 인자로 전달할 때 유용하다.
  • spawn(command, [args], [options]): 새로운 프로세스를 시작하기 위해 사용되며, 스트리밍 데이터(예: 큰 파일 처리)에 가장 적합하다. spawn은 exec와 달리 즉시 ChildProcess 객체를 반환하며, 이를 통해 프로세스의 stdout, stderr 스트림에 접근할 수 있다.
  • fork(modulePath, [args], [options]): 특별한 경우의 spawn으로, Node.js 모듈을 새로운 Node.js 프로세스에서 실행한다. fork된 프로세스는 IPC 채널을 통해 부모 프로세스와 통신할 수 있어, 메시지를 주고 받을 수 있다.

exec 사용 예시
spawn 사용 예시

3.5.9 기타 모듈들

이외에도 언급하지 않은 모듈들이 많다. 따라서 공식 문서를 참조하며 공부하자.

 

3.6 파일 시스템 접근하기

fs 모듈은 파일 시스템에 접근하는 모듈이다. 즉, 파일을 생성하거나 삭제하고, 읽거나 쓸 수 있다. 또한, 폴더도 만들거나 지울 수 있다.

 

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

 

동기 VS 비동기

  • 동기: 동기 방식에서는 작업이 순차적으로 실행된다. 한 작업이 완료되어야 다음 작업을 시작할 수 있다. 이 방식은 프로그램의 흐름을 이해하기 쉽게 만들지만, 현재 작업이 완료될 때까지 프로그램이 다른 작업을 수행하지 못하게 하여 리소스를 비효율적으로 사용할 수 있다.
  • 비동기: 비동기 방식에서는 한 작업이 완료되기를 기다리지 않고, 다음 작업을 시작할 수 있다. 작업의 완료는 콜백 함수, 프로미스, async/await 등을 통해 처리된다. 이 방식은 동시에 여러 작업을 처리할 수 있게 하여 프로그램의 효율을 높일 수 있지만, 코드의 복잡성이 증가할 수 있다.

블로킹 VS 논블로킹

  • 블로킹: 블로킹 방식에서는 요청한 작업이 완료될 때까지 호출한 프로세스가 대기 상태에 놓인다. 이는 리소스를 효율적으로 사용하지 못하게 만들 수 있으며, 특히 대규모 시스템이나 멀티유저 애플리케이션에서 성능 저하를 초래할 수 있다.
  • 논블로킹: 논블로킹 방식에서는 요청한 작업이 즉시 완료될 수 없을 때, 해당 작업을 기다리지 않고 즉시 제어권이 호출자에게 반환된다. 이 방식은 특히 비동기 프로그래밍에서 유용하며, 시스템 리소스를 보다 효율적으로 사용할 수 있게 한다.

상호 관계

  • 동기 블로킹: 가장 전통적인 작업 처리 방식으로, 요청된 작업의 완료를 기다린다.
  • 동기 논블로킹: 일반적으로 덜 사용되는 방식으로, 작업을 요청하고 가능한 경우 즉시 반환되지만, 완료를 위해 반복적으로 상태를 확인해야 한다.
  • 비동기 논블로킹: 현대의 많은 프로그래밍 환경에서 선호되는 방식으로, 작업을 요청하고 완료될 때까지 기다리지 않으며, 작업 완료 시 콜백을 통해 알림을 받는다. Node.js는 이 방식을 널리 사용한다.

3.6.2 버퍼와 스트림 이해하기

Node.js에서의 버퍼와 스트림은 데이터를 다루는 두 가지 핵심적인 개념이다. 이 두 기능은 특히 대량의 데이터를 처리하거나, 데이터를 전송할 때 중요한 역할을 한다.

 

버퍼(Buffer)

버퍼는 일시적으로 데이터를 저장하는 메모리 영역이다. Node.js에서의 버퍼는 주로 바이너리 데이터를 저장하는데 사용되며, 파일 시스템 작업, 네트워크 통신, 이미지 처리 등 바이트 단위로 데이터를 다룰 때 필요하다.

  • 버퍼는 고정된 크기를 가지며, Node.js 에서는 `Buffer` 클래스를 통해 이를 구현한다.
  • 버퍼는 배열과 유사하게 동작하지만, 저장할 수 있는 것은 바이트 데이터뿐이다.
  • 버퍼를 사용하면 데이터를 효율적으로 처리할 수가 있으며, Node.js가 비동기적으로 데이터를 처리하는 데 있어 중요한 역할을 한다.

스트림(Stream)

스트림은 데이터의 흐름을 나타내며, 데이터를 조각내어 순차적으로 처리할 수 있게 한다. 이는 큰 데이터를 한 번에 메모리에 적재하지 않고, 필요한 만큼 조금씩 처리할 수 있게 해주어 메모리 사용을 최적화한다.

  • 스트림은 데이터를 소비하는 방식에 따라 `읽기 가능 스트림`, `쓰기 가능 스트림`, `변호나 스트림` 및 `복합 스트림`으로 구분된다.
  • 파일 읽기/쓰기, 네트워크 통신 등에서 스트림을 사용하면, 데이터를 효율적으로 전송하고 처리할 수 있다.
  • 스트림을 사용하면 이벤트 기반으로 데이터를 처리할 수 있으며, `data`, `end`, `error`, `finish` 등의 이벤트를 통해 데이터 처리 과정을 제어할 수 있다.

버퍼와 스트림의 상호작용

  • 버퍼와 스트림은 데이터를 처리하는 방식에서 차이가 있지만, 함께 사용되어 강략한 데이터 처리 능력을 발휘한다.
  • 예를 들어, 파일을 읽을 때 스트림을 사용하면 파일의 내용이 작은 조각으로 나누어져 순차적으로 처리된다. 이는 큰 파일을 효율적으로 처리할 수 있게 해주며, 애플리케이션의 반응성을 높여준다.

버퍼 생성 예제
스트림을 사용한 파일 읽기 예제

이 예제에서는 파일을 읽기 위해 읽기 가능한 스트림을 생성하고, 파일의 내용이 조각으로 읽힐 때마다 해당 족가을 콘솔에 출력한다. 파일 읽기가 완료되면 'end' 이벤트가 발생한다.

 

Node.js에서의 버퍼와 스트림은 데이터를 효율적으로 처리하기 위한 중요한 도구이다. 대량의 데이터를 다룰 대 이들을 적절히 사용하면, 애플리케이션의 성능과 반응성을 크게 향상시킬 수 있다.

 

3.6.3 기타 fs 메서드 알아보기

fs 모듈은 파일 시스템 작업을 위한 다양한 메서드를 제공한다. 이 메서드들은 파일을 생성, 읽기, 쓰기, 수정, 삭제 등의 작업을 수행할 수 있게 해준다. `fs` 메서드는 동기적과 비동기적 버전으로 제공되며, 비동기 메서드는 Node.js의 비동기적인 특성을 활용해 비동기 I/O 작업을 수행한다.

 

  • fs.access(path[, mode], callback): 파일이나 디렉토리의 접근성을 테스트한다. 이는 파일이나 디렉토리가 존재하는지, 그리고 주어진 권한으로 접근 가능한지 확인하는데 사용된다
  • fs.mkdir(path, [options], callback): 비동기적으로 디렉토리를 생성한다
  • fs.open(path, flags[, mode], callback): 파일을 열 때 사용되며, 파일을 읽고/쓰기 위한 파일 디스크립터를 제공한다
  • fs.rename(oldPath, newPath, callback): 파일이나 디렉토리의 이름을 변경한다. 이 메서드는 또한 파일을 다른 디렉토리로 이동시키는 데도 사용될 수 있다.
  • fs.readdir(path, [options], callback): 비동기적으로 디렉토리의 내용을 읽는다
  • fs.unlink(path, callback): 비동기적으로 파일을 삭제한다
  • fs.rmdir(path, callback): 비동기적으로 디렉토리를 삭제한다

3.7 이벤트 이해하기

Node.js에서 이벤트는 애플리케이션에서 발생하는 특정한 행동이나 사건을 의미한다. 예를 들어, HTTP 서버가 클라이언트로부터 요청을 받았을 때, 파일 읽기가 완료되었을 때, 사용자가 정의한 조건이 충족되었을 때 등 다양한 상황에서 이벤트가 발생할 수 있다. Node.js는 이벤트 기반 모델을 사용하여 비동기 I/O 작업을 효율적으로 처리한다.

  • .on(이벤트명, 콜백): 이벤트에 이어질 리스너를 추가한다. 이벤트가 발생하면, 등록된 리스너들이 호출된다. 이벤트와 연결하는 복수의 리스너를 추가할 수 있으며, event2처럼 이벤트 하나에 여러 개의 리스너를 연결할 수 있다.
  • .addListener(이벤트명, 콜백): `.on`과 기능이 같다.
  • .emit(이벤트명): 이벤트를 발생시킨다. 해당 이벤트와 연결된 모든 리스너들을 호출한다. `.emit('event3')`으로 호출하면, 해당 이벤트와 연결된 모든 리스너가 호출된다.
  • .once(이벤트명, 콜백): 한 번만 호출되는 이벤트 리스너를 추가한다. 이벤트가 발생하면 리스너가 호출되고 이후 자동으로 리스너가 제거된다.
  • .removeAllListeners(이벤트명): 특정 이벤트에 연결된 모든 리스너를 제거한다. 이벤트명을 지정하지 않으면, 모든 이벤트의 리스너를 제거할 수 있다.
  • .removeListener(이벤트명, 리스너): 특정 이벤트에 연결된 특정 리스너를 제거한다. 리스너가 여러 개일 경우, 지정한 리스너만 제거된다.
  • .off(이벤트명, 콜백): .removeListener와 같은 기능을 한다.
  • .listenerCount(이벤트명): 주어진 이벤트와 연결된 리스너의 수를 반환한다.

3.8 예외 처리하기

예외 처리는 프로그램의 안정성과 신뢰성을 유지하는 데 필수적이다. 예외란 프로그램 실행 중에 발생하는 예상치 못한 상황을 말하며, 이를 적절히 처리하지 않으면 프로그램이 중단될 수 있다.

 

동기 코드의 예외 처리

동기 코드에서 예외를 처리하는 가장 일반적인 방법은 `try...catch` 문을 사용하는 것이다.

사용 예시

비동기 코드의 예외 처리

비동기 코드에서 발생하는 예외는 `try...catch`로 잡을 수 없다. 대신, 콜백 함수 내부에서 에러를 처리하거나, 프로미스를 사용하는 경우 `.catch()` 메서드를 활용해야 한다.

예외 처리 예시
프로미스 사용시 예외처리 예시

 

async/await를 사용하여 비동기 코드의 예외를 동기 코드처럼 처리가능

 

3.8.1 자주 발생하는 에러들

  • node: command not found: 이 에러는 시스템에서 node 커맨드를 찾을 수 없을 때 발생한다. 이는 node가 설치되지 않았거나 시스템의 PATH 환경 변수에 node가 포함되지 않았을 때 발생한다.
  • ReferenceError: 모듈 is not defined: 이 에러는 require 함수를 사용할 때 해당 모듈이 올바르게 지정되지 않았을 때 발생한다. require의 인자로 올바른 모듈 경로를 지정해야 한다.
  • Error: Cannot find module 모듈명: require 함수를 사용하여 모듈을 불러오려고 할 때 해당 모듈을 찾을 수 없을 때 발생한다. 모듈이 올바르게 설치되었는지 확인하거나, 올바른 경로로 모듈을 불러오고 있는지 확인해야 한다.
  • Error [ERR_MODULE_NOT_FOUND]: 잘못된 경로나 이름으로 모듈을 불러올 때 발생한다.

등등 많은 에러가 있다. 여기까지만 알아보겠다. 나머지는 경험하며 배우자

 

728x90
반응형

'개발' 카테고리의 다른 글

[Node.js] 6장  (0) 2024.02.08
[Node.js] 5장  (0) 2024.02.07
[Node.js] 4장  (0) 2024.02.04
[Node.js] 2장  (0) 2024.02.02
[Node.js] 1장  (0) 2024.02.02