[nodejs] form (get, post)

- 10 mins

폼(form)

특정 사이트에 회원가입을 하거나 로그인 할 때를 생각해보면,

아이디, 비밀번호, 기타 정보를 입력하고 ‘확인’ 등의 버튼을 누른다.

버튼을 누르면 우리가 입력한 데이터가 서버로 전송될 것이다.

그리고 서버에서는 그 데이터가 올바른 데이터인지 체크하고,

체크한 결과에 따라 사용자에게 적절한 응답을 해줄것이다.


로그인할때 아이디와 비밀번호를 입력하고 확인 버튼을 누른다.

그럼 내가 입력한 아이디와 비밀번호는 서버로 전송될것이다.

서버는 자신이 저장하고있는 아이디, 비밀번호와 일치하는지 확인할 것이고,

일치한다면 ‘로그인 되었습니다’ 등의 메시지를,

일치하지 않는다면 ‘비밀번호를 다시 확인해주세요’ 등의 메시지를 띄워줄 것이다.


이처럼 클라이언트가 특정 데이터를 서버에 전송해서 처리할 수 있도록하는 일련의 인터페이스를 폼 이라고 한다.

쉽게 생각하면, 회원가입이나 로그인 화면을 폼의 일종이라고 생각하면 된다.

간단한 예제를 보자.

// app.js
var express = require('express');
var app = express();

app.locals.pretty = true;

app.set('view engine', 'jade');
app.set('views', './views');

app.get('/login', (req, res) => {
  res.render('login.jade');
})

app.listen(3000, () => console.log('connected, 3000'));

/login이라는 경로로 접속하면 화면에 login.jade 내용을 띄워주는 간단한 코드이다.

login.jade는 다음과 같이 생겼다.

doctype html
html
  head
    meta(caharset="utf-8")
  body
    p
      |아이디
      input(type="text")
    p
      |비밀번호
      input(type="text")
    input(type="submit" value="로그인")

위 코드는 다음과 같이 두 개의 입력박스와 한 개의 제출박스로 이루어진 간단한 화면을 출력해준다.

폼

현재 상태에서는 아이디와 비밀번호를 입력하고 로그인 버튼을 눌러도 아무일도 발생하지 않을것이다.

단순히 입력 박스만 띄웠을뿐, 입력한 데이터를 전송하기 위한 처리를 해주지 않았기 때문이다.

즉, 이 상태 만으로는 아직 폼 이라고 할 수가 없다.

다음과 같이 form 태그를 추가해보자.

doctype html
html
  head
    meta(caharset="utf-8")
  body
    form(action="login_check")
      p
        |아이디
        input(type="text")
      p
        |비밀번호
        input(type="text")
      input(type="submit" value="로그인")

body 바로 밑에 form 태그가 추가된것을 확인할 수 있다.

form태그를 보니 action="login_check" 라는 옵션이 있다.

이는 “login_check”라는 이름의 페이지로 해당 form안에 입력된 데이터들을 전송한다는 의미이다.

데이터의 전송은 submit을 하는 순간 발생한다. (즉, login 버튼을 누르는 순간)

이대로 실행하면 다음과 같은 에러가 발생한다.

폼

login_check 라는 페이지가 없기 때문이다.

해당 페이지에 대한 라우터를 추가해주자.

  1 var express = require('express');
  2 var app = express();
  3
  4 app.locals.pretty = true;
  5 app.use(express.static('static'))
  6
  7 app.set('view engine', 'jade');
  8 app.set('views', './views');
  9
 10 app.get('/login', (req, res) => {
 11   res.render('login');
 12 })
 13
 14 app.get('/login_check', (req, res) => {
 15   var id = req.query.id;
 16   var pw = req.query.pw;
 17   res.send(`id : ${id}, pw : ${pw}`);
 18 })
 19
 20 app.listen(3000, () => console.log('connected, 3000'));

14 ~ 18번째 줄에 ‘login_check’ 페이지를 처리할 수 있는 라우터를 추가했다.

그리고 사용자가 입력한 아이디와 비밀번호를 변수에 담아 화면에 출력하도록 코딩해두었다.

아이디와 비밀번호는 사용자가 입력한 데이터이므로 req 객체에 담겨있으며,

더 정확히는 req.query 객체에 담겨있다.

그래서 15, 16번째 줄에서 req.query.id, req.query.pw와 같이 데이터를 받아오고있다.


근데 생각해보니 ‘id’나 ‘pw’같은 이름은 정의해준적이 없다.

이는 다음과 같이 jade 파일의 input 태그에서 정의해주면 된다.

doctype html
html
  head
    meta(caharset="utf-8")
  body
    form(action="login_check")
      p
        |아이디
        input(type="text" name="id")
      p
        |비밀번호
        input(type="text" name="pw")
      input(type="submit" value="로그인")

input 태그에 name이라는 옵션을 주고 이름을 지정했다.

앞의 코드에서 아이디는 “req.query.id”로, 비밀번호는 “req.query.pw”로 받기로 해놓았으므로,

그 규칙에 따라 아이디를 받는 변수는 “id”, 비밀번호를 받는 변수는 “pw”로 지정했다.

다시 실행해보면 다음과 같이 화면에 제대로 출력되는 것을 확인할 수 있다.

폼

이처럼 폼을 이용하면 사용자가 입력한 데이터를 서버로 전송해 처리할 수 있다.


하지만 현재 url을 보면 다음과 같이 사용자가 넘긴 데이터가 그대로 노출되고있다.

http://127.0.0.1:3000/login_check?id=myid&pw=mypassword

사용자가 아이디, 비밀번호로 입력한 myid, mypassword 라는 데이터가 그대로 노출되었다.

이는 현재 form태그로 전송하는 데이터의 타입이 get 방식으로 되어있기 때문이다.

doctype html
html
  head
    meta(caharset="utf-8")
  body
    form(action="login_check" method="get")
      p
        |아이디
        input(type="text" name="id")
      p
        |비밀번호
        input(type="text" name="pw")
      input(type="submit" value="로그인")

form 태그에 method라는 속성으로 “get”을 추가하고 실행해보자.

결과는 똑같이 나올 것이다.

method 속성은 기본 값이 get 으로 되어있기 때문이다.

즉, 여태까지 알아본 데이터 전송 방식은 get 방식이다.


url에서 데이터를 감추기 위해서는 post라는 방식을 사용해야한다.

다음과 같이 method를 post로 변경하고 다시 실행해보자.

doctype html
html
  head
    meta(caharset="utf-8")
  body
    form(action="login_check" method="post")
      p
        |아이디
        input(type="text" name="id")
      p
        |비밀번호
        input(type="text" name="pw")
      input(type="submit" value="로그인")

다음과 같은 에러가 발생한다.

폼

login_check라는 페이지가 없다고한다.

아까 분명히 라우터를 추가해줬는데 무슨일일까?

자세히보면 Cannot 'POST' /login_check 라고 써있는것을 볼 수 있다.

맨 처음 login_check 페이지가 없을때 나왔던 에러랑 비교해보자.

폼

Cannot 'GET' /login_check 라고 되어있다.

그렇다.

생각해보면 당연하지만, POST에 대한 처리를 따로 해주어야 하는 것이다.

login_check 페이지의 post 요청에 대한 라우터를 추가해보자.

  1 var express = require('express');
  2 var app = express();
  3
  4 app.locals.pretty = true;
  5 app.use(express.static('static'))
  6
  7 app.set('view engine', 'jade');
  8 app.set('views', './views');
  9
 10 app.get('/login', (req, res) => {
 11   res.render('login');
 12 })
 13
 14 app.get('/login_check', (req, res) => {
 15   var id = req.query.id;
 16   var pw = req.query.pw;
 17   res.send(`id : ${id}, pw : ${pw}`);
 18 })
 19
 20 app.post('/login_check', (req, res) => {
 21   var id = req.body.id;
 22   var pw = req.body.pw;
 23   res.send(`id : ${id}, pw : ${pw}`);
 24 })
 25
 26 app.listen(3000, () => console.log('connected, 3000'));

20 ~ 24번째 줄에 post를 처리할 수 있는 라우터를 추가했다.

얼핏보면 14 ~ 18번째 줄에 추가한 코드와 비슷해보인다.


자세히보면 get 메소드 대신 post 메소드를 사용했고,

req.query 대신 req.body 에서 데이터를 받아오고있다.

한 번에 실행됐으면 좋겠지만, 역시나 다음과 같은 에러가 발생한다.

폼

이는 현재 프로그램에서 ‘body’라는 속성을 인식하지 못하기 때문이다.

express에서는 기본적으로 post 기능을 제공하지 않는다.

따라서 다음과 같이 body-parser 라는 미들웨어를 설치해주어야한다.

npm install body-parser

그리고 다음 두 줄을 추가하면 된다.

const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false})

전체 코드를 보면 다음과 같다.

var express = require('express');
var app = express();

const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))

app.locals.pretty = true;
app.use(express.static('static'))

app.set('view engine', 'jade');
app.set('views', './views');

app.get('/login', (req, res) => {
  res.render('login');
})

app.get('/login_check', (req, res) => {
  var id = req.query.id;
  var pw = req.query.pw;
  res.send(`id : ${id}, pw : ${pw}`);
})

app.post('/login_check', (req, res) => {
  var id = req.body.id;
  var pw = req.body.pw;
  res.send(`id : ${id}, pw : ${pw}`);
})

app.listen(3000, () => console.log('connected, 3000'));

이제 사용자가 데이터를 입력하고 확인 버튼을 누르면,

bodyParser라는 녀석이 먼저 동작하면서 사용자가 입력한 데이터를 프로그램에서 사용할 수 있게 파싱해준다.

body 라는 요소를 사용할 수 있도록 만들어준다고 생각하면 된다.

이제 다음과같이 정상 동작하는것을 확인할 수 있다.

폼

url에도 더이상 사용자가 입력한 데이터가 노출되지 않는다.

정리

폼을 통해 사용자가 입력한 데이터를 서버로 보내 처리할 수 있다.

서버로 보내 처리하는 방식에는 크게 GET, POST 방식이 있다.


결국 사용자가 입력한 데이터를 서버로 보낸다는 점에서 GET과 POST는 다를게 없다.

하지만 GET 방식은 url에 데이터 상세 내용이 전부 드러난다.

따라서 어떤 정보를 전부 표현하고 싶을때는 GET방식을 사용하면 된다.

친구에게 링크를 보내주고, 완전히 똑같은 화면을 공유하고싶다면 GET 방식을 사용해야한다.


반면 POST 방식은 url에 데이터 내용이 감추어진다.

따라서 예시로 든 로그인 화면과 같이 사용자가 입력한 정보를 숨기고싶을때 사용하면 된다.


그리고 만약 GET방식으로 데이터를 보낼때 내용이 엄청 길어지면,

url의 최대 길이 한계때문에 데이터가 짤릴수있다.

따라서 특정 게시글을 작성하고 서버에 데이터를 보낼때는 POST 방식으로 하는게 더 합리적이다.


즉, 모든 기술이 그렇지만 상황에따라 적절한 방식을 선택해야한다.




코딩장이

코딩장이

-장이: [접사] ‘그것과 관련된 기술을 가진 사람’의 뜻을 더하는 접미사.

rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora