Node.js | Express에 의한 요청 처리 기본

Express를 이용하여 Web 페이지를 만들 때에 필요한 처리로서. “쿼리 문자열 처리”, “양식 제출 처리”, “Ajax로 JSON 데이터 송수신”, “쿠키의 읽기 및 쓰기"라는 것에 대해 설명한다.

쿼리 문자열로 페라미터 전송

어느 페이지에서 다른 페이지에 액세스할 때, 어떠한 형태로 필요한 정보를 전달할 필요가 있었다. 어떤 방식을 생각할 수 있을까?

쿼리 문자열로 페라미터 전송하기

우선, 모두가 생각할 수 있는 것은 “쿼리 문자열"을 이용하는 것이다. 쿼리 문자열이라고 하는 것은, URL의 뒷부분에 사용하여 값을 작성한다. 예를 들어. http://localhost/index?a=hello와 같은 형태로 URL을 지정하여 a라는 페라미터에 “hello"를 설정하여 보낼 수 있다.

이 쿼리 문자열 값은 Request 객체의 “query” 속성 안에 정리되고 있다. 이 중에 각각의 key마다 속성으로 값이 저장된다. 예를 들어, /index?a=hello라면, quey.a에 “hello"가 저장되어 있다는 것이다.

실제로 간단한 사용 예제는 아래와 같다. views/helo.ejs

  <body>
    <h1><%= title %></h1>
    <p><%= msg %></a>
    <p><a href="/helo?p1=hello&p2=bye">link</a></p>
  </body>

routes/helo.js

var express = require('express');
var router = express.Router();
 
/* GET helo page. */
router.get('/', function(req, res, next) {
    var p1 = req.query.p1;
    var p2 = req.query.p2;
    var msg = p1 == undefined ? "" : p1 + "," + p2;
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: msg
        }
    );
});
 
module.exports = router;
app.get('/helo', helo.helo);

지난번 작성한 것처럼, views 폴더 안에 helo.ejs, routes 폴더 안에 helo.js을 배치하고, app.js 안에 이것들을 이용하기 위한 코드를 추가한다.

여기에서는 href="/helo?p1=hello&p2=bye으로 <a> 태그 링크를 작성하고 있다. 그리고 /helo 액세스 처리는 다음과 같이 쿼리 문자열에서 값을 얻어서 사용하고 있다.

var p1 = req.query.p1;
var p2 = req.query.p2;
var msg = p1 == undefined ? "" : p1 + "," + p2;

쿼리 문자열이 전달되지 않은 경우, p1과 p2의 값은 undefined이다. undefined이 아니면, 쿼리 문자열에 어떤 값이 전달되어 있다고 생각해도 좋을 것이다.

 

여기의 예제는 express 명령으로 Web 어플리케이션을 생성하고 이용하는 것을 전제로 작성하고 있다. express 명령을 사용하여 어플리케이션의 생성에 대해서는 다음을 참조한다.

express-generator 설치

양식(form) 전송

클라이언트에서의 정보 전송 기본은 역시 ‘폼(form)‘일 것이다. 폼에서 전송되는 처리도 Express는 매우 간단다다. 이것은 다음의 두 포인트에 정리된다.

POST 전송은 router.post으로 등록

Express에는 공개된 주소와 거기에 접근했을 때의 처리를 등록할 수 있게 되어 있었다. 지금까지 routes안에 제공하는 스크립트는 “router.get"을 사용하여 이 등록 작업을 해 왔다. 하지만 POST 전송 대상의 주소는 “router.post"을 사용해야 하다.

"Router".post(주소, 호출하는 함수);

이렇게 호출하여, 지정된 주소에 POST으로 액세스할 수 있다. 기본적으로 router.get을 router.post으로 작성할 뿐, 사용법은 동일하므로 바로 알 것이다.

전송 폼의 값을 body에서 얻기

전송된 폼의 값은, Request의 ‘body’라는 속성에 정리하고 있다. 이것은 다음과 같이 사용한다.

var 변수 = "Request".body[얻는 이름];

얻는 이름은 폼의 입력용 태그의 name 속성에 작성한 이름을 지정한다. 그럼 이것도 실제로 간단한 예제는 만들어 보자. 아래에 필요한 스크립트를 정리해 두었다. 이번에도 /helo 관계의 파일을 다시 작성한다.

helo.ejs

  <body>
    <h1><%= title %></h1>
    <%= msg %>
    <form method="post" action="/form">
        <input type="text" name="input1"
            value="<%= input %>">
        <input type="submit">
    </form>
  </body>

helo.js

var express = require('express');
var router = express.Router();
 
/* GET helo page. */
router.get('/', function(req, res, next) {
    var p1 = req.query["p1"];
    var p2 = req.query.p2;
    var msg = p1 == undefined ? "" : p1 + "," + p2;
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: msg,
            input: ''
        }
    );
});
 
/* POST helo page. */
router.post('/', function(req, res, next) {
var str = req.body['input1'];
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: "you typed: " + str,
            input: str
        }
    );
});
 
module.exports = router;

수정되면 Node.js를 시작하고, / helo에 접근해 본다. 입력 필드가 하나만 있는 폼이 표시된다.

적당히 뭔가 써서 전송하면, 보낸 텍스트를 폼에 표시된다. 또한 필드에 작성된 텍스트도 그대로 유지되는 것을 알 수 있다.

제출 양식에는 <form method="post" action="/helo">라고 작성하고 있다. 즉, /helo에는 GET과 POST 모두 대응이 필요하다. routes/helo.js을 보면, router.get과 router.post 모두가 준비되어 있는 것을 알 수 있을 것이다.

폼을 얻는 처리하는 router.post 부분에서는 이렇게 보내진 값을 얻을 수 있다.

var str = req.body['input1'];

이것으로 <input type="text" name="input1"> 태그의 value를 변수로 추출할 수 있다. 다음에 그것을 사용한 처리를 실행하면 된다. 알고 보면 매우 간단하다!

Ajax으로 액세스한 정보를 JSON으로 받기

최근에는 폼을 사용하지 않고 Ajax으로 필요한 정보를 서버로부터 받는 경우가 많아지고 있다. 폼보다 이것을 사용하는 것 기억해 두는 편이 좋을지도 모릅니다.

Ajax에서 액세스는 기본적으로 클라이언트에서 JavaScript로 실시하기 때문에, 액세스에 대한 처리를 Node.js의 템플릿과 스크립트를 준비할 필요는 없다. 일반적인 Ajax와 마찬가지로 Ajax 스크립트를 적 작성하면 된다.

다만, 액서스한 측(즉, Ajax에서 액세스되었을 때 서버 측의 처리)에 대해 생각해야 하는 필요가 있다. 단순히 필요한 정보를 내 보낼 정도라면 Response의 “send"를 호출하면 된다.

"Response".send(출력 );

단지 이것만으로 텍스트나 템플릿의 내용을 클라이언트에 다시 보낼 수 있다. 또한 만약 JSON을 사용하여 데이터 반환을 하고자 한다면, “json” 메소드가 편리하다.

"Response".json(JSON 형식의 데이터);

이것으로 JSON 데이터를 써서 보낼 수 있다. 수신 측에서는 텍스트를 JSON.parse하고 처리하며 된다.

그럼 이도 사용할 예를 들어 둔다.

routes/helo.js

var express = require('express');
var router = express.Router();
 
/* GET helo page. */
router.get('/', function(req, res, next) {
    var p1 = req.query["p1"];
    var p2 = req.query.p2;
    var msg = p1 == undefined ? "" : p1 + "," + p2;
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: msg,
            input: ''
        }
    );
});
 
/* POST helo page. */
router.post('/', function(req, res, next) {
    var str = req.query.input1;
    res.json(
        { msg: str }
    );
});
 
module.exports = router;

views/helo.ejs

<!DOCTYPE html>
<html>
    <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
    <script type="text/javascript">
    var ajax = null;
  
    function doAction(){
        var input = document.getElementById("input1");
        var callback = function(){
            var target = document.getElementById("msg");
            var res = JSON.parse(ajax.getResponse());
            target.textContent = "you send::" + res.msg;
        }
        ajax = new AjaxObject('/helo?input1=' + 
            input.value,callback);
    }
 
    function AjaxObject(url,callback){
        var response = null;
        var callback = callback;
          
        ajaxStart(url);
 
        this.getResponse = function(){
            return response;
        }
          
        function ajaxStart(url){
            var req =  createRequest();
            if (req == null){
                alert("실행할 수 없습니다!");
                return;
            }
            req.open("POST",url);
            req.setRequestHeader
                ("User-Agent","XMLHttpRequest");
            req.onreadystatechange = function(){
                if (this.readyState == 4 && 
                        this.status == 200){
                    precallback(this);
                }
            }
            req.send();
        }
          
        function createRequest(){
            var httplist = [
                function(){
                    return new XMLHttpRequest();
                },
                function(){
                    return new ActiveXObjct
                        ("Msxml2.XMLHTTP");
                },
                function(){
                    return new ActiveXObject
                        ("Microsoft.XMLHTTP");
                }
            ];
            for(var i = 0;i < httplist.length;i++){
                try {
                    var http = httplist[i]();
                    if (http != null) return http;
                } catch(e){
                    continue;
                }
            }
            return null;
        }
          
        function precallback(request){
            response = request.responseText;
            callback();
        }
    }
    </script>
</head>
<body onload="init()">
    <h1><%= title %></h1>
    <p id="msg"><%= msg %></a>
    <form id="form1" name="form1" method="post" action="/helo"
            onsubmit="return false;">
        <input type="text" id="input1" name="input1"
            value="<%= input %>">
        <input type="button" id="btn" value="click"
            onclick="doAction();">
    </form>
</body>
</html>

방금 전에 예제을 사용하여, helo에서 Ajax 통신에 액세스하고, JSON으로 보내진 값을 받아 표시해 본다. 아까와 마찬가지로 폼의 입력 필드에 뭔가 쓰고 버튼을 클릭하여 본다. 페이지 이동하지 않고 그 자리에서 표시가 업데이트된다.

helo.js의 router.post에서 전송된 정보에서 input1의 값을 얻고, 그것을 JSON 데이터를 클라이언트에게 돌려 보내고 있다. 다음 부분이다.

var str = req.query.input1;
res.json(
    { msg: str }
);

query는 쿼리 문자열을 정리하고 있는 속성이다. 거기에서 input1의 값을 꺼내, 그리고 Request의 ‘json’메소드로 전송한다. 전송하는 데이터는 연관 배열의 형태로 인수 준비한다. 이것으로 변수 str의 값이 msg라는 키에 보내진다. 이 후에는 Ajax 통신의 콜백 함수로 JSON 형식의 데이터를 받아 처리를 해주고 있다.

var callback = function () {
    var target = document.getElementById ( "msg");
    var res = JSON.parse (ajax.getResponse ());
    target.textContent = "you send :"+ res.msg;
}

JavaScript의 JSON.parse으로 Ajax 통신으로 받은 결과에서 getResponse의 값을 파싱하고 거기에서 msg 값을 꺼낸다. JSON을 사용하면 필요에 따라 여러 개의 값을 서버에서 받을 수 있어서 매우 편리하다. 여기서는 msg뿐이지만, 서버 측에서 보내는 값을 만들면, 여러 개의 값을 함께 보낼 수 있다.

Express에서 쿠키 이용

약간의 데이터 저장에 많이 이용되는 것이 “쿠키"이다. Express는 쿠키를 이용하기 위한 기능이 준비되어 있다. 그 사용법을 설명한다.

Express에서 쿠키

라이브러리로드

"Application".use (express.cookieParser());

쿠키를 이용하면 express의 “cookieParser"을 로드해야 한다. 이걸로 쿠키 정보를 객체로 취급할 수 있게 된다.

쿠키의 저장

"Response".cookie(이름,  [,옵션]);

쿠키를 저장하는 경우, Response의 cookie 메소드를 호출한다. 값에 붙이는 이름과 텍스트를 지정하면된다. 세번째 인수에 옵션 설정을 연관 배열로 사용할 수 있다. 예를 들어 쿠키의 유효 기간을 expires 값으로 갖게 할 수 있다.

쿠키의 얻기

"Request".cookies.이름

쿠키의 값은 cookieParser 의해 Request의 “cookies"속성으로 저장된다. 이 중에 쿠키 이름의 속성이 만들어지고 거기에 각각의 값이 저장된다.

그럼 다음에 간단한 사용 예제는 아래와 같다.

routers/helo.js

var express = require('express');
var router = express.Router();
 
/* GET helo page. */
router.get('/', function(req, res, next) {
    var str;
    try {
        str = req.cookies.lastdata;
    } catch(e){}
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: 'please type...',
            cookie: "last:" + str,
            input: ''
        }
    );
});
 
/* POST helo page. */
router.post('/', function(req, res, next) {
    var str = req.body.input1;
    res.cookie("lastdata",str,
        { expires: new Date(Date.now() + 600000)});
    res.render('helo', 
        {
            title: 'HELO Page',
            msg: "you typed: " + str,
            cookie: str,
            input: str
        }
    );
});
 
module.exports = router;

views/helo.ejs

<!DOCTYPE html>
<html>
    <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body onload="init()">
    <h1><%= title %></h1>
    <p><%= msg %></a>
    <p><%= cookie %></p>
    <form id="form1" name="form1" method="post" action="/helo">
        <input type="text" id="input1" name="input1"
            value="<%= input %>">
        <input type="submit" value="click">
    </form>
</body>
</html>

앞전에 /helo를 사용한 예제를 그대로 사용하고 있다.

/helo 폼에 뭔가 쓰게 보내면 그것이 쿠키에 저장된다. 이후, /helo에 액세스하면 저장되어 있던 값이 표시되도록 한다. 여기에 10분 동안 쿠키를 보관할 수 있도록되어 있지만, expires를 조정하여 좀 더 오래 보관 할 수 있다.

여기에서는 helo.js의 router.post에 res.cookie를 사용하여 쿠키를 저장하고, router.get에서 req.cookies.lastdata에서 쿠키 값을 얻어 표시를 수행하고 있다. 쿠키의 사용은 이렇게 Express를 사용하면 대단히 쉽게 할 수 있다.




최종 수정 : 2018-07-16