클라이언트가 보내는 데이터 추출하기
프론트엔드에서 백엔드로 데이터를 넘기는 방식은 크게 3가지가 있습니다. 주소에 몰래 숨기거나(Params), 꼬리표처럼 붙이거나(Query), 안전한 박스에 담아 보내는(Body) 방식입니다. Express는 이 3가지 데이터를 손쉽게 객체(Object) 형태로 뽑아낼 수 있게 해줍니다.
데이터 전송 3대장 비교
| 속성명 |
주 용도 |
데이터 전달 형태 |
| req.params |
특정 데이터 하나를 식별할 때 (유저 정보 보기, 특정 게시글 삭제 등) |
/users/123 |
| req.query |
검색, 필터링, 정렬, 페이지네이션 (옵션 느낌의 데이터) |
/search?keyword=node |
| req.body |
방대한 데이터, 보안이 필요한 데이터 (로그인 아이디/비번, 게시글 작성 등) |
POST 전송 시 내부 Payload (JSON 등) |
왜 req.body만 값을 못 읽어올까요? (undefined 문제)
req.params와 req.query는 Express가 자동으로 파싱(Parsing)해 주지만, req.body는 기본적으로 undefined를 반환합니다. 본문(Body) 데이터는 크기가 매우 클 수 있기 때문에, 서버 리소스 낭비와 보안 문제를 막기 위해 개발자가 "어떤 형식의 데이터를 받을 것인지" 명시적으로 허락(미들웨어 장착)해야만 읽을 수 있습니다.
// 1. 클라이언트가 JSON(예: { "name": "Minstudio" })을 보낼 때 파싱 허락
app.use(express.json());
// 2. 클라이언트가 HTML <form> 태그로 보낼 때 파싱 허락
app.use(express.urlencoded({ extended: true }));
💡 팁: 미들웨어 배치 순서
데이터 파싱 미들웨어(express.json() 등)는 반드시 라우터(app.post(...))들보다 위쪽(코드 상단)에 작성해야 합니다. 미들웨어는 위에서 아래로 물 흐르듯 실행되므로, 미리 데이터를 파싱해 놓지 않으면 아래쪽의 라우터가 req.body를 읽지 못합니다.
Params, Query, Body 데이터 추출 실습
클라이언트가 서버로 보내는 데이터의 3가지 핵심 방식이 Express 서버 측에서 어떻게 추출되어 객체로 변환되는지 확인하세요.
const express = require('express');
const app = express();
// 💡 중요: 클라이언트가 POST 방식 등으로 보내는 JSON 형태의 본문(req.body)을
// 자동으로 파싱(해석)해주기 위해 반드시 필요한 설정입니다.
app.use(express.json());
// 1. URL Params 추출 (경로의 일부를 변수로 사용)
// 클라이언트 요청: GET /users/999
app.get('/users/:id', (req, res) => {
console.log(`\n[URL Params] 매칭 라우터: /users/:id`);
console.log(`> 추출된 req.params:`, req.params); // { id: '999' }
res.send(`유저 ID ${req.params.id} 조회 성공`);
});
// 2. Query String 추출 (주소창 물음표 뒤의 옵션들)
// 클라이언트 요청: GET /products?search=macbook&sort=price
app.get('/products', (req, res) => {
console.log(`\n[Query String] 매칭 라우터: /products`);
console.log(`> 추출된 req.query:`, req.query); // { search: 'macbook', sort: 'price' }
res.send(`검색어: ${req.query.search}, 정렬: ${req.query.sort}`);
});
// 3. HTTP Body 추출 (POST 요청 시 내부에 숨겨진 방대한 데이터)
// 클라이언트 요청: POST /login (Body: {"email":"a@b.com", "pw":"1234"})
app.post('/login', (req, res) => {
console.log(`\n[HTTP Body] 매칭 라우터: POST /login`);
console.log(`> 추출된 req.body:`, req.body); // { email: 'a@b.com', pw: '1234' }
res.send(`${req.body.email} 님 환영합니다.`);
});
app.listen(3000, () => {
console.log('서버가 3000번 포트에서 대기 중입니다...');
});
$ node server.js
서버가 3000번 포트에서 대기 중입니다...
(클라이언트 1: GET http://localhost:3000/users/999 요청)
[URL Params] 매칭 라우터: /users/:id
> 추출된 req.params: { id: '999' }
(클라이언트 2: GET http://localhost:3000/products?search=macbook&sort=price 요청)
[Query String] 매칭 라우터: /products
> 추출된 req.query: { search: 'macbook', sort: 'price' }
(클라이언트 3: POST http://localhost:3000/login 요청)
[HTTP Body] 매칭 라우터: POST /login
> 추출된 req.body: { email: 'a@b.com', pw: '1234' }