Express에서 body-parser와 폼 데이터 처리하기



1. body-parser란?

body-parser는 Express에서 요청(request) 객체의 본문(body) 데이터를 쉽게 추출할 수 있도록 도와주는 미들웨어입니다. 클라이언트가 폼을 제출하면 데이터는 서버로 전송되고, 이 데이터를 파싱하여 쉽게 접근할 수 있도록 해줍니다. 요청(request)과 응답(response)의 중간에서 작업합니다. express에서는 app.use()로 등록해야 합니다.

1) 주요 기능

  • URL-encoded 데이터 파싱: HTML 폼에서 보내는 urlencoded로 파싱된 body를 요청합니다.
  • JSON 데이터 파싱: JSON 형식의 요청한 body 객체가 파싱됩니다.


2) Express 설정

(1) 기본 설정

const express = require('express'); // Express 모듈 가져오기
const app = express(); // Express 애플리케이션 객체 생성
const PORT = 8888; // 서버가 실행될 포트 번호

app.set('view engine', 'ejs'); // 뷰 엔진을 EJS로 설정
app.set('views', './views'); // 뷰 파일들이 위치하는 폴더 설정

(2) body-parser 미들웨어 설정

// body-parser 미들웨어 설정 (body 내용이 보일 수 있게 해줌)
app.use(express.urlencoded({ extended: true })); // URL-encoded 데이터 파싱
app.use(express.json()); // JSON 데이터 파싱



2. 폼 태그와 속성

1) form 요소

form 요소는 사용자의 입력 값을 서버로 전송하는 역할을 합니다. form 태그 안에는 다양한 입력 요소들이 포함될 수 있습니다.

  • action: 데이터를 전송할 서버의 URL을 지정합니다.
  • method: 데이터를 전송하는 방법을 지정합니다. 일반적으로 GET 또는 POST를 사용합니다.
<form action="/getForm" method="get">


2) input 요소

  • type: 입력 필드의 유형을 지정합니다. 예: text, password, submit, button
  • name: 서버로 전송될 때 각 입력 필드를 식별하기 위한 이름을 지정합니다.
  • placeholder: 입력 필드에 표시되는 안내 문구를 지정합니다.
  • autofocus: 페이지 로드 시 자동으로 입력 필드에 포커스를 줍니다.
  • disabled: 입력 필드를 비활성화하여 편집할 수 없도록 합니다.
  • readonly: 입력 필드를 읽기 전용으로 설정하여 수정할 수 없도록 합니다.

참고 disabled와 readonly의 차이점

  • disabled : 비활성화되어 사용자가 입력하거나 수정할 수 없습니다. 폼이 제출될 때 이 필드의 값은 전송되지 않습니다.
  • readonly : 읽기 전용으로 설정되어 사용자가 수정할 수 없습니다. 하지만 폼이 제출될 때 이 필드의 값은 전송됩니다.
<!-- 다양한 input 요소 예제 -->
<input type="text"> <br>
<input type="text" disabled> <br>
<input type="text" autofocus> <br> 
<input type="text" readonly value="안녕"> <br>


3) label 요소

label 요소는 for 속성을 사용하여 input 요소의 id와 연결할 수 있습니다.

<!-- label과 input 요소의 연결 예제 -->
<label for="username">사용자 이름: </label>
<input type="text" id="username" name="username">


4) fieldset과 legend 요소

fieldset 요소는 관련된 폼 요소들을 그룹화하는 데 사용됩니다. legend 요소는 그룹화된 폼 요소들의 제목입니다.

<!-- fieldset과 legend 요소 예제 -->
<fieldset>
    <legend>개인 정보</legend>
    <label for="name">이름: </label>
    <input type="text" id="name" name="name"><br>
    <label for="age">나이: </label>
    <input type="text" id="age" name="age">
</fieldset>


5) button 요소와 input 요소의 차이점

폼에서 사용하는 버튼에는 input 요소와 button 요소가 있습니다.

  • input[type="button"]button[type="button"]: 둘 다 클릭 가능한 단순 버튼을 생성하지만, button 요소는 태그 내에 텍스트나 HTML을 포함할 수 있습니다.
  • input[type="submit"]button[type="submit"]: 둘 다 폼 제출 버튼을 생성하지만, button 요소는 태그 내에 텍스트나 HTML을 포함할 수 있습니다.
<!-- value 속성으로 값 지정 -->
<input type="button" value="단순 버튼 1">
<!-- 태그 내 택스트 포함 가능 -->
<button type="button">단순 버튼 2</button>  
<br>
<input type="submit" value="제출 버튼 1">
<button type="submit">제출 버튼 2</button>
  • type="button": 단순 버튼으로, 폼 제출과는 관련이 없습니다.
  • type="submit": 폼을 제출하는 버튼입니다.



3. 폼에서 name 속성의 중요성

name 속성은 폼 요소에서 매우 중요합니다. 서버로 전송될 때 각 입력 필드를 식별하기 위한 키(key) 역할을 하며, 서버는 name 속성을 통해 어떤 데이터가 어떤 입력 필드에서 왔는지 알 수 있습니다. name 속성이 없으면 서버는 해당 데이터를 처리할 수 없습니다.

예제에서, name="id"name="pw"는 서버로 전송될 때 키로 사용됩니다. 서버는 이 키를 통해 어떤 데이터가 전달되었는지 식별할 수 있습니다.

<form action="/getForm" method="get">

    <!-- 폼 요소에서는 name이 아주 중요합니다. -->
    <input type="text" name="id" placeholder="아이디">
    <input type="password" name="pw" placeholder="패스워드">
    <button type="submit">GET 방식으로 폼 제출</button>
</form>


4. 폼 데이터 처리

(1) GET 요청으로 폼 데이터 처리

GET 요청은 URL에 데이터를 포함시켜 전송합니다. 폼 데이터를 쿼리 문자열로 전달하므로 보안에 취약할 수 있습니다. 예를 들어, URL이 http://example.com/getForm?id=example&pw=1234처럼 됩니다.

<!-- GET 요청으로 폼 제출 -->
<h2>GET 방식으로 요청하는 폼</h2>
<form action="/getForm" method="get">
    <input type="text" name="id" placeholder="아이디">
    <input type="password" name="pw" placeholder="패스워드">
    <button type="submit">GET 방식으로 폼 제출</button>
</form>


(2) POST 요청으로 폼 데이터 처리

POST 요청은 폼 데이터를 요청 본문(body)에 포함시켜 전송합니다. 이는 URL에 데이터가 노출되지 않아 GET 요청보다 보안이 더 좋습니다. 예를 들어, URL이 http://example.com/postForm이고, 데이터는 본문에 포함됩니다.

<!-- POST 요청으로 폼 제출 -->
<h2>POST 방식으로 요청하는 폼</h2>
<form action="/postForm" method="post">
    <input type="text" name="id" placeholder="아이디">
    <input type="password" name="pw" placeholder="패스워드">
    <button type="submit">POST 방식으로 폼 제출</button>
</form>


(3) GET 요청과 POST 요청의 차이점

  • GET 요청 : 데이터를 URL의 쿼리 문자열로 전송합니다. 보안에 취약하며, 데이터 크기에 제한이 있습니다.
  • POST 요청 : 데이터를 요청 본문(body)에 전송합니다. 보다 안전하고, 데이터 크기 제한이 상대적으로 적습니다.



5. 라우팅 설정 및 데이터 처리

(1) GET 요청 처리

GET 요청으로 전달된 폼 데이터를 처리하여 결과를 렌더링합니다.

app.get('/getForm', (req, res) => {
    console.log(req.query); // { id: 'example', pw: '1234' } // query 사용
    res.render('result', { title: 'GET 요청 결과', userInfo: req.query });
});


(2) POST 요청 처리

POST 요청으로 전달된 폼 데이터를 처리하여 결과를 렌더링합니다.

app.post('/postForm', (req, res) => {
    console.log(req.body); // { id: 'example', pw: '1234' } // body 사용
    res.render('result', { title: 'POST 요청 결과', userInfo: req.body });
});


(3) req.query와 req.body의 차이점

  • req.query : URL의 쿼리 문자열에 포함된 데이터를 가져옵니다. 주로 GET 요청에서 사용됩니다.
  • req.body : 요청 본문(body)에 포함된 데이터를 가져옵니다. 주로 POST 요청에서 사용됩니다.



6. 결과 페이지

사용자에게 폼 데이터를 출력합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        span {
          color: blue;
          font-weight: 700;
        }
    </style>
</head>
<body>
    <h1><%= title %></h1>
    <div><span><%= userInfo.id %></span>님 환영합니다!</div>
    <div>비밀번호는 <span><%= userInfo.pw %></span>이군요!!</div>
    <a href="/">홈으로 이동하기</a>
</body>
</html>