Node.js 교재 · 13편 · Express

Express 입문 — 설치·라우팅·응답 보내기

12편의 raw http 코드가 절반으로. Node 표준 웹 프레임워크 첫 만남.

Express 라우터가 요청을 분기하는 컨셉 아이소메트릭 일러스트

12편에서 raw http 모듈로 서버를 만들면서 — switch 로 라우팅, chunk 모아 본문 파싱, 매번 헤더 + status 직접. 5 라우트만 되어도 코드가 어수선해졌다.

Express 는 그 반복을 함수 호출로 줄인다. 2010 년에 등장해 지금도 npm 다운로드 주간 3천만+ 의 Node 백엔드 표준. NestJS·Fastify 같은 후속작도 결국 Express 의 컨셉을 따른다. 한 번은 손에 익혀야 할 도구.

1. 설치 — 한 줄

$ mkdir my-api && cd my-api $ npm init -y $ npm install express $ npm install -D @types/express # TS 쓸 때

5편 npm 챕터에서 다룬 그대로. express 본체는 dependencies, 타입 정의(@types/express)는 devDependencies 로.

package.json"type": "module" 추가 (4편 ESM 챕터). 이 교재의 코드는 모두 ESM 기준.

2. 가장 단순한 서버 — 10줄

// server.js import express from 'express'; const app = express(); app.get('/', (req, res) => { res.send('안녕, Express!'); }); app.get('/api/health', (req, res) => { res.json({ status: 'ok', ts: Date.now() }); }); app.listen(3000, () => { console.log('http://localhost:3000'); });

12편의 raw http 코드와 비교 — switch 분기·writeHead·Content-Type 헤더가 다 사라졌다. app.get(경로, 핸들러) 한 줄로 라우트 등록, res.send 또는 res.json 으로 응답.

Express 의 정체 — 내부적으로 raw http.createServer 를 호출한다. Express 의 req·res 객체는 Node 의 IncomingMessage·ServerResponse 를 상속해 메서드를 추가한 것. 그래서 req.headers 같은 Node 본래 속성도 그대로 쓸 수 있다.

3. 응답 메서드 — 자주 쓰는 5가지

메서드역할
res.send(body)문자열·Buffer·객체 자동 감지res.send('hello')
res.json(obj)JSON.stringify + Content-Type 자동res.json({ ok: true })
res.status(code)status 설정 (체이닝 가능)res.status(404).json({err})
res.redirect(url)302 리디렉트res.redirect('/login')
res.sendFile(path)파일 그대로 응답 (Streaming)res.sendFile(absPath)

체이닝이 자주 쓰인다 — res.status(404).json({ error: 'not found' }). raw http 의 res.writeHead(404, …) + res.end(…) 두 줄이 한 줄로.

4. 라우팅 — 메서드별·동적 세그먼트

Express 는 모든 HTTP 메서드를 메서드 이름으로 직접 등록.

app.get('/posts', listPosts); app.post('/posts', createPost); app.get('/posts/:id', getPost); app.put('/posts/:id', updatePost); app.delete('/posts/:id', deletePost);

:id 가 동적 세그먼트. 핸들러 안에선 req.params.id 로 받는다.

app.get('/posts/:id', (req, res) => { const id = req.params.id; // string const post = db.posts.find(p => p.id === id); if (!post) return res.status(404).json({ error: '찾을 수 없음' }); res.json(post); });

여러 동적 세그먼트도 — /users/:userId/posts/:postId. req.params 객체에 둘 다 담겨 온다.

5. JSON 본문 파싱 — express.json()

12편에서 raw http 는 req.on('data', ...) 로 chunk 를 모았다. Express 는 미들웨어 한 줄로 자동.

// server.js import express from 'express'; const app = express(); app.use(express.json()); // ← 이 한 줄 app.use(express.urlencoded({ extended: true })); // 폼 데이터 app.post('/api/echo', (req, res) => { res.json({ received: req.body }); // 자동으로 파싱된 객체 });

이게 Express 의 진정한 가치 — 미들웨어 체인. app.use(fn) 으로 등록된 함수가 모든 요청에 순서대로 실행되고, 끝나면 다음으로 넘긴다. express.json() 은 그저 "JSON 본문을 파싱해 req.body 에 박아 다음으로 넘기는 함수". 14편에서 자세히.

본문 크기 제한 — 기본 1MB. 더 받아야 하면 express.json({ limit: '10mb' }). 너무 크게 잡으면 DoS 공격 표면이 되니까 필요한 만큼만.

raw http vs Express — 같은 일 비교

같은 POST /echo 엔드포인트를 두 방식으로.

// raw http — 약 25줄 http.createServer((req, res) => { if (req.method === 'POST' && req.url === '/echo') { let body = ''; req.on('data', c => body += c); req.on('end', () => { try { const data = JSON.parse(body); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ received: data })); } catch { res.writeHead(400); res.end('Invalid JSON'); } }); } }); // Express — 5줄 app.post('/echo', (req, res) => { res.json({ received: req.body }); });

5배 짧고 더 읽힌다. 에러 처리·파싱은 Express 가 알아서. 이게 npm 다운로드 3천만의 이유.

요약 — 13편 좌표

여기까지 정리. npm install expressexpress() 호출로 앱 생성. 라우트는 app.get/post/put/delete(경로, 핸들러). 응답은 res.send/json/status/redirect/sendFile. JSON 본문 파싱은 app.use(express.json()) 한 줄. 동적 세그먼트는 :idreq.params.id. 다음 편에서 진짜 강력한 부분 — 라우팅 분리와 미들웨어 체인.

다음 편 예고 — Express 라우팅·미들웨어

Router 분리, 미들웨어 체인, 인증 미들웨어 만들기. 14편.

© 2026 주나이테크(주) @JUNAITECH