wisePocket

[Flask] Flask framework 미니프로젝트(project bucket) 06 (Backend 버킷리스트 기록하기 기능 구현 / DB설계, DB연결, POST 요청 및 응답, insert) 본문

Python&Flask Tutorials, AWS EB/Flask_project_bucket

[Flask] Flask framework 미니프로젝트(project bucket) 06 (Backend 버킷리스트 기록하기 기능 구현 / DB설계, DB연결, POST 요청 및 응답, insert)

ohnyong 2023. 7. 15. 14:45

GET 및 POST 연결 테스트 메서드의 작동여부가 확인되었다.

클라이언트에서 입력값을 받아 DB에 저장하는 것부터 *POST 방식으로 연결하고자 한다.

클라이언트에서는 "버킷리스트 메모" 내용을 받고

이 데이터들을 DB에 넣어주는 기능을 작성해야 한다.

#### 버킷리스트 기록 진행
- input박스에 텍스트 입력
- '기록하기' 버튼으로 입력값 DB로 전송 및 저장 (insert)

1. 데이터 명세

  • DB : MongoDB
  • Collection : bucket
  • Document :
    • 버킷리스트 메모 내용 : 'bucket':'bucket_receive' / from Frontend #bucket-> formData 'bucket_give':'value'

2. DB 커넥션

우선 DB에 넣어주어야 하기 때문에 DB를 사용할 수 있도록

pymongo를 임포트

(MacOS 권한 관련 오류가 뜰 수 있으므로 cetifi를 추가로 설치, 임포트 해주었다.

관련 내용은 https://ohnyong.tistory.com/35)

# [POST-2] MongoDB사용을 위한 pymongo와 certifi 임포트
from pymongo import MongoClient
import certifi
# [POST-3] DB 커넥션 구성
ca = certifi.where()
client = MongoClient('mongodb+srv://ohnyong:test@cluster0.lu7mz8j.mongodb.net/?retryWrites=true&w=majority',tlsCAFile=ca)
db = client.dbsparta

3. 기능 구현을 위한 app.py 부분 작성 순서

이전 연결 테스트로 '기록하기' 버튼이 정상적으로 POST 요청, 응답 연결되는 것을 확인했기 때문에

우선 app.py부분부터 테스트 코드를 수정하여 원하는 기능을 구현하고자 한다.

이번엔 코드 작성 때 "무엇을 작성해야 되지?"부터 생각하고 필요한 부분을 찾는 방식을 순서대로 작성해 보았다.

큰 흐름은 "어떤 데이터가 필요한가?"라는 물음에 "이런 데이터를 받을 것이다."라는 답과 받는 방법(코드)을 도구처럼 작성하는 순서이다.

 

# [POST-0] CREATE 부분부터 코드를 작성하는 것이 확인이 가능(READ부터 하면 데이터가 없어서 테스트 어려움)

# [POST-0] CREATE 부분부터 코드를 작성하는 것(==POST)이 확인이 가능(READ부터하면 데이터가없어서 테스트 어려움)
# fetch('URL')부분, 반환값은 res로 전달.
# "localhost:5001/bucket" URL POST방식 요청에 응답
@app.route("/bucket", methods=["POST"])
def bucket_post():

# [POST-1] 프론트로부터 무엇을 받아야 하는가? -> 프론트 input으로부터 bucket을 받을 것이다.

    # [POST-1] 프론트로부터 무엇을 받아야 하는가? -> 프론트 input으로부터 (html)bucket->(js)bucket_give를 받을 것이다.
    bucket_receive = request.form['bucket_give']

# [POST-2] 클라이언트로부터 받은 데이터를 DB에 넣자 MongoDB연결을 위한 임포트부터 시작(더블체크)

# [POST-3] MongoDB사용을 위한 pymongo와 certifi 임포트

# [POST-3] MongoDB사용을 위한 pymongo와 certifi 임포트
from pymongo import MongoClient
import certifi

# [POST-4] DB 커넥션 구성

# [POST-4] DB 커넥션 구성
ca = certifi.where()
client = MongoClient('mongodb+srv://ohnyong:test@cluster0.lu7mz8j.mongodb.net/?retryWrites=true&w=majority',tlsCAFile=ca)
db = client.dbsparta

# [POST-5] DB연결이 완료되었으니 Dictionary key:value형태 데이터들을 doc=리스트 객체에 담는다.

    # [POST-5] DB연결이 완료되었으니 Dictionary key:value형태 데이터들을 doc=리스트 객체에 담는다.
    # INSERT_ONE
    # 저장 - 예시
    # doc = {'name':'bobby','age':21}
    doc = {
        'bucket' : bucket_receive
    }

# [POST-6] doc에 담았으니 DB에 insert 한다.

    # [POST-6] doc에 담았으니 DB에 insert 한다.
    db.bucket.insert_one(doc)

# [POST-7] insert가 완료되었으니 완료 메시지를 반환한다.

    # [POST-7] insert가 완료되었으니 완료 메시지를 반환한다.
    return jsonify({'msg': 'POST 연결 완료!'+'DB 저장 완료!'})

이와 같은 의식의 흐름대로 작성된 app.py는 다음과 같다. (POST맵핑 부분과 임포트, DB 커넥션 부분만)

# 라이브러리 임포트
# Flask Framework
# view페이지 렌더링을 위한 render_template 메서드
# 요청 데이터에 접근 할 수 있는 flask.request 모듈
# dictionary를 json형식의 응답 데이터를 내보낼 수 있는 jsonify 메서드
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

# [POST-3] MongoDB사용을 위한 pymongo와 certifi 임포트
from pymongo import MongoClient
import certifi
# [POST-4] DB 커넥션 구성
ca = certifi.where()
client = MongoClient('mongodb+srv://ohnyong:test@cluster0.lu7mz8j.mongodb.net/?retryWrites=true&w=majority',tlsCAFile=ca)
db = client.dbsparta


...


# [POST-0] CREATE 부분부터 코드를 작성하는 것(==POST)이 확인이 가능(READ부터하면 데이터가없어서 테스트 어려움)
# fetch('URL')부분, 반환값은 res로 전달.
# "localhost:5001/bucket" URL POST방식 요청에 응답
@app.route("/bucket", methods=["POST"])
def bucket_post():
    # [POST-1] 프론트로부터 무엇을 받아야 하는가? -> 프론트 input으로부터 (html)bucket->(js)bucket_give를 받을 것이다.
    bucket_receive = request.form['bucket_give']
    print(bucket_receive)
    # [POST-2] 클라이언트로부터 받은 데이터를 DB에 넣자 MongoDB연결을 위한 임포트부터 시작(더블체크)
    # [POST-5] DB연결이 완료되었으니 Dictionary key:value형태 데이터들을 doc=리스트 객체에 담는다.
    # INSERT_ONE
    # 저장 - 예시
    # doc = {'name':'bobby','age':21}
    doc = {
        'bucket' : bucket_receive
    }
    # [POST-6] doc에 담았으니 DB에 insert 한다.
    db.bucket.insert_one(doc)
    # [POST-7] insert가 완료되었으니 완료 메시지를 반환한다.
    return jsonify({'msg': 'POST 연결 완료!'+'DB 저장 완료!'})
    

...


# app이라는 메인 함수 
# if __name__ == "__main__" 의 의미는 메인 함수의 선언, 시작을 의미
# 이 파이썬 스크립트가 직접 실행될 때에는 main() 함수를 실행하라
if __name__ == '__main__':
    app.run('0.0.0.0', port=5001, debug=True)

4. 기능 구현을 위한 app.py 부분 수정 및 작성 DB Insert(Create) 작성

다시 처음부터 기능(데이터)의 흐름 순서에 따른 코드리뷰

  • [기능 흐름 순서 3]
    • body에 담겨서 도착한 데이터들은
    • request.form을 통해 ['key']에 해당되는 value를 가져오고 변수 "bucket_receive"라는 변수에 담는다.
# [POST-0] CREATE 부분부터 코드를 작성하는 것(==POST)이 확인이 가능(READ부터하면 데이터가없어서 테스트 어려움)
# fetch('URL')부분, 반환값은 res로 전달.
# "localhost:5001/bucket" URL POST방식 요청에 응답
@app.route("/bucket", methods=["POST"])
def bucket_post():
    # [POST-1] 프론트로부터 무엇을 받아야 하는가? -> 프론트 input으로부터 (html)bucket->(js)bucket_give를 받을 것이다.
    bucket_receive = request.form['bucket_give']
  • [기능 흐름 순서 4]
    • 다음 Dictionary 형식의 리스트 데이터를 갖는 doc이라는 객체 생성
    • 위 변수들에 request.form을 통해 저장한 데이터는 아래 각 value로 들어가고 doc객체 내에 담긴다.
      • 'bucket' : bucket_receive,
    •  1개 key:value 묶음을 가진 객체 insert_one()에 의해 MongoDB로 전송되면서 1개의 document가 되며 내용물인 각 Dictionary는 field:value 형태로 변환되고 bucket이라는 collection 추가 됨

DB 저장 이후

  • [기능 흐름 순서 5]
    • 이후, 확인용으로 {'msg' : 'POST 연결 완료! + DB 저장(insert) 완료!'} 라 하드코딩된 key, value가
    • jsonify()에 의해 json 형식의 데이터로 변환(주어진 값과 대응하는 JSON 문자열) 후 반환하고 js로 이동
    # [POST-6] doc에 담았으니 DB에 insert 한다.
    db.bucket.insert_one(doc)
    # [POST-7] insert가 완료되었으니 완료 메시지를 반환한다.
    return jsonify({'msg': 'POST 연결 완료!'+'DB 저장 완료!'})

5. 기능 구현을 위한 script.js 부분 수정 및 작성

버킷리스트 기록 하기 기능은 View 페이지에서 '기록하기' button의 onclick 이벤트로부터 시작되도록 설계되었다.

이전 테스트를 통해 script.js에서 POST 요청을 시작하고 최종 응답을 받는 것까지 정상적으로 작동되는 것을 확인했다.

이벤트와 연결된 함수인 save_bucket() 부분을 작성(수정)한다.

 

View 페이지인 index.html에서 id가 bucket로부터 입력 및 선택되는 value를 받아와야 한다.

  • [기능 흐름 순서 1]
    • (값들을 입력하고)
    • "기록하기" button의 onclick 이벤트로 JavaScript save_bucket() 함수 호출
    • JavaScript save_bucket()라는 함수 실행
    • 값이 입력된 input 태그들로부터 value를 가져와야 한다
    • . val()을 통해 각 id에 해당되는 부분의 value를 얻어 bucket 변수에 저장
// [Create]
function save_bucket() {
    // index.html로부터 값 가져오기
    let bucket = $('#bucket').val()
  • [기능 흐름 순서 2]
  • formData라는 객체를 생성
  • {'bucket_give':bucket}, {...}, {...) Dictionary 형식 데이터를. append()를 통해  formData 담기
  • save_bucket() 내부 fetch()를 통해 '/bucket' URL에 대한 POST 방식 요청 (+ 위 formData 객체를 body로 추가하여 요청함)
  • app.py로 이동

DB저장 이후(fetch() 이후. then() 절로 jsonify 변환 객체가 반환된 이후)

  • [기능 흐름 순서 6]
  • 반환 데이터(여기서는 완료 메시지)는 첫 번째 then() 절의 res 인자값으로 들어감
  • 첫 번째 then()으로 들어간 res *response.json()에 의해 Promise 객체로 변환
  • 해당 객체 데이터 data라는 변수에 담기고
  • alert를 통해 key msg의 value인 'POST 연결 완료! + DB 저장 완료!'가 출력됨. 
    // formData 객체를 생성하고
    let formData = new FormData();
    // append()통해 {key,value}를 객체에 담는다
    formData.append("bucket_give", bucket);

    // POST 요청에 위 formData를 body에 담아 요청한다.
    fetch('/bucket', { method: "POST", body: formData, }).then((response) => response.json()).then((data) => {
        alert(data["msg"]);
        // 브라우저 새로고침 추가
        window.location.reload();
    });
}

5. 테스트

  • Flask 서버가 실행 중인 상태
  • 브라우저에서 localhost:5001 URL로 접속
  • 테스트 인풋 값 입력
    • 버킷리스트 내용 :
      • "꾸준히 공부하는 개발자가 되고 싶어요."
      • "운동을 규칙적으로 해서 몸관리 하기."
      • "웹서비스 스스로 기획, 설계, 개발 완성해 보기"
      • "유럽 배낭 여행"
  • "기록하기" 버튼 클릭
  • 'POST 연결 완료! + DB 저장 완료!' 알림 창
  • MongoDB내 bucket라는 collection 테스트 데이터가 추가(insert) 됨


 

POST,GET?route()?

HTTP(웹 어플리케이션에서 사용하는 프로토콜)는 URL 접근에 대해 몇가지 다른 방식을 제공한다. 기본적으로 
GET 방식으로 제공되지만, route() 데코레이터에 methods 인자를 제공하면 다른 방식으로 변경할 수 있다. 

GET
브라우저가 어떤 페이지에 저장된 정보를 단지 얻기 위해 서버에 요청하고 서버는 그 정보를 보낸다. 가장 일반적인 메소드다.
POST
브라우저는 서버에게 새로운 정보를 *전송*하도록 특정 URL에 요청하고 그 정보가 오직 한번 저장되는것을 보장하도록 한다. 이것이 보통 HTML폼을 통해서 서버에 데이터 전송하는 방식이다.

https://flask-docs-kr.readthedocs.io/ko/latest/quickstart.html#http

해당 프로젝트는 아래 깃을 통해 업데이트되고 있습니다.

https://github.com/yzpocket/Flask_project_bucket

 

GitHub - yzpocket/Flask_project_bucket

Contribute to yzpocket/Flask_project_bucket development by creating an account on GitHub.

github.com