본문 바로가기

문돌이 존버/Node.js 스터디

HTML Form 및 POST 방식 데이터 전송

반응형
본 글은 생활코딩의 Node.js 강의를 보고 정리한 것입니다.

기본적인 HTML Form을 작성하고 POST 방식으로 데이터를 전송하는 과정을 살펴보겠습니다. HTML Form을 표현하는 html 파일은 아래와 같이 간단하게 적어줍니다.

<!-- form.html -->
<form action="http://localhost:3000/create_process" method="post">
    <p>
        <input type="text" name="title">
    </p>
    <p>
        <textarea name="description"></textarea>
    </p>
    <p>
        <input type="submit">
    </p>
</form>

그리고 main.js 코드를 적을 차례인데요. 지금까지 적어온 코드에서 몇 가지만 추가하는 것이라 길이가 길더라도 어렵지 않습니다^^

// main.js
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring'); // 쿼리 모듈

function templateHTML(title, list, body) {
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      <h1><a href="/">WEB</a></h1>
      ${list}
      <a href="/create">create</a>
      ${body}
    </body>
    </html>
    `;
}
function templateList(filelist) {
    var list = '<ul>';
    var i = 0;
    while (i < filelist.length) {
        list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
        i += 1;
    }
    list = list + '</ul>';
    return list;
}

var app = http.createServer((request, response) => {
    var _url = request.url;
    // console.log(request);
    var queryData = new URL('http://localhost:3000' + _url);
    var queryDataId = queryData.searchParams.get('id');
    var pathname = queryData.pathname;

    if (pathname === '/') {
        if (!queryDataId) {
            fs.readdir('./data', (err, filelist) => {
                var title = 'Welcome';
                var description = 'Hello, Node.js';
                var list = templateList(filelist);
                var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
                response.writeHead(200); // 헤더 정보 전달 (상태 코드, 메시지 등)
                response.end(template); // 데이터 정보 탑재 후 브라우저로 전송 <- write함과 동시에 response 종료
            })
        } else {
            fs.readdir('./data', (err, filelist) => {
                fs.readFile(`data/${queryDataId}`, 'utf8', (err, description) => {
                    var title = queryDataId;
                    var list = templateList(filelist);
                    var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
                    response.writeHead(200);
                    response.end(template);
                });
            });
        }
    } else if (pathname === '/create') {
        fs.readdir('./data', (err, filelist) => {
            var title = 'WEB - create';
            var list = templateList(filelist);
            // 위에서 작성한 html 파일 코드
            var template = templateHTML(title, list, `
                <form action="http://localhost:3000/create_process" method="post">
                    <p><input type="text" name="title" placeholder="title"></p>
                    <p>
                        <textarea name="description" placeholder="description"></textarea>
                    </p>
                    <p>
                        <input type="submit">
                    </p>
                </form>
            `);
            response.writeHead(200);
            response.end(template);
        });
    } else if (pathname === '/create_process') {
        var body = '';
        request.on('data', (data) => {
            body = body + data;
        });
        console.log(body);
        request.on('end', () => {
            var post = qs.parse(body);
            console.log(post);
            var title = post.title;
            var description = post.description
        });
        
        response.writeHead(200);
        response.end('success');
    } else {
        response.writeHead(404);
        response.end('Not Found');
    }

});

app.listen(3000);

위에서 중심적으로 살펴볼 내용은 request.on 부분으로 요청 바디(request body)와 관련된 것입니다. POST나 PUT 요청을 받을 때 어플리케이션에 요청 바디는 중요하며, 요청 헤더에 접근하는 것보다 좀 더 어렵습니다. 핸들러에 전달된 request 객체는 ReadableStream 인터페이스를 구현하고 있습니다.

해당 스트림에 이벤트 리스너를 등록하거나 다른 스트림에 파이프로 연결할 수 있습니다. 스트림의 'data''end' 이벤트에 이벤트 리스너를 등록해서 데이터를 받을 수 있는 것입니다.

각 'data' 이벤트에서 발생시킨 청크는 Buffer 입니다. 이 청크가 문자열 데이터라는 것을 알고 있다면 이 데이터를 배열에 수집한 다음 'end' 이벤트에서 이어 붙인 다음 문자열로 만드는 것이 좋습니다.

위의 코드에는 없지만 'error' 이벤트를 처리하는 경우도 있습니다. request 객체는 오류가 발생하면 EventEmiiter 처럼 동작합니다.

request.on('error', (err) => {
    console.error(err)
});

request 스트림의 오류가 발생하면 스트림에서 'error' 이벤트가 발생하면서 오류를 전달합니다. 이벤트에 리스너가 등록되어 있지 않다면 Node.js 프로그램을 종료시킬 수 있는 오류를 던질 것입니다. 따라서 단순한 오류 로깅만을 위해서라도 요청 스트림에 'error' 리스너를 추가해야 합니다.

지금까지 설명한 것은 Node.js의 한국어판 "HTTP 트랜잭션 해부"의 내용을 그대로 가져온 것입니다. request 부분은 클라이언트가 전달한(요청한) 내용을 받는 것이고, 이에 대한 응답의 내용을 response를 통해 진행하는 것입니다. response.writeHead() 를 통해 헤더 데이터를 전송하고, write()end() 를 통해 응답 바디를 전송합니다.

더 자세한 내용은 공식 문서를 참고해주세요.

728x90
반응형