Node.js를 실무 흐름으로 이해하기
JavaScript를 서버에서 실행하는 Node.js. npm 생태계, 이벤트 루프, 파일 시스템, HTTP 서버, Express.js까지 한국어로 배우세요. 이 가이드는 개념을 나열하기보다, 실제 프로젝트에서 판단해야 하는 순서대로 내용을 따라갈 수 있게 구성했습니다.
JavaScript를 서버에서 실행하는 Node.js. npm 생태계, 이벤트 루프, 파일 시스템, HTTP 서버, Express.js까지 한국어로 배우세요.
JavaScript를 서버에서 실행하는 Node.js. npm 생태계, 이벤트 루프, 파일 시스템, HTTP 서버, Express.js까지 한국어로 배우세요. 이 가이드는 개념을 나열하기보다, 실제 프로젝트에서 판단해야 하는 순서대로 내용을 따라갈 수 있게 구성했습니다.
화면을 그리는 법에서 멈추지 않고, 상태, 데이터 요청, 라우팅, 접근성, 배포 단위까지 함께 봅니다.
글로 읽은 내용을 머릿속에 오래 남기려면 먼저 흐름을 그림으로 잡는 편이 좋습니다. 아래 두 그림은 Node.js를 학습할 때 계속 되돌아볼 수 있는 기준 지도입니다.
Node.js를 처음 펼칠 때는 세부 명령보다 큰 그림이 먼저입니다. 이 섹션에서는 앞으로 배울 개념들이 어떤 문제를 풀기 위해 등장했는지부터 잡아봅니다.
# nvm으로 버전 관리
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 22
nvm use 22
node --version # v22.x.x여기서는 npm & package.json을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"dev": "node --watch src/index.js",
"build": "tsc",
"test": "node --test"
},
"dependencies": {
"express": "^4.19.0"
},
"devDependencies": {
"typescript": "^5.5.0"
}
}| 명령 | 동작 |
|---|---|
| npm install | package.json 버전 범위 내에서 설치, lock 파일 갱신 가능 |
| npm ci | lock 파일에 고정된 버전 그대로 설치 — 빠르고 재현 가능, CI에서 표준 |
| ^1.2.3 | 1.x.x 범위 내 최신 버전 허용 (semver 마이너/패치 업데이트) |
| ~1.2.3 | 1.2.x 범위 내 최신 버전만 허용 (패치 업데이트만) |
여기서는 ES Modules vs CommonJS을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
// ES Modules 사용 선언
{ "type": "module" }
// ESM
import fs from 'node:fs/promises';
export const helper = () => {};
// CJS (기본값, type:module 없을 때)
const fs = require('fs');
module.exports = { helper };여기서는 이벤트 루프 & 비동기을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
console.log("1. 동기 코드");
setTimeout(() => console.log("4. setTimeout (매크로태스크)"), 0);
Promise.resolve().then(() => console.log("3. Promise.then (마이크로태스크)"));
console.log("2. 동기 코드");
// 출력 순서: 1 → 2 → 3 → 4
// 마이크로태스크(Promise)는 현재 동기 코드가 끝나자마자,
// 매크로태스크(setTimeout)보다 항상 먼저 처리됩니다.여기서는 파일 시스템 (fs)을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
import { readFile, writeFile } from 'node:fs/promises';
import { createReadStream, createWriteStream } from 'node:fs';
// 작은 파일 — 전체를 메모리에 올려도 무방
const data = await readFile('config.json', 'utf8');
await writeFile('output.json', JSON.stringify(JSON.parse(data), null, 2));
// 큰 파일 — 스트림으로 조금씩 처리 (메모리에 전체를 올리지 않음)
createReadStream('large-input.csv')
.pipe(createWriteStream('large-output.csv'));여기서는 Express.js을 실제 코드와 함께 확인합니다. 예제를 그대로 따라 하기보다, 입력과 출력, 그리고 바뀌기 쉬운 부분이 어디인지 보면서 읽어보세요.
import express from 'express';
import cors from 'cors';
const app = express();
app.use(cors());
app.use(express.json());
app.get('/users', async (req, res) => {
const users = await db.findAll();
res.json(users);
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ error: err.message });
});
app.listen(3000, () => console.log('Server on :3000'));Node.js 실무 설계은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.
| 결정 지점 | 확인 질문 | 실무 기준 |
|---|---|---|
| 경계 | Node.js 코드에서 바뀌기 쉬운 부분은 어디인가? | 입출력, 설정, 외부 연동, 핵심 규칙을 분리합니다. |
| 상태 | 상태가 어디서 생성되고 어디서 사라지는가? | 상태 소유자와 수명 주기를 코드로 드러냅니다. |
| 장애 | 실패했을 때 호출자는 무엇을 받는가? | timeout, fallback, error contract를 먼저 정합니다. |
이 섹션은 Node.js 운영 기준을 실무 관점에서 정리합니다. 개념을 외우기보다, 어떤 상황에서 이 기준을 꺼내 쓸지에 초점을 맞춰보세요.
Node.js 검증 전략은 선택지가 갈리는 지점입니다. 표를 기준으로 각 방법의 쓰임새와 운영상의 차이를 비교해두면 이후 판단이 훨씬 쉬워집니다.
| 품질 축 | 검증 방법 | 완료 기준 |
|---|---|---|
| 정확성 | 정상/실패 케이스를 자동화합니다. | 핵심 시나리오가 재현 가능하게 통과합니다. |
| 회귀 방지 | 버그 수정 시 동일 케이스를 테스트로 남깁니다. | 같은 장애가 다시 배포되지 않습니다. |
| 운영성 | 로그, 메트릭, 알림을 확인합니다. | 문제가 생겼을 때 원인 추적 경로가 있습니다. |