Skip to content

Latest commit

 

History

History
308 lines (263 loc) · 8.72 KB

0830.md

File metadata and controls

308 lines (263 loc) · 8.72 KB

0830

Web Form

HTML Form

1. HTML form의 기본 동작

  • HTML form을 전송하면, 입력된 정보가 기본적으로 percent encoding 되어 요청된다.
    • GET method
    GET /search?query=%EA%B0%9C&sort=latest HTTP/1.1
    ..
    
    • POST method
    POST /form HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    ..
    home=Cosby&favorite+flavor=flies
    

2. multipart/form-data

  • 기본 설정(percent encoding)으로는 폼으로 파일을 업로드하는 것은 불가능
  • (클라이언트 측) form 태그에 enctype="multipart/form-data" 속성을 적용하면 파일 업로드 가능
  • (서버 측) body-parser 미들웨어는 multipart/form-data 형태의 요청을 지원하지 않음 (multer 필요)

======= HTML Form 예제 # =======

  • 순수 HTML에서는 get과 post 만을 지원한다. 그래서 등록,수정,삭제 시 post를 사용한 것이다.
  • Form validation : form을 통해서 사용자가 입력한 데이터를 원하는 데이터인지 검사하는 과정이 필요하다.

form validation을 구현하는 전형적인 방법

  1. 사용자가 폼을 작성합니다.
  2. 사용자가 폼을 서버에 전송합니다.
  3. 서버는 기대한대로 데이터가 들어왔는지 검사합니다.
  4. 서버는 데이터가 기대한 대로 잘 들어왔으면 다음 단계를 진행하고, 데이터에 문제가 있다면 어떤 문제가 있는지를 사용자에게 알려줍니다. (이 프로젝트에서는 데이터에 문제가 있으면 단순하게 400 Bad Request 응답을 하고 있지만 사용자 경험을 위해서는 이렇게 하면 안되겠죠?)
  • 클라이언트 측 validation :
  1. javascript로 일일히 하나 다 짜는방법, submit 이벤트에 데이터 검사 방법
  2. HTML5 form validation : 내장되어 있어서 간편하고 모바일 측에서 좋지만, 복잡한 것에는 지원하지 않는다!!
    • required
    <input required type="text" name="title">
    
  • 서버 측 validation : 클라이언트 측에서 했지만 꼭 서버 측에서도 해주어야 한다!!
  • redirect('/')
    : 브라우저의 새로고침은 이전에 보냈던 요청을 다시 요청하는 것이다. 이렇기 때문에 redirect를 안해주면 같은 요청이 계속 가기 때문에 원하던 결과가 안 나올 수도 있다. 대신 ajax로 보낼 시에는 redirect가 아니어도 상관이 없지만, 순수 html형식으로 보낼 시에는 redirect를 써주는 것이 좋다.

    • 301 redirect: 웹브라우저에 정보를 기억 해놨다가 똑같은 요청이 오면 웹브라우저에 기억된 것을 실행
    • 302 redirect: 똑같은 요청을 보내더라도 서버에 계속 정보를 요청할 때 (form같은 부류의 요청을 사용할 때)
  • UUID (Univer)
    : 어떤 자료의 식별자를 만들 때 사용한다.

    • slug : url로 이 아이디가 무엇을 의미하는지를 알게 하고 싶을 때도 사용된다.
    • UUID : 분산 데이터베이스를 사용 하면 어떤 것이 어떤 순서로 데이터가 들어온지 알 수가 없다. 이를 위해 데이터 하나하나에 고유한 식별자를 지정해준다. 이때 쓰는 것이 UUID이다. 이때 식별자들은 숫자이며 128 bit이다.

    : 사용법은 uuid를 다운로드 한 후 다음과 같이 사용한다.

npm install uuid
const uuidv4 = require('uuid/v4')

const todos = [
  {
    id: uuidv4(),
    title: 'sample todo'
  }
]

======= HTML Form 예제 끝 =======

URL Shortener

==== 실습 ====
<< 시나리오 >>
(관리자)

  1. 로그인
  2. 긴 URL을 폼에 입력하고 전송
  3. 서버에서 URL 변환
  4. 경과확인

짧은 URL 이용하기
(방문자 or 관리자)

  1. 짧은 URL 접속
  2. 301 응답
  3. 긴 URL로 리다이렉트 됨

URL 목록 열람
(관리자)

  1. 로그인
  2. 루트경로(/)에서 열람

<< 화면설계 >>

<< 데이터 설계 >>

  1. 배열에 긴 URL을 longUrl, 짧은 URL을 id에 객체형태로 저장한다.

구현
<< 프로젝트 세팅 >>

  • npm init -y
    작업할 디렉터리를 생성한 후, .git을 생성해 준다.
$ git init -y
  • .gitignore 추가 vscode 확장자에서 gitignore를 설치해준다.
    add gitignore -> node를 선택하여 node_modules의 변경사항을 무시하는 gitignore를 생성할 수 있다.

node_modules는 깃 저장소에 넣지 않는 것이 원칙이다.

  • node_modules를 깃에 올리지 않는 이유?
    • git 저장소는 내 프로젝트의 코드를 관리하기 위한 곳이지 외부 패키지를 관리하기 위한 것이 아니다.
    • git 저장소의 용량이 커지고 git이 추적해야 할 파일이 많아지기 때문에 느려질 수 있다.

<< Express 앱 세팅 >>

  • install
$ npm install --save express
const express = require('express')
const app = express()
  • 템플릿 엔진 설정
$ npm install --save ejs
app.set('view engine', 'ejs')
  • static 라우트 설정
app.use('/static', express.static('public'))

<< 로깅과 인증 >>

  • morgan 설정 : morgan - 서버에 요청이 들어올 때 어떤게 들어오는지 보여준다.
$ npm install --save morgan
const morgan = require('morgan')
app.use(morgan('tiny'))
  • express basic auth 설정 install :
$ npm install --save express-basic--auth
const basicAuth = require('express-basic-auth')

app.use(basicAuth({
  users: { 'admin': 'admin' },
  challenge: true,
  realm: 'Imb4T3st4pp'
}))

<< 초기 데이터 작업 >>

const data = [
  {longUrl: 'http://google.com', id: '59DX23'}
]

// 짧은 url은 : http://localhost:3000/59DX23 접속하면
// 302 응답이 온다.
// 굳이 다 저장할 필요 없이 뒤에 것만 저장하자! /59DX23 

<< 표로 보여주기 >>
그리고 확인 해보기 위해 server.js 와 index.ejs를 다음과 같이 코딩해준다.

// javascript
app.get('/', (req, res) => {
  res.render('index.ejs', {data})
})
<!-- index.ejs -->
<table>
    <thead>
      <tr>
        <td>Long URL</td>
        <td>Short URL</td>
      </tr>
    </thead>
    <tbody>
    <% data.forEach(item => { %>
      <tr>
        <td><%= item.longUrl %></td>
        <td><%= item.id %></td>
      </tr>
    <% }) %>
    </tbody>
  </table>

로딩해보면 다음과 같다.

<< randomstring >>
insall:

$ npm install --save randomstring
const randomstring = require('randomstring')
// data의 id를 랜덤 스트링으로 해준다.
const data = [
  {longUrl: 'http://google.com', id: randomstring.generate(6)}
]

<< 짧은 URL의 리디렉션 >>

app.get('/:id', (req, res) => {
  const id = req.params.id
  const matched = data.find(item => item.id === id)
  if(matched) {
    res.redirect(301, matched.longUrl)
  } else {
    res.status(404)
    res.send('404 Not Found')
  }

브라우저가 저장하고 요청시 저장한 내용을 실행 하도록 301 요청을 하였다.

<< 폼 >>

  • body-parser install:
$ npm install --save body-parser
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))

한 후, index.ejs 에 form을 만든다.

<form action="/" method="post">
    <input type="url" name="longUrl" placeholder="url">
    <input type="submit" value="전송">
  </form>
// post, form으로 index.ejs에서 정보들을 가져온다.
app.post('/', (req, res) => {
  const longUrl = req.body.longUrl
  // id가 우연히 같은 것이 생성될 수도 있으니 let으로 선언해준다.
  let id
  while(true) {
    const candidate = randomstring.generate(6)
    const matched = data.find(item => item.id === candidate)
    if(!matched) {
      id = candidate
      break
    }
  }
  data.push({longUrl, id})
  res.redirect('/') // 302 응답코드
})


그리고 text에 http://naver.com 을 입력한 후 전송을 누르면

<< now.sh를 통한 배포 >>

$ npm install -g now
$ now

e-mail입력하고, 메일로 가서 confirm 받은 후, 다시 한번 돌아와서 now를 실행하면 배포할 것인지 물어본다! 그때 y를 눌러서 배포된 url을 받는다!!

내가 받은 URL = https://urlshortner-flboillbut.now.sh