사용자가 입력한 내용을 서버로 넘길 때 form 태그를 사용한다. form 안 input 태그에 작성한 데이터를 서버로 넘기려는 방법을 간단하게 적어둔다.
프론트를 거치지 않고 바로 서버로 데이터를 보낼 수 있다.
html 태그에 메소드와 주소를 명시해 두면 직접 서버로 보내고, 서버는 데이터를 받아 처리한다.
코드 예시
아래 코드는 서버의 /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 출력
})
}
}
}
입력값을 검증하거나 추가적인 로직이 필요한 경우, 프론트단에서 값을 필터링하여 서버로 보낼 수 있다. 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'} 출력
})
}
}
}
첫번째 방식은 html 내의 form에 action과 method를 정의하여 서버로 데이터를 보냈다.
두번쨰 방식은 프론트엔드의 스크립트를 이용하여 서버로 데이터를 보냈다.
두 방식에서 가장 의외였던 점은 서버가 받는 데이터의 형식이 다르다는 점이었다.
서버는 다음과 같이 데이터를 받았다.
form 자체로 데이터를 보낼 때:
fetch api 를 이용하여 보낼 때:
📌 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