ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 제로부터 시작하는 Node.js - 12. RESTful 웹 서비스 개발
    내가 보기 위해 쓰는 것/Node.js 2019. 11. 16. 17:35

    1. RESTful 이 무슨 뜻인가요?

     - REST라는 규정을 준수하며 개발된 웹 서비스를 말합니다.

    2. REST 규정은 뭔가요?

     - (Representational State Transfer)의 약자입니다. 정말 다양한 규정들이 있습니다만 주 목적은 '일관된 웹 서비스 인터페이스 설계' 입니다. 모든 규정을 정리하기는 너무 길고, 저도 전부 알지는 못합니다. 잘 설명된 글이 있어서 링크로 대체하겠습니다. https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html

     

    [Network] REST란? REST API란? RESTful이란? - Heee's Development Blog

    Step by step goes a long way.

    gmlwjd9405.github.io

    3. 자세히 안 알려줄거면 왜 이런 챕터를 구성했나요?

     - 결국 웹 서비스를 개발한다면 RESTful 이라는 개념, 경험이 반드시 필요합니다. 간단하게라도 짚고 넘어가자는 의미에서  작성하게 되었습니다. 이 글도 완벽한 웹 서비스가 아니라 개념을 훑어보는 수준의 글입니다.

     

    늘 그렇듯, 실전으로 빨리 넘어가면서 훑어보겠습니다.

    간단하게 RESTful 서비스 구조를 훑어보겠습니다. 읽어보시면 감이 오시리라 생각합니다.

     

    경로 /collection /collection/:value
    GET 방식 컬렉션 조회 특정 컬렉션 조회
    POST 방식 컬렉션에 새 데이터 추가 없음
    PUT 방식 컬렉션 전체를 한꺼번에 변경 컬렉션에 특정 요소 수정
    DELETE 방식 컬렉션 전체 삭제 특정 컬렉션 삭제

     

    마치 sql 구문같은 구조네요. 부가적인 예를 들어보겠습니다.

     

    • GET /user - 사용자 전체 조회
    • GET /user/123 - 123번 유저 조회
    • POST /user - 사용자 추가
    • DELETE /user/123 - 123번 유저 정보 삭제

    이번 예제는 소스가 많이 깁니다.

    우선 전체를 본 후 차근차근 톺아보겠습니다.

     

    index.js 입니다.

     

    
    const express = require('express')
    const fs = require('fs')
    const bodyParser = require('body-parser')
    
    let DB = (function () {
    
      // 변수 선언
      let DB = {}
      let storage = []
      let count = 1
    
      // 메서드
      // get < 검색
      DB.get = function (id) {
        if (id) {
          id = (typeof id == 'string') ? Number(id) : id
    
          for (let i in storage) {
            if (storage[i].id == id) {
              return storage[i]
            }
          }
        } else {
          return storage
        }
      }
    
      DB.insert = function (data) {
        data.id = count++
        storage.push(data)
        return data
      }
    
      DB.remove = function (id) {
        id = (typeof id == 'string') ? Number(id) : id
    
        for (let i in storage) {
          if (storage[i].id == id) {
            storage.splice(i, 1)
            // 데이터 삭제 성공 이라는 return
            return true 
          }
        }
        // 데이터 삭제 실페 라는 return
        return false
      }
    
      return DB
    })()
    
    const app = express()
    
    app.use(bodyParser.urlencoded({
      extended: false
    }))
    
    app.get('/user', function (req, res) {
      res.send(DB.get())
    })
    
    app.get('/user/:value', function (req, res) {
      res.send(DB.get(req.params.id))
    })
    
    app.post('/user', function (req, res) {
      const name = req.body.name
      const region = req.body.region
    
      if (name && region) {
        res.send(DB.insert({
          name: name,
          region: region
        }))
      } else {
        throw new Error('error')
      }
    })
    
    app.put('/user', function (req, res) {
      const id = req.params.id
      const name = req.body.name
      const region = req.body.region
    
      let item = DB.get(id)
      item.name = name || item.name
      item.region = region || item.region
    
      res.send(item)
    })
    
    app.delete('/user', function (req, res) {
      res.send(DB.remove(req.params.id))
    })
    
    app.listen(52273, function () {
      console.log('server is running')
    })

    그리고 간단하게 테스트해보기 위해서 크롬 확장앱 Postman을 사용하겠습니다.

     

    https://chrome.google.com/webstore/detail/tabbed-postman-rest-clien/coohjcphdfgbiolnekdpbcijmhambjff?hl=ko

     

    Tabbed Postman - REST Client

    No separate window required! This is the legacy postman extension that can run in a Chrome tab. * Now runs in tab. * Does not…

    chrome.google.com

    위 소스를 실행한 후

     

    파란색 Postman 확장앱을 클릭합니다.

     

    이런식으로 url을 입력하고 간단하게 요청을 할 수 있는 확장앱 입니다.

     

    위 이미지처럼 입력하고 send를 누르면 POST방식으로 요청이 갔을테니 데이터베이스에 정보가 추가되었을 겁니다.

     

    http:127.0.0.1:52273/user 에 접속하면 데이터가 나와야 합니다.

     

    마찬가지로 PUT, DELETE등의 요청으로 바꿔서 전송하면 수정되거나 삭제할 수 있겠죠.

     

    기능이 잘 작동하는 것을 확인했으면, 소스로 다시 돌아옵시다.

     

    let DB = (function () {
    
      // 변수 선언
      let DB = {}
      let storage = []
      let count = 1
    
      // 메서드
      // get < 검색
      DB.get = function (id) {
        if (id) {
          id = (typeof id == 'string') ? Number(id) : id
    
          for (let i in storage) {
            if (storage[i].id == id) {
              return storage[i]
            }
          }
        } else {
          return storage
        }
      }
    
      DB.insert = function (data) {
        data.id = count++
        storage.push(data)
        return data
      }
    
      DB.remove = function (id) {
        id = (typeof id == 'string') ? Number(id) : id
    
        for (let i in storage) {
          if (storage[i].id == id) {
            storage.splice(i, 1)
            // 데이터 삭제 성공 이라는 return
            return true 
          }
        }
        // 데이터 삭제 실페 라는 return
        return false
      }
    
      return DB
    })()

    이 부분부터 살펴봅시다.

     

    DB라는 객체에 여러 메서드 멤버를 추가하고, 반환하여 저장했습니다.

    하나하나의 메서드를 살펴보면 사실 간단한 내용입니다. 

     

      // 메서드
      // get < 검색
      DB.get = function (id) {
        if (id) {
          id = (typeof id == 'string') ? Number(id) : id
    
          for (let i in storage) {
            if (storage[i].id == id) {
              return storage[i]
            }
          }
        } else {
          return storage
        }
      }

     

    매개변수로 받은 값을 삼항연산자를 이용하여 가공하고, storage 배열에 저장된 값에 비교 검색하여 return 하거나, 없을경우 전체를 return 하는, 말 그대로 검색 메서드입니다. 나머지도 위에서 설명한 표처럼 기능하는 매서드들입니다.

     

      DB.insert = function (data) {
        data.id = count++
        storage.push(data)
        return data
      }

     

    받은 값을 배열에 추가하는 데이터 저장 메서드입니다.

     

      DB.remove = function (id) {
        id = (typeof id == 'string') ? Number(id) : id
    
        for (let i in storage) {
          if (storage[i].id == id) {
            storage.splice(i, 1)
            // 데이터 삭제 성공 이라는 return
            return true 
          }
        }
        // 데이터 삭제 실페 라는 return
        return false
      }

    값을 가공하고, 비교하여 맞는 값이 나오면 배열에서 삭제하고 삭제성공 여부를 return 하는 메서드입니다.

     

    이렇게 DB라는 객체를 app.get, post, put 등 여러가지 메서드로 연결시켜놓았죠.

     

    app.get('/user', function (req, res) {
      res.send(DB.get())
    })

     

    /user 라는 로케이션으로 get 요청을 받을경우, 그냥 DB.get을 실행합니다. 매개변수가 없으니 모든 데이터를 보여 줄 것입니다.

     

    app.get('/user/:value', function (req, res) {
      res.send(DB.get(req.params.id))
    })

     

    /user/값 로케이션으로 get 요청을 받으면, 매개변수로 값을 보내줍니다. 검색문에 걸려서 해당 데이터를 보여 줄 것입니다.

     

    app.post('/user', function (req, res) {
      const name = req.body.name
      const region = req.body.region
    
      if (name && region) {
        res.send(DB.insert({
          name: name,
          region: region
        }))
      } else {
        throw new Error('error')
      }
    })

     

    /user 로케이션으로 post 요청이 올 경우, post요청으로 받은 값이 유효한지 검증하고, DB.insert() 메서드로 보내줍니다. 데이터가 추가 될 것입니다. 값이 유효하지 않을경우 에러처리가 되었습니다.

     

    app.put('/user', function (req, res) {
      const id = req.params.id
      const name = req.body.name
      const region = req.body.region
    
      let item = DB.get(id)
      item.name = name || item.name
      item.region = region || item.region
    
      res.send(item)
    })

    /user 로케이션으로 put 요청을 받은 경우 item 이라는 변수에 검색된 값을 저장하고, 가공하여 보여줍니다.

     

    app.delete('/user', function (req, res) {
      res.send(DB.remove(req.params.id))
    })

     

    DB.remove 메서드에 매개변수로 보내어 삭제될 것입니다.

     

    이렇게 소스는 길지만 체계적인 구조입니다.

    전체 내용보다 RESTful 개발이 어떤 느낌인지 감을 잡는게 중요합니다. express 프레임워크까지 간 후엔 반드시 해봐야 할 경험이니까요.

     

    다음 글은 진짜 데이터베이스인 MySQL을 이용하는 방법에 대해서 쓰겠습니다. 그전에 MySQL에 대한 포스팅도 하겠습니다.

    댓글

Designed by Tistory.