TypeScript는 JavaScript에 정적 타입을 추가한 상위 언어로, 컴파일하면 JavaScript가 됨
Node.js
JavaScript를 브라우저 밖에서 실행하게 해주는 런타임 환경
Python에서 python 인터프리터가 .py 파일을 실행하는 것처럼, Node.js가 .js 파일을 실행
V8 엔진(Chrome에서 사용하는 JS 엔진) 기반으로 빠른 실행 속도
왜 브라우저 밖에서 JS를 실행해야 하나
JS를 잘 쓰는 프론트엔드 개발자가 이미 매우 많았고, “프론트도 백엔드도 같은 언어로 하고 싶다”는 수요에서 Node.js가 탄생 (2009년)
가장 큰 실용적 이유는 프론트엔드 빌드 도구를 돌리기 위해서
React, Vue, TypeScript 등을 브라우저가 이해하는 JS로 변환(빌드)하는 과정 자체가 Node.js 위에서 실행됨
npm run build → Node.js가 webpack/vite를 실행하여 JSX/TS를 순수 JS로 변환
프론트엔드만 해도 Node.js가 필수인 이유
Node.js로 할 수 있는 것
용도
가능 여부
예시
웹 서버 / API 서버
✅
Express, Fastify, NestJS
파일 읽기/쓰기
✅
fs 모듈 (Python의 open()과 동일)
DB 연결
✅
PostgreSQL, MongoDB, Redis 등
CLI 도구
✅
eslint, prettier, Claude Code 자체도 Node.js
빌드 도구
✅
webpack, vite, tsc (TypeScript 컴파일러)
스크립트/자동화
✅
Python 스크립트 대신 JS로 작성
데스크톱 앱
✅
Electron (VS Code, Slack, Discord가 이걸로 만듦)
데이터 과학 / ML
❌ 약함
이 영역은 Python이 압도적 (numpy, pandas, pytorch 등)
시스템 프로그래밍
❌ 약함
저수준 작업은 C/Rust 영역
브라우저 JS vs Node.js — 같은 언어, 다른 환경
같은 JavaScript 문법이지만 사용할 수 있는 API가 다름
Python도 Jupyter에서의 Python과 서버에서 돌리는 Python이 같은 언어지만 환경에 따라 쓸 수 있는 기능이 다른 것과 비슷
브라우저 JS
Node.js
DOM 조작
✅ document.getElementById()
❌ 브라우저가 없으니 DOM도 없음
화면 그리기
✅ HTML/CSS 렌더링
❌
파일 시스템
❌ 보안상 접근 불가
✅ fs.readFile()
네트워크 서버
❌
✅ http.createServer()
OS 정보
❌
✅ os.cpus(), os.platform()
프로세스 실행
❌
✅ child_process.exec()
Node.js 기본 사용
# Node.js 버전 확인node --version# v20.11.0# JavaScript 파일 실행 (uv run python app.py와 동일한 감각)node index.js# REPL 모드 (python 입력 시 대화형 모드와 동일)node# > console.log("Hello")# Hello
프론트엔드 프레임워크와의 관계
React, Next.js, Vue.js 등도 결국 npm/pnpm으로 설치하는 Node.js 패키지
개발 시에는 Node.js 환경에서 빌드하고, 빌드 결과물(HTML, CSS, JS)이 브라우저에서 실행됨
프론트엔드 프로젝트를 열어도 package.json, node_modules가 있는 이유
npm (Node Package Manager)
개념
Node.js의 기본 패키지 매니저로 Node.js 설치 시 함께 설치됨
역할
JavaScript/TypeScript 패키지 설치, 업데이트, 제거
프로젝트 의존성 버전 관리
스크립트 실행 인터페이스 (npm run ...)
Python의 uv와 가장 유사하지만, 스크립트 실행 기능까지 포함
npm 핵심 명령어
npm 명령어 (uv 비교 포함)
# 프로젝트 초기화 — package.json 생성npm init # 질문에 답하며 설정 (uv init과 유사)npm init -y # 기본값으로 빠르게 생성# 의존성 설치npm install # package.json 기반 전체 설치 (uv sync)npm install axios # 런타임 의존성 추가 (uv add requests)npm install -D jest # 개발용 의존성 추가 (uv add --dev pytest)npm install axios@1.6.0 # 특정 버전 설치 (uv add requests==2.31.0)# 패키지 제거npm uninstall axios # 패키지 삭제 (uv remove requests)# 스크립트 실행 (package.json의 "scripts"에 정의된 명령)npm run dev # 개발 서버 실행npm run build # 프로덕션 빌드npm run test # 테스트 실행npm start # "start" 스크립트는 run 생략 가능# 설치된 패키지 확인npm list # 전체 의존성 트리 (uv pip list)npm list --depth=0 # 직접 설치한 패키지만npm outdated # 업데이트 가능한 패키지 확인
npm run과 uv run의 차이
npm run dev : package.json의 "scripts"에 미리 정의된 명령어 별칭을 실행
uv run python app.py : 가상환경 내에서 임의의 명령어를 실행
Node.js에서는 "scripts"에 자주 쓰는 명령을 등록하고 npm run으로 실행하는 것이 관례
// package.json"scripts": { "dev": "next dev", // npm run dev → next dev 실행 "build": "next build" // npm run build → next build 실행}
Python(uv)에는 이런 스크립트 등록 기능이 내장되어 있지 않아서 pyproject.toml의 [project.scripts]나 외부 도구를 사용
package.json — 프로젝트의 모든 것을 담는 설정 파일
역할
Python의 pyproject.toml과 동일한 위치의 파일
프로젝트 메타데이터, 의존성 목록, 실행 스크립트를 모두 포함
구조 상세 설명
package.json 예시
{ "name": "my-app", // 프로젝트 이름 "version": "1.0.0", // 프로젝트 버전 "description": "My awesome app", "main": "index.js", // 진입점 파일 "scripts": { // 실행 가능한 스크립트 정의 "dev": "next dev", // npm run dev → next dev 실행 "build": "next build", // npm run build → 프로덕션 빌드 "start": "next start", // npm start → 프로덕션 서버 "test": "jest", // npm run test → 테스트 실행 "lint": "eslint ." // npm run lint → 코드 검사 }, "dependencies": { // 런타임에 필요한 패키지 "react": "^18.2.0", // ^ : 마이너/패치 업데이트 허용 "next": "~14.0.0", // ~ : 패치 업데이트만 허용 "axios": "1.6.0" // 버전 고정 }, "devDependencies": { // 개발 시에만 필요한 패키지 "jest": "^29.7.0", // 테스트 프레임워크 "eslint": "^8.56.0", // 코드 린터 "typescript": "^5.3.0" // 타입스크립트 컴파일러 }}
Python에서 .venv/lib/python3.x/site-packages와 동일한 역할
특징
매우 큰 용량 : 작은 프로젝트도 수백 MB에 달할 수 있음
패키지 하나를 설치해도 그 패키지의 의존성, 의존성의 의존성… 이 모두 포함
반드시 .gitignore에 추가 : Python에서 .venv를 git에 올리지 않는 것과 동일
언제든 재생성 가능 : 삭제 후 npm install로 다시 설치 가능
node_modules 관리
# .gitignore에 추가 (필수)echo "node_modules/" >> .gitignore# node_modules가 꼬였을 때 — 삭제 후 재설치 (uv에서 .venv 삭제 후 uv sync 하는 것과 동일)rm -rf node_modulesnpm install# node_modules 용량 확인du -sh node_modules# 487M node_modules ← 흔한 광경...# 프로젝트별 node_modules 한번에 정리 (디스크 절약)npx npkill # 터미널 UI에서 node_modules 폴더를 선택적으로 삭제
npm의 node_modules 구조 (Flat 방식)
npm의 의존성 구조
node_modules/├── axios/ # 직접 설치한 패키지├── follow-redirects/ # axios의 의존성이지만 최상위에 배치 (hoisting)├── form-data/ # axios의 의존성└── proxy-from-env/ # axios의 의존성→ npm은 의존성을 최대한 최상위(flat)로 올려서 중복을 줄임→ 단점: 직접 설치하지 않은 패키지도 import할 수 있는 문제 (유령 의존성)
pnpm — 더 빠르고 엄격한 패키지 매니저
개념
npm과 동일한 역할이지만 디스크 효율성과 의존성 엄격성에 초점을 맞춘 대안
pnpm의 핵심 차별점
공용 스토어(Content-Addressable Store) 기반
패키지 파일을 전역 스토어(~/.pnpm-store)에 한 번만 저장
각 프로젝트의 node_modules에는 하드링크로 연결
10개 프로젝트에서 같은 버전의 React를 써도 디스크에는 1벌만 존재
uv가 전역 캐시(~/.cache/uv)를 활용하는 것과 유사한 접근
유령 의존성(Phantom Dependency) 차단
npm은 의존성을 flat하게 올리기 때문에 package.json에 선언하지 않은 패키지도 실수로 import 가능
pnpm은 직접 선언한 패키지만 접근 가능하게 제한 → 더 안전한 의존성 관리
pnpm의 node_modules 구조
node_modules/├── .pnpm/ # 실제 패키지들 (하드링크)│ ├── axios@1.6.0/│ │ └── node_modules/│ │ ├── axios/ # 실제 파일 (스토어에서 하드링크)│ │ └── follow-redirects/ # axios의 의존성│ └── follow-redirects@1.15.0/└── axios -> .pnpm/axios@1.6.0/node_modules/axios # 심볼릭 링크→ 직접 설치한 axios만 최상위에 심볼릭 링크로 노출→ follow-redirects는 직접 import 불가 (유령 의존성 차단)
pnpm 핵심 명령어
pnpm 명령어 (npm과 비교)
# 프로젝트 초기화pnpm init # npm init과 동일# 의존성 설치pnpm install # npm installpnpm add axios # npm install axiospnpm add -D jest # npm install -D jestpnpm remove axios # npm uninstall axios# 스크립트 실행pnpm run dev # npm run devpnpm dev # pnpm은 run 생략 가능# 설치된 패키지 확인pnpm list # npm listpnpm outdated # npm outdated
npm vs pnpm 비교
항목
npm
pnpm
설치 속도
보통
빠름 (캐시 + 하드링크)
디스크 사용량
프로젝트마다 복사
전역 스토어에서 하드링크 → 절약
유령 의존성
허용됨 (flat 구조)
차단됨 (엄격한 구조)
모노레포 지원
workspace 지원
더 효율적인 workspace 지원
잠금 파일
package-lock.json
pnpm-lock.yaml
Node.js 기본 제공
✅
❌ (별도 설치 필요)
Yarn — Facebook이 만든 패키지 매니저
개념
2016년 Facebook(현 Meta)이 npm의 속도/보안 문제를 개선하기 위해 만든 패키지 매니저
npm, pnpm과 동일한 역할을 하는 또 하나의 선택지
현재는 Yarn Classic(v1)과 Yarn Berry(v2+) 두 갈래로 나뉨
Yarn 핵심 명령어
Yarn 명령어 (npm과 비교)
# 프로젝트 초기화yarn init # npm init# 의존성 설치yarn # npm install (yarn install도 가능)yarn add axios # npm install axiosyarn add -D jest # npm install -D jestyarn remove axios # npm uninstall axios# 스크립트 실행yarn dev # npm run dev (run 생략 가능)yarn build # npm run build
npm vs pnpm vs yarn 한눈에 비교
항목
npm
pnpm
yarn
개발 주체
npm, Inc (GitHub)
커뮤니티
Meta (Facebook)
설치
Node.js 기본 포함
별도 설치
별도 설치
잠금 파일
package-lock.json
pnpm-lock.yaml
yarn.lock
설치 명령
npm install
pnpm install
yarn
추가 명령
npm install pkg
pnpm add pkg
yarn add pkg
디스크 효율
낮음
높음 (하드링크)
보통 (v1) / PnP(v2+)
주 사용처
범용 (기본값)
모노레포, 대규모
React/Meta 생태계
어떤 패키지 매니저를 쓸까?
프로젝트에 이미 잠금 파일이 있으면 그에 맞는 매니저 사용
package-lock.json → npm
pnpm-lock.yaml → pnpm
yarn.lock → yarn
새 프로젝트라면 npm(기본, 무난)이나 pnpm(빠름, 엄격)을 추천
하나의 프로젝트에서 여러 패키지 매니저를 섞어 쓰면 안 됨
버전 표기법 — SemVer (Semantic Versioning)
개념
npm 생태계에서 패키지 버전은 SemVer 규칙을 따름
형식 : MAJOR.MINOR.PATCH (예: 1.6.2)
Python(PyPI)도 동일한 규칙을 따르지만, npm에서 특히 ^, ~ 같은 범위 기호를 자주 사용
# pyproject.toml (uv)dependencies = [ "requests>=2.31.0", # npm의 ">=2.31.0"과 동일 "requests>=2.31.0,<3.0.0", # npm의 "^2.31.0"과 유사 "requests~=2.31.0", # npm의 "~2.31.0"과 유사 (Compatible release) "requests==2.31.0", # npm의 "2.31.0"과 동일 (정확히 고정)]
글로벌 설치 vs 로컬 설치
로컬 설치 (기본, 권장)
프로젝트의 node_modules에 설치
프로젝트 간 의존성이 격리됨
uv가 .venv에 패키지를 설치하는 것과 동일한 개념
로컬 설치
npm install axios # ./node_modules/axios 에 설치
글로벌 설치
시스템 전역에 설치하여 어디서든 CLI 명령으로 사용 가능
uv에서 uv tool install로 CLI 도구를 전역 설치하는 것과 유사
글로벌 설치
npm install -g typescript # 어디서든 tsc 명령 사용 가능npm install -g vercel # 어디서든 vercel 명령 사용 가능# 글로벌 설치 목록 확인npm list -g --depth=0# 글로벌 설치 경로 확인npm root -g# /usr/local/lib/node_modules
uv에서 대응되는 명령어
# uv로 CLI 도구 전역 설치uv tool install ruff # 어디서든 ruff 명령 사용 가능uv tool list # 전역 설치된 도구 목록
글로벌 설치는 최소한으로
글로벌 설치는 프로젝트 간 버전 충돌 위험이 있음
가능하면 로컬 설치 + npx로 실행하는 것을 권장
글로벌로 설치할 만한 것: CLI 도구 (vercel, netlify-cli 등)
npx — 패키지를 설치하지 않고 실행
개념
npm 5.2+부터 함께 제공되는 패키지 실행 도구
글로벌 설치 없이 패키지를 임시로 다운로드하여 한 번 실행하고 버림
uv의 uvx와 동일한 개념
npx vs uvx 비교
# Node.js — npxnpx create-next-app my-app # Next.js 프로젝트 생성 도구를 임시로 받아 실행npx prettier --write . # 코드 포맷터를 설치 없이 실행npx tsc --init # TypeScript 설정 파일 생성# Python — uvx (동일한 개념)uvx ruff check . # ruff를 설치 없이 실행uvx black . # black 포맷터를 설치 없이 실행
npx 추가 활용
# 프로젝트 생성 도구 (가장 흔한 용도)npx create-react-app my-app # React 프로젝트 생성npx create-next-app my-app # Next.js 프로젝트 생성# 특정 버전으로 실행npx node@18 index.js # Node.js 18 버전으로 실행# 로컬에 설치된 패키지의 CLI 실행# node_modules/.bin/jest를 직접 쓸 필요 없이npx jest # 로컬 jest 실행
워크플로 비교 — Python (uv) vs Node.js
Python (uv)
Python 프로젝트 시작
mkdir my_app && cd my_appuv init # pyproject.toml 생성 + .venv 자동 생성uv add requests # 패키지 설치uv run python app.py # 가상환경 내에서 실행
Node.js (npm)
Node.js 프로젝트 시작
mkdir my_app && cd my_appnpm init -y # package.json 생성npm install axios # 패키지 설치 → node_modules 생성node index.js # 실행
Node.js (pnpm)
pnpm 프로젝트 시작
mkdir my_app && cd my_apppnpm init # package.json 생성pnpm add axios # 패키지 설치node index.js # 실행 (런타임은 동일하게 node)
Python과의 핵심 차이
Python(uv)은 가상환경 활성화 또는 uv run이 필요하지만, Node.js는 node_modules가 프로젝트 로컬에 있어서 별도의 활성화가 불필요
Node.js에서 require() 또는 import는 자동으로 가까운 node_modules를 탐색
uv의 .venv ↔ Node.js의 node_modules : 둘 다 프로젝트 로컬에 패키지를 격리하는 같은 역할
실무에서 Node.js 프로젝트를 처음 열었을 때 체크리스트
프로젝트 파악 순서
# 1. 어떤 패키지 매니저를 쓰는지 확인ls package-lock.json # 있으면 → npmls pnpm-lock.yaml # 있으면 → pnpmls yarn.lock # 있으면 → yarn# 2. 의존성 설치npm install # 또는 pnpm install, yarn# 3. 사용 가능한 스크립트 확인cat package.json | grep -A 20 '"scripts"'# "dev", "build", "start", "test" 등 확인# 4. 개발 서버 실행npm run dev # 또는 pnpm dev, yarn dev