← JavaScript 강의 목록으로
🟢
Node 입문
심화 · 선수: 23_모듈_ESM

24. Node.js 환경 입문

브라우저 밖에서 JS를 실행하는 런타임. 서버, CLI, 빌드 도구 등에 쓰입니다.

Node.jsCommonJSESM파일 시스템
소요 시간
약 1.5시간
난이도
📊 중급
선수 조건
🎯 단원 23
결과물
브라우저 밖에서 JS를 실행하는 런타임. 서버, CLI, 빌드 도구 등에 쓰입니다.

이 강의에서 배우는 것

  • 1Node로 JS 파일을 실행할 수 있다.
  • 2`process.argv`, `process.env`를 활용한다.
  • 3`fs` 모듈로 파일을 읽고 쓸 수 있다.
  • 4CommonJS와 ESM 모듈 시스템의 차이를 안다.

소개

브라우저 밖에서 JS를 실행하는 런타임. 서버, CLI, 빌드 도구 등에 쓰입니다.

핵심 개념

1. Node란?

브라우저 밖에서 JS를 실행하는 런타임. 서버, CLI, 빌드 도구 등에 쓰입니다.

설치 확인:

bash
node -v

실행:

bash
node 01_hello_node.js

2. process — 인자와 환경변수

javascript
console.log(process.argv);   // ['node 경로', '스크립트 경로', ...추가 인자]
console.log(process.env.HOME);
bash
node 02_process.js apple 5

3. fs — 파일 시스템

javascript
import { readFileSync, writeFileSync } from 'node:fs';

writeFileSync('hello.txt', '안녕 Node');
const text = readFileSync('hello.txt', 'utf-8');
console.log(text);

비동기 버전(`readFile`, `promises` API)도 있습니다.

4. CommonJS vs ESM

Node에는 두 모듈 시스템이 공존합니다.

항목CommonJSESM
파일 확장자`.js` (기본)`.mjs` 또는 `"type":"module"`
내보내기`module.exports = ...``export`
가져오기`require('./x')``import`
로딩동기비동기
javascript
// CommonJS (legacy.cjs)
module.exports = { hi: () => 'hi' };
const { hi } = require('./legacy');

// ESM (modern.mjs)
export const hi = () => 'hi';
import { hi } from './modern.mjs';

신규 코드는 ESM을 권장합니다.

핵심 예제

파일다루는 내용
01_hello_node.jsnode 실행 첫 걸음
02_process.jsargv / env 사용
03_fs_basic.js파일 읽기/쓰기
04_commonjs_esm.mjs두 모듈 시스템 비교

src/01_hello_node.js

javascript
/**
 * 첫 Node 실행
 * 실행: node 01_hello_node.js
 */
console.log('Hello, Node!');
console.log('Node 버전:', process.version);
console.log('플랫폼:', process.platform);

src/02_process.js

javascript
/**
 * process.argv와 process.env
 * 실행 예: node 02_process.js apple 5
 */
const [, , fruit, countStr] = process.argv;
const count = Number(countStr ?? 1);

console.log(`인자: ${fruit} × ${count}`);
console.log('전체 argv:', process.argv);
console.log('HOME 환경변수:', process.env.HOME ?? process.env.USERPROFILE);

src/03_fs_basic.js

javascript
/**
 * fs로 텍스트 파일 쓰고 읽기
 */
const { writeFileSync, readFileSync, existsSync } = require('node:fs');

const path = 'hello.txt';
writeFileSync(path, '안녕 Node\n두 번째 줄');

if (existsSync(path)) {
  const text = readFileSync(path, 'utf-8');
  console.log('파일 내용:');
  console.log(text);
}

src/04_commonjs_esm.mjs

mjs
/**
 * ESM 스타일 — .mjs 확장자
 * CommonJS와 비교 주석 포함
 */
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';

// CommonJS에서는 __filename, __dirname이 기본 제공되지만
// ESM에서는 직접 만들어야 한다
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

console.log('이 파일:', __filename);
console.log('이 디렉토리:', __dirname);

// CommonJS:
//   const { readFileSync } = require('node:fs');
//   module.exports = { ... };
//
// ESM:
//   import { readFileSync } from 'node:fs';
//   export { ... };

export const hello = () => 'ESM에서 안녕';
console.log(hello());

자주 하는 실수

  1. 브라우저 API(`window`, `document`)를 Node에서 사용.
  2. ESM에서 `require` 사용 (반대도 마찬가지).
  3. 상대경로에 `./`를 빼먹기.
  4. `fs.writeFileSync`로 만든 파일이 다른 작업 디렉토리에 생성된 줄 모르고 못 찾음.
  5. 환경변수를 코드에 하드코딩.

FAQ

Q1. Node 버전 어떤 걸 써야?

LTS(짝수 메이저) 최신을 권장합니다. **Q2. .env 파일은?** A. Node 20+은 `--env-file`, 그 외는 `dotenv` 패키지. **Q3. 작업 디렉토리는?** A. `process.cwd()`로 확인. 보통 명령을 실행한 위치입니다.

과제

명령행 인자와 fs로 간단한 도구를 만드세요.

homework/README.md

## 과제 1 (CommonJS) 명령행으로 받은 두 수를 더해 출력하세요. `node homework_01.js 3 5` → `합: 8`

## 과제 2 (ESM) `note.txt` 파일에 명령행으로 받은 문자열을 한 줄씩 추가(append)하세요. `node homework_02.mjs "오늘의 메모"` 실행 후 파일 내용 확인.

homework/answer/homework_01.js

javascript
/**
 * 과제 1: 명령행 인자 두 수 더하기 (CommonJS)
 * 실행: node homework_01.js 3 5
 */
const [, , aStr, bStr] = process.argv;
const a = Number(aStr);
const b = Number(bStr);

if (Number.isNaN(a) || Number.isNaN(b)) {
  console.error('숫자 두 개를 입력하세요.');
  process.exit(1);
}

console.log(`합: ${a + b}`);

homework/answer/homework_02.mjs

mjs
/**
 * 과제 2: note.txt에 메모 추가 (ESM)
 * 실행: node homework_02.mjs "오늘의 메모"
 */
import { appendFileSync, readFileSync, existsSync } from 'node:fs';

const text = process.argv[2];
if (!text) {
  console.error('추가할 문자열을 인자로 주세요.');
  process.exit(1);
}

const path = 'note.txt';
appendFileSync(path, text + '\n');

console.log('--- 현재 note.txt ---');
console.log(existsSync(path) ? readFileSync(path, 'utf-8') : '(없음)');

다음 단원

[25_npm_입문](../25_npm_입문/)

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗