서버에 form 데이터를 넘기는 방법

cautious·2021년 4월 25일
2
post-custom-banner

사용자가 입력한 내용을 서버로 넘길 때 form 태그를 사용한다. form 안 input 태그에 작성한 데이터를 서버로 넘기려는 방법을 간단하게 적어둔다.

1. HTML에서 직접 서버로 넘기기

프론트를 거치지 않고 바로 서버로 데이터를 보낼 수 있다.
html 태그에 메소드와 주소를 명시해 두면 직접 서버로 보내고, 서버는 데이터를 받아 처리한다.

  • action: 보내는 주소를 작성 (생략하면 현재 폼이 위치한 url로 설정됨)
  • method: 보내는 방법을 작성 (GET, POST)
  • name: 서버에서 input 태그의 데이터를 구별하는 데 이용한다

코드 예시

아래 코드는 서버의 /food라는 url에 POST로 데이터를 보내는 예시 코드다.
서버는 foodname=apple&foodsize=2과 같은 형식의 데이터를 받게 된다.


index.html

<form id="form" method="POST" action="/food">
  <input type="text" name="foodname" />
  <input type="number" name="foodsize" />
  <button type="submit">등록</button>
</form>

server.js

const http = require('http')
const fs = require('fs').promises

http.createServer((req,res)=> {
  if (req.method === 'POST') {
    if (req.url === '/food') {
      let body = '';
      req.on('data', data => body += data);
      return req.on('end', () => {
        console.log(body) //foodname=apple&foodsize=2 출력
      })
    }
  }
}

2. 프론트엔드 JS 코드 이용하기

입력값을 검증하거나 추가적인 로직이 필요한 경우, 프론트단에서 값을 필터링하여 서버로 보낼 수 있다. preventDefault()를 이용하여 서버로 자동 전송되는 것을 막은 후 fetch() 등의 api를 이용하여 데이터를 보낸다.


코드 예시

아래 코드는 /food라는 url에 POST로 데이터를 보내는 예시 코드다.
위 코드와는fetch()를 이용하여 데이터를 보낸다는 점이 다르다.
또한, 서버와 클라이언트는 JSON 형식으로 데이터를 주고받도록 했다. 따라서 클라이언트는 JSON.stringify()를, 서버는 JSON.parse()를 수행한다.

index.html

<form id="form">
  <input type="text" name="foodname" />
  <input type="number" name="foodsize" />
  <button type="submit">등록</button>
</form>

front.js

function registerFood(evt) {
  evt.preventDefault(); /* POST 이벤트 중지 */
  const foodname = evt.target.foodname.value;
  const foodsize = evt.target.foodsize.value;
  if (!foodname || !foodsize) {
    return alert('이름과 개수를 모두 입력하세요');
  }

  const url = '/food';
  const data = { foodname, foodsize };
  fetch('/food', {
    method: 'POST',
    body: JSON.stringify(data),
  });
}

document.querySelector('form').addEventListener('submit', registerFood);

server.js

const http = require('http')
const fs = require('fs').promises

http.createServer((req,res)=> {
  if (req.method === 'POST') {
    if (req.url === '/food') {
      let body = '';
      req.on('data', data => body += data);
      return req.on('end', () => {
        console.log(body) //{"foodname":"apple","foodsize"="2"} 출력
        console.log(JSON.parse(body)) //{foodname:'apple',foodsize='2'} 출력
      })
    }
  }
}

3. 두 방식의 차이점

첫번째 방식은 html 내의 form에 action과 method를 정의하여 서버로 데이터를 보냈다.
두번쨰 방식은 프론트엔드의 스크립트를 이용하여 서버로 데이터를 보냈다.

두 방식에서 가장 의외였던 점은 서버가 받는 데이터의 형식이 다르다는 점이었다.
서버는 다음과 같이 데이터를 받았다.

  1. form 자체로 데이터를 보낼 때:

    • foodname=b&foodsize=123
  2. fetch api 를 이용하여 보낼 때:

    • [object Object] ( 그냥 객체상태로 전송한 경우)
    • {"foodname":"ab","foodsize":"2"} (JSON.stringfy() 후 보낸 경우)


스크립트 로딩 오류

📌 html에서 script가 로딩되지 않는 문제 해결 방법

html에 js 파일을 삽입했지만, 로딩이 제대로 되지 않았다.
왜냐하면 서버에 파일 주소로 접근했을때 js 파일을 서빙해주는 코드를 작성하지 않았기 때문이었다.

html의 body는 다음과 같이 작성했었다.

index.html

<body>
  <div>
    <form id="form">
        <input type="text" name="foodname" />
        <input type="number" name="foodsize" />
        <button type="submit" onclick="registerFood()">등록</button>
    </form>
  </div>
  <script src="front.js"></script> <!-- FIXME: front.js가 로딩되지 않음 -->
</body>

html에 삽입한 주소는 front.js 다.
로컬서버를 구동하면 html에서 js파일을 링크한 주소는 http://localhost:8080/front.js가 된다. 하지만, 서버에선 해당 링크에 대한 요청을 처리하는 코드를 작성하지 않았기 때문에 오류가 발생했다. 해당 주소로 접근하면 맞는 js파일을 서빙해주도록 서버측 코드를 작성해야 한다.

server.js

http.createServer((req, res) => {
  if (req.method === 'GET') {
    // 요청한 url에 맞는 파일을 서빙해주는 코드
    const data = fs.readFile(`.${req.url}`);
      data
        .then(file => {
          res.end(file);
        })
        .catch(err => { /* 유저에겐 오류 페이지를 보여주어야 한다 ex.404*/
          console.error(err);
          res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end(err.message);
        });
  }
}

문제를 해결하기 위해 아래 스택오버플로 글을 참고했다.
https://stackoverflow.com/questions/48050666/node-js-serve-html-but-cant-load-script-files-in-served-page/48050718

참고

https://developer.mozilla.org/ko/docs/Learn/Forms/Your_first_form
https://developer.mozilla.org/ko/docs/Learn/Forms/Sending_and_retrieving_form_data

profile
cautious
post-custom-banner

0개의 댓글