4주차 수업내용

이수형·2021년 10월 4일
0

HTML과 mongoDB까지 연동해서 서버를 만들기!
같은 컴퓨터에다 서버도 만들고, 요청도 한다.
즉, 클라이언트 = 서버가 되는 것.
이것을 바로 "로컬 개발환경"이라고 한다!

Flask시작하기 - 서버만들기

패키지 설치 화면 진입하기 File → setting → Python interpreter
python interpreter 화면에서 + 버튼을 누르면 창이 뜹니다!
flask 로 검색한 후, Install package 클릭

  • Flask 프레임워크: 서버를 구동시켜주는 편한 코드 모음. 서버를 구동하려면 필요한 복잡한 일들을 쉽게 가져다 쓸 수 있습니다.
    프레임워크를 쓰지 않으면 태양초를 빻아서 고추장을 만드는 격!
    프레임워크는 3분 요리/소스 세트라고 생각하면 된다!
    파일 이름은 아무렇게나 해도 상관없지만,
    통상적으로 flask 서버를 돌리는 파일은 app.py라고 이름 짓습니다!

<flask 시작 코드>
from flask import Flask
app = Flask(name)

@app.route('/')
def home():
return 'This is Home!'

if name == 'main':
app.run('0.0.0.0',port=5000,debug=True)

오른쪽 클릭 → 'Run app'을 클릭하고, 터미널에 아래와 같은 메시지가 뜨면 실행 성공!

크롬에서 http://localhost:5000/ 으로 접속해요.

Flask 기초: URL 나눠보기
@app.route('/) 부분을 수정해서 URL을 나눌 수 있습니다!
url 별로 함수명이 같거나, route('/')내의 주소가 같으면 안됩니다.

from flask import Flask
app = Flask(name)

@app.route('/')
def home():
return 'This is Home!'

@app.route('/mypage')
def mypage():
return 'This is My Page!'

if name == 'main':
app.run('0.0.0.0',port=5000,debug=True)

Flask시작하기 - HTML파일 주기
Flask 기초: 기본 폴더구조 - 항상 이렇게 세팅하고 시작!
프로젝트 폴더 안에,
ㄴstatic 폴더 (이미지, css파일을 넣어둡니다)
ㄴtemplates 폴더 (html파일을 넣어둡니다)
ㄴapp.py 파일
이렇게 세 개를 만들어두고 시작하세요.
꼭 참고!! venv는 실제로는 보이지만, 안보인다~라고 생각하기.

Flask 기초: HTML 파일 불러오기
templates 폴더의 역할을 알아보겠습니다.
HTML 파일을 담아두고, 불러오는 역할을 하죠!
간단한 index.html 파일을 templates 안에 만들기

html 파일 불러오기
flask 내장함수 render_template를 이용합니다. 바로 이게 프레임워크의 위력!

from flask import Flask, render_template
app = Flask(name)

##URL 별로 함수명이 같거나,
##route('/') 등의 주소가 같으면 안됩니다.

@app.route('/')
def home():
return render_template('index.html')

if name == 'main':
app.run('0.0.0.0', port=5000, debug=True)

**Flask시작하기 - 본격 API 만들기

들어가기 전에: GET, POST 요청타입 - 리마인드본격 API 만들기**
리마인드!
은행의 창구가 API와 같다는 것을 기억하시나요?
같은 예금 창구에서도 개인 고객이냐 기업 고객이냐에 따라 처리하는 것이 다른 것처럼,

클라이언트가 요청 할 때에도, "방식"이 존재합니다.
HTTP 라는 통신 규약을 따른다는 거 잊지 않으셨죠? 클라이언트는 요청할 때 HTTP request method(요청 메소드)를 통해, 어떤 요청 종류인지 응답하는 서버 쪽에 정보를 알려주는 거에요.

GET, POST 방식
여러 방식(링크)이 존재하지만 우리는 가장 많이 쓰이는 GET, POST 방식.

  • GET → 통상적으로! 데이터 조회(Read)를 요청할 때
    예) 영화 목록 조회
    → 데이터 전달 : URL 뒤에 물음표를 붙여 key=value로 전달
    → 예: google.com?q=북극곰

  • POST → 통상적으로! 데이터 생성(Create), 변경(Update), 삭제(Delete) 요청 할 때
    예) 회원가입, 회원탈퇴, 비밀번호 수정
    → 데이터 전달 : 바로 보이지 않는 HTML body에 key:value 형태로 전달

           

GET, POST 요청에서 클라이언트의 데이터를 받는 방법
예를 들어, 클라이언트에서 서버에 title_give란 키 값으로 데이터를 들고왔다
(주민등록번호 라는 키 값으로 850120- .. 을 가져온 것과 같은 의미)

받은 값을 개발자가 볼 수 있게 print 로 찍어볼 수 있게 GET 요청 API코드
@app.route('/test', methods=['GET'])
def test_get():
title_receive = request.args.get('title_give')
print(title_receive)
return jsonify({'result':'success', 'msg': '이 요청은 GET!'})

GET 요청 확인 Ajax코드
$.ajax({
type: "GET",
url: "/test?title_give=봄날은간다",
data: {},
success: function(response){
console.log(response)
}
})

POST 요청 API코드
@app.route('/test', methods=['POST'])
def test_post():
title_receive = request.form['title_give']
print(title_receive)
return jsonify({'result':'success', 'msg': '이 요청은 POST!'})

POST 요청 확인 Ajax코드
$.ajax({
type: "POST",
url: "/test",
data: { title_give:'봄날은간다' },
success: function(response){
console.log(response)
}
})

[모두의책리뷰] - POST 연습(리뷰 저장)
API 만들고 사용하기 - 제목, 저자, 리뷰 정보 저장하기(Create → POST)
1. 클라이언트와 서버 확인하기

  • 여기서는 적혀 있는 쌍으로 되어있는 서버-클라이언트 코드를 확인하고 갈게요.
  • 분홍 형광펜 부분이 서로 어떻게 매칭되는지 확인해보세요!

만들어져 있는 API 정보
1. 요청 정보 : 요청 URL= /review , 요청 방식 = POST
2. 서버가 제공할 기능 : 클라이언트에게 정해진 메시지를 보냄
3. 응답 데이터 : (JSON 형식) 'result'= 'success', 'msg'= '리뷰가 성공적으로 작성되었습니다.'

서버 코드 - app.py
##API 역할을 하는 부분
@app.route('/review', methods=['POST'])
def write_review():

# 1. 클라이언트가 준 title, author, review 가져오기.
# 2. DB에 정보 삽입하기
# 3. 성공 여부 & 성공 메시지 반환하기
return jsonify({'result': 'success', 'msg': '리뷰가 성공적으로 작성되었습니다.'})

클라이언트 코드 - index.html
function makeReview() {
// 1. 제목, 저자, 리뷰 내용을 가져옵니다.
// 2. 제목, 저자, 리뷰 중 하나라도 입력하지 않았을 경우 alert를 띄웁니다.
// 3. POST /review 에 저장을 요청합니다.
$.ajax({
type: "POST",
url: "/review",
data: { },
success: function (response) {
if (response["result"] == "success") {
alert(response["msg"] );
window.location.reload();
}
}
})
}

동작 테스트
'리뷰 시작하기' 버튼을 눌렀을 때, '리뷰가 성공적으로 작성되었습니다.' 라는 내용의 alert창이 뜨면 클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.

서버부터 만들기
API 는 약속이라고 했습니다. API를 먼저 만들기!
리뷰를 작성하기 위해 필요한 정보는 다음 세 가지 입니다.

  • 제목(title)
  • 저자(author)
  • 리뷰(review)

따라서 API 기능은 다음 세 단계로 구성되어야 합니다.
1. 클라이언트가 준 title, author, review 가져오기.
2. DB에 정보 삽입하기
3. 성공 여부 & 성공 메시지 반환하기

정리하면, 만들 API 정보는 아래와 같습니다.
A. 요청 정보

  • 요청 URL= /review , 요청 방식 = POST
  • 요청 데이터 : 제목(title), 저자(author), 리뷰(review)

B. 서버가 제공할 기능 : 클라이언트에게 보낸 요청 데이터를 데이터베이스에 생성(Create)하고, 저장이 성공했다고 응답 데이터를 보냄

C. 응답 데이터 : (JSON 형식) 'msg'= '리뷰가 성공적으로 작성되었습니다.'

@app.route('/review', methods=['POST'])
def write_review():

# title_receive로 클라이언트가 준 title 가져오기
title_receive = request.form['title_give']
# author_receive로 클라이언트가 준 author 가져오기
author_receive = request.form['author_give']
# review_receive로 클라이언트가 준 review 가져오기
review_receive = request.form['review_give']

# DB에 삽입할 review 만들기
doc = {
    'title': title_receive,
    'author': author_receive,
    'review': review_receive
}
# reviews에 review 저장하기
db.bookreview.insert_one(doc)
# 성공 여부 & 성공 메시지 반환
return jsonify({'msg': '리뷰가 성공적으로 작성되었습니다.'})



##클라이언트 만들기##
API 는 약속이라고 했습니다. API를 사용할 클라이언트를 만들어보죠!

리뷰를 작성하기 위해 필요한 정보는 다음 세 가지 입니다.

  • 제목(title)
  • 저자(author)
  • 리뷰(review)

따라서 클라이언트 코드는 다음 세 단계로 구성되어야 합니다.
1. input에서 title, author, review 가져오기
2. 입력값이 하나라도 없을 때 alert 띄우기.
3. Ajax로 서버에 저장 요청하고, 화면 다시 로딩하기

사용할 API 정보

A. 요청 정보

  • 요청 URL= /review , 요청 방식 = POST
  • 요청 데이터 : 제목(title), 저자(author), 리뷰(review)

B. 서버가 제공할 기능 : 클라이언트에게 보낸 요청 데이터를 데이터베이스에 생성(Create)하고, 저장이 성공했다고 응답 데이터를 보냄

C. 응답 데이터 : (JSON 형식) 'result'= 'success', 'msg'= '리뷰가 성공적으로 작성되었습니다.'

function makeReview() {
// 화면에 입력어 있는 제목, 저자, 리뷰 내용을 가져옵니다.
let title = $("#title").val();
let author = $("#author").val();
let review = $("#bookReview").val();

// POST /review 에 저장(Create)을 요청합니다.
$.ajax({
    type: "POST",
    url: "/review",
    data: { title_give: title, author_give: author, review_give: review },
    success: function (response) {
        alert(response["msg"]);
        window.location.reload();
    }
})

}

완성 확인하기

동작 테스트
제목, 저자, 리뷰를 작성하고 '리뷰 작성하기' 버튼을 눌렀을 때,
'리뷰가 성공적으로 작성되었습니다.'라는 alert가 뜨는지 확인합니다.

[모두의책리뷰] - GET 연습(리뷰 보여주기)
API 만들고 사용하기 - 저장된 리뷰를 화면에 보여주기(Read → GET)

    1. 클라이언트와 서버 확인하기
    • 여기서는 미리 적혀 있는 쌍으로 되어있는 서버-클라이언트 코드를 확인하고 갈게요.

    • 분홍 형광펜 부분이 서로 어떻게 매칭되는지 확인해보세요!

      만들어져 있는 API 정보

      1. 요청 정보 : 요청 URL= /review , 요청 방식 = GET
      2. 서버가 제공할 기능 : 클라이언트에게 정해진 메시지를 보냄
      3. 응답 데이터 : (JSON 형식) {'msg': '이 요청은 GET!'}

      [서버 코드 - app.py]

      @app.route('/review', methods=['GET'])
      def read_reviews():
          sample_receive = request.args.get('sample_give')
          print(sample_receive)
          return jsonify({'msg': '이 요청은 GET!'})

      [클라이언트 코드 - index.html]

      function showReview() {
      		// 서버의 데이터를 받아오기
      		$.ajax({
              type: "GET",
              url: "/review?sample_give=샘플데이터",
              data: {},
              success: function (response) {
                  alert(response["msg"]);
              }
          })
      }

      동작 테스트
      화면을 새로고침 했을 때, '리뷰를 받아왔습니다.' 라는 내용의 alert창이 뜨면
      클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.

    1. 서버부터 만들기

      API 는 약속이라고 했습니다. API를 먼저 만들어보죠!

      API 기능은 다음 단계로 구성되어야 합니다.

    2. DB에서 리뷰 정보 모두 가져오기

    3. 성공 여부 & 리뷰 목록 반환하기

      정리하면, 만들 API 정보는 아래와 같습니다.

      A. 요청 정보

    • 요청 URL= /review , 요청 방식 = GET

    • 요청 데이터 : 없음

      B. 서버가 제공할 기능 : 데이터베이스에 리뷰 정보를 조회(Read)하고, 성공 메시지와 리뷰 정보를 응답 데이터를 보냄

      C. 응답 데이터 : (JSON 형식) 'all_reviews'= 리뷰리스트

      @app.route('/review', methods=['GET'])
      def read_reviews():
          # 1. DB에서 리뷰 정보 모두 가져오기
          reviews = list(db.bookreview.find({}, {'_id': False}))
          # 2. 성공 여부 & 리뷰 목록 반환하기
          return jsonify({'all_reviews': reviews})
    1. 클라이언트 만들기

      API 는 약속이라고 했습니다. API를 사용할 클라이언트를 만들어보죠!

      리뷰를 작성하기 위해 필요한 정보는 다음 세 가지 입니다.

    • 제목(title)

    • 저자(author)

    • 리뷰(review)

      따라서 클라이언트 코드는 다음 세 단계로 구성되어야 합니다.

    1. 리뷰 목록을 서버에 요청하기

    2. 요청 성공 여부 확인하기

    3. 요청 성공했을 때 리뷰를 올바르게 화면에 나타내기

      사용할 API 정보는 아래와 같습니다.

      A. 요청 정보

    • 요청 URL= /review , 요청 방식 = GET

    • 요청 데이터 : 없음

      B. 서버가 제공할 기능 : 데이터베이스에 리뷰 정보를 조회(Read)하고, 성공 메시지와 리뷰 정보를 응답 데이터를 보냄

      C. 응답 데이터 : (JSON 형식) 'all_reviews'= 리뷰리스트

      function showReview() {
                      $.ajax({
                          type: "GET",
                          url: "/review",
                          data: {},
                          success: function (response) {
                              let reviews = response['all_reviews']
                              for (let i = 0; i < reviews.length; i++) {
                                  let title = reviews[i]['title']
                                  let author = reviews[i]['author']
                                  let review = reviews[i]['review']
      
                                  let temp_html = `<tr>
                                                      <td>${title}</td>
                                                      <td>${author}</td>
                                                      <td>${review}</td>
                                                  </tr>`
                                  $('#reviews-box').append(temp_html)
                              }
                          }
                      })
                  }
    1. 완성 확인하기

      동작 테스트
      화면을 새로고침 했을 때, DB에 저장된 리뷰가 화면에 올바르게 나타나는지 확인합니다.

전체 완성 코드

프로젝트 API 정보는 아래와 같습니다.

[리뷰 저장하기(Create)]
A. 요청 정보

  • 요청 URL= /review , 요청 방식 = POST
  • 요청 데이터 : 제목(title), 저자(author), 리뷰(review)

B. 서버가 제공할 기능 : 클라이언트에게 보낸 요청 데이터를 데이터베이스에 생성(Create)하고, 저장이 성공했다고 응답 데이터를 보냄

C. 응답 데이터 : (JSON 형식) 'result'= 'success', 'msg'= '리뷰가 성공적으로 작성되었습니다.'

[리뷰 보여주기(Read)]
A. 요청 정보

  • 요청 URL= /review , 요청 방식 = GET
  • 요청 데이터 : 없음

B. 서버가 제공할 기능 : 데이터베이스에 리뷰 정보를 조회(Read)하고, 성공 메시지와 리뷰 정보를 응답 데이터를 보냄

C. 응답 데이터 : (JSON 형식) 'result'= 'success', 'reviews'= 리뷰리스트

  • [💻코드 - 서버 app.py ]
    from flask import Flask, render_template, jsonify, request
    app = Flask(__name__)
    
    from pymongo import MongoClient
    client = MongoClient('localhost', 27017)
    db = client.dbsparta
    
    ## HTML을 주는 부분
    @app.route('/')
    def home():
        return render_template('index.html')
    
    ## API 역할을 하는 부분
    @app.route('/review', methods=['POST'])
    def write_review():
        title_receive = request.form['title_give']
        author_receive = request.form['author_give']
        review_receive = request.form['review_give']
    
        doc = {
            'title':title_receive,
            'author':author_receive,
            'review':review_receive
        }
    
        db.bookreview.insert_one(doc)
    
        return jsonify({'msg': '저장 완료!'})
    
    @app.route('/review', methods=['GET'])
    def read_reviews():
        reviews = list(db.bookreview.find({}, {'_id': False}))
        return jsonify({'all_reviews': reviews})
    
    if __name__ == '__main__':
        app.run('0.0.0.0', port=5000, debug=True)
    • 15) 전체 완성 코드

      프로젝트 API 정보는 아래와 같습니다.

      [리뷰 저장하기(Create)]
      A. 요청 정보

    • 요청 URL= /review , 요청 방식 = POST

    • 요청 데이터 : 제목(title), 저자(author), 리뷰(review)

      B. 서버가 제공할 기능 : 클라이언트에게 보낸 요청 데이터를 데이터베이스에 생성(Create)하고, 저장이 성공했다고 응답 데이터를 보냄

      C. 응답 데이터 : (JSON 형식) 'result'= 'success', 'msg'= '리뷰가 성공적으로 작성되었습니다.'

      [리뷰 보여주기(Read)]
      A. 요청 정보

    • 요청 URL= /review , 요청 방식 = GET

    • 요청 데이터 : 없음

      B. 서버가 제공할 기능 : 데이터베이스에 리뷰 정보를 조회(Read)하고, 성공 메시지와 리뷰 정보를 응답 데이터를 보냄

      C. 응답 데이터 : (JSON 형식) 'result'= 'success', 'reviews'= 리뷰리스트

    • [💻코드 - 서버 app.py ]

      from flask import Flask, render_template, jsonify, request
      app = Flask(__name__)
      
      from pymongo import MongoClient
      client = MongoClient('localhost', 27017)
      db = client.dbsparta
      
      ## HTML을 주는 부분
      @app.route('/')
      def home():
          return render_template('index.html')
      
      ## API 역할을 하는 부분
      @app.route('/review', methods=['POST'])
      def write_review():
          title_receive = request.form['title_give']
          author_receive = request.form['author_give']
          review_receive = request.form['review_give']
      
          doc = {
              'title':title_receive,
              'author':author_receive,
              'review':review_receive
          }
      
          db.bookreview.insert_one(doc)
      
          return jsonify({'msg': '저장 완료!'})
      
      @app.route('/review', methods=['GET'])
      def read_reviews():
          reviews = list(db.bookreview.find({}, {'_id': False}))
          return jsonify({'all_reviews': reviews})
      
      if __name__ == '__main__':
          app.run('0.0.0.0', port=5000, debug=True)
    • [💻코드 - 클라이언트 index.html ]

      <!DOCTYPE html>
      <html lang="ko">
      
          <head>
              <!-- Webpage Title -->
              <title>모두의 책리뷰 | 스파르타코딩클럽</title>
      
              <!-- Required meta tags -->
              <meta charset="utf-8">
              <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      
              <!-- Bootstrap CSS -->
              <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
                    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
                    crossorigin="anonymous">
      
              <!-- JS -->
              <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
                      integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
                      crossorigin="anonymous"></script>
      
              <!-- 구글폰트 -->
              <link href="https://fonts.googleapis.com/css?family=Do+Hyeon&display=swap" rel="stylesheet">
      
              <script type="text/javascript">
      
                  $(document).ready(function () {
                      showReview();
                  });
      
                  function makeReview() {
                      let title = $('#title').val()
                      let author = $('#author').val()
                      let review = $('#bookReview').val()
      
                      $.ajax({
                          type: "POST",
                          url: "/review",
                          data: {title_give:title,author_give:author,review_give:review},
                          success: function (response) {
                              alert(response["msg"]);
                              window.location.reload();
                          }
                      })
                  }
      
                  function showReview() {
                      $.ajax({
                          type: "GET",
                          url: "/review",
                          data: {},
                          success: function (response) {
                              let reviews = response['all_reviews']
                              for (let i = 0; i < reviews.length; i++) {
                                  let title = reviews[i]['title']
                                  let author = reviews[i]['author']
                                  let review = reviews[i]['review']
      
                                  let temp_html = `<tr>
                                                      <td>${title}</td>
                                                      <td>${author}</td>
                                                      <td>${review}</td>
                                                  </tr>`
                                  $('#reviews-box').append(temp_html)
                              }
                          }
                      })
                  }
      
              </script>
      
              <style type="text/css">
                  * {
                      font-family: "Do Hyeon", sans-serif;
                  }
      
                  h1,
                  h5 {
                      display: inline;
                  }
      
                  .info {
                      margin-top: 20px;
                      margin-bottom: 20px;
                  }
      
                  .review {
                      text-align: center;
                  }
      
                  .reviews {
                      margin-top: 100px;
                  }
              </style>
          </head>
      
          <body>
              <div class="container" style="max-width: 600px;">
                  <img src="https://image.freepik.com/free-vector/large-bookcase-with-books-library-book-shelf-interior_92863-357.jpg"
                       class="img-fluid" alt="Responsive image">
                  <div class="info">
                      <h1>읽은 책에 대해 말씀해주세요.</h1>
                      <p>다른 사람을 위해 리뷰를 남겨주세요! 다 같이 좋은 책을 읽는다면 다 함께 행복해질 수 있지 않을까요?</p>
                      <div class="input-group mb-3">
                          <div class="input-group-prepend">
                              <span class="input-group-text">제목</span>
                          </div>
                          <input type="text" class="form-control" id="title">
                      </div>
                      <div class="input-group mb-3">
                          <div class="input-group-prepend">
                              <span class="input-group-text">저자</span>
                          </div>
                          <input type="text" class="form-control" id="author">
                      </div>
                      <div class="input-group mb-3">
                          <div class="input-group-prepend">
                              <span class="input-group-text">리뷰</span>
                          </div>
                          <textarea class="form-control" id="bookReview"
                                    cols="30"
                                    rows="5" placeholder="140자까지 입력할 수 있습니다."></textarea>
                      </div>
                      <div class="review">
                          <button onclick="makeReview()" type="button" class="btn btn-primary">리뷰 작성하기</button>
                      </div>
                  </div>
                  <div class="reviews">
                      <table class="table">
                          <thead>
                          <tr>
                              <th scope="col">제목</th>
                              <th scope="col">저자</th>
                              <th scope="col">리뷰</th>
                          </tr>
                          </thead>
                          <tbody id="reviews-box">
                          </tbody>
                      </table>
                  </div>
              </div>
          </body>
      
      </html>
profile
자유롭게 즐거운 인생을 살자.

0개의 댓글

관련 채용 정보