지극히 개인적인 공부 노트/웹(Web)

[Web] API 설계 시 데이터 타입 POST, GET 사용법(feat. CRUD, Flask)

AS J 2021. 6. 29. 23:54

GET, POST와 같은 데이터 타입을 이해하려면 우선 API가 무엇인지 이해해야 합니다. 간단하게 요약하면 API는 서버와 클라이언트가 서로 다른 프로그램(예를 들면 서버는 Python, 클라이언트는 html, JS)에서 요청과 응답을 서로 주고받을 수 있도록 만든 체계입니다. 대개 클라이언트는 요청을 보내고, 서버는 이에 대한 응답(데이터)을 제공하는 구조인데, 여기서 이 요청에 대한 종류를 크게 4가지, CRUD로 나눌 수 있습니다.

CRUD는 각 알파벳마다 Create, Read, Update, Delete 등의 데이터 요청 방식을 의미합니다. 여기서 각 데이터 요청 방식에 따라 API에서는 마치 스티커(실제로는 메소드라고 부름)처럼 데이터 타입을 미리 정의하고, 각 방식에 알맞게 요청과 데이터가 오갈 수 있도록 했습니다. 각 요청에 따른 데이터 타입은 아래와 같습니다.

  • Create(생성하기): POST
  • Read(불러오기): GET
  • Update(변경하기): PUT(전체) / PATCH(일부)
  • Delete(삭제하기): DELETE

이 중에서 간단한 개인 토이 프로젝트를 진행하며 사용해본 POST와 GET 메소드의 간략한 사용법(코드)에 대해 기록해봤습니다. 해당 프로젝트는 한 페이지에 고객의 주문 정보(이름, 주문 수량, 주소, 전화번호)를 입력(POST)하면 DB(데이터베이스)에 저장되며, 저장된 주문 정보를 확인(GET)하는 아주 간단한 프로젝트였습니다.

 

0. 세팅

실행되는 전체적인 경로는 이 사진과 같습니다.

우선, 진행하기 전에 해당 프로젝트를 저장한 디렉터리(폴더) 내에 하위 디렉터리로 'static', 'templates'라는 디렉터리를 만들고, 그 중 templates 디렉터리 안에 index.html 파일을 하나 만들어둡니다. 그리고 원래의 디렉터리에는 app.py 파일을 생성하고 아래와 같이 입력합니다.

코드는 아래와 같이 Python 기반 마이크로 웹 프레임워크 중 하나인 Flask와 필요한 클래스를 임포트해서 사용했습니다. 그리고 기본으로 정의해야 할 변수와 함수도 함께 정의했습니다. 보이는 것처럼 '@app.route('/')' 아래에 함수를 정의해두면, 클라이언트가 route 안에 있는 주소에서 요청을 할 때 자동으로 실행됩니다.

from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

## HTML 화면 보여주기
@app.route('/')
def toy_project():
    return render_template('index.html')    # templates 디렉터리 안의 index.html 파일 실행

 

1. POST 사용법

1) index.html 파일의 Javascript 부분에는 다음과 같이 작성했습니다. html의 input 태그에 입력받은 정보를 다음과 같이 4가지 변수(name, count, address, phone_num)로 선언 및 저장합니다. 이후, 각각 입력받은 데이터가 올바르게 입력됐는지 체크하는 부분(if문)을 거쳐 ajax를 통해 POST 타입 데이터로 서버에 잘 전달되면 서버에 저장된 메시지 알림, 페이지 '새로고침'까지 진행한다는 내용입니다.

        function get_order() {
            let name = $('#name').val()
            let count = $('#count').val()
            let address = $('#address').val()
            let phone_num = $('#phone-num').val()

            if(name.length==0){alert("이름을 입력해주세요."); $('#name').focus(); return false;}
            if(isNaN(count)){alert("수량을 선택해주세요."); $('#count').focus(); return false;}
            if(address.length==0){alert("주소를 입력해주세요."); $('#address').focus(); return false;}
            if (checkPhoneNum(phone_num)) {
                alert("전화번호를 형식에 맞게 입력해주세요.\n010-0000-0000 형식으로 입력바랍니다.");
                $('#phone-num').focus();
                return false;
            }

            $.ajax({
                type: "POST",
                url: "/order",
                data: {name_give: name, count_give: count, address_give: address, phone_num_give: phone_num},
                success: function (response) {
                    alert(response["msg"]);
                    window.location.reload();
                }
            })
        }

2) app.py 파일에는 아래와 같이 작성했습니다. html에서 ajax를 통해 딕셔너리 형태로 전달, 요청 받은 데이터를 각각 변수에 다시 저장하고, 다시 DB에 저장할 딕셔너리 형태로 정의한 후, 'webshopping'이라는 DB의 Collection에 추가합니다. 이후 주문이 완료되었다는 메시지를 다시 html을 통해 클라이언트에게 전달하는 방식입니다.

## 주문하기(Create - POST) API
@app.route('/order', methods=['POST'])
def save_order():
    name_receive = request.form['name_give']
    count_receive = request.form['count_give']
    address_receive = request.form['address_give']
    phone_num_receive = request.form['phone_num_give']
    doc = {'name':name_receive,
           'count':count_receive,
           'address':address_receive,
           'phone_num':phone_num_receive}
    db.webshopping.insert_one(doc)
    return jsonify({'msg': '주문이 완료되었습니다!'})

 

2. GET 사용법

1) 데이터 타입 GET 메소드를 사용하는 Javascript 함수는 다음과 같이 작성했습니다. 이 함수는 ajax를 통해 서버에서 받은 데이터를 재구성한 다음에, temp_html이라는 변수와 백틱(`)을 이용해서 추가할 html 위치의 구조에 맞게 통째로 틀까지 생성합니다. 그리고 마지막으로 html에 append 함수(jQuery 함수)를 통해 실제 클라이언트 페이지에 추가해서 보여줍니다.

그리고 첫 번째 행에 정의된 함수에 의해 클라이언트의 페이지에 자동으로 실행되도록 설계했습니다.

        $(document).ready(function () {
            show_order()
        })
        
        function show_order() {
            $.ajax({
                    type: "GET",
                    url: "/order",
                    data: {},
                    success: function (response) {
                        let orders = response['all_orders'];
                        for (i = 0; i < orders.length; i++) {
                            let name = orders[i]['name']
                            let count = orders[i]['count']
                            let address = orders[i]['address']
                            let phone_num = orders[i]['phone_num']

                            let temp_html = `<tr align="center" bgcolor="white">
                                                <td>${name}</td>
                                                <td>${count}</td>
                                                <td>${address}</td>
                                                <td>${phone_num}</td>
                                            </tr>`
                            $('#table-body').append(temp_html)
                        }
                    }
                })
        }

2) app.py에는 DB의 webshopping 컬렉션에 저장된 데이터를 모두 가져오되, id 값은 제외, 각 데이터는 리스트 형태로 받아옵니다. 그리고 이 데이터는 마지막 줄과 같은 형태로 html의 해당 함수와 연결된(@app.route의 주소, 메소드가 같은) 함수, ajax로 반환합니다.

## 주문 목록보기(Read - GET) API
@app.route('/order', methods=['GET'])
def view_orders():
    orders_receive = list(db.webshopping.find({},{'_id':False}))
    return jsonify({'all_orders':orders_receive})