개발 강의/스파르타코딩클럽 웹개발 종합반

스파르타코딩클럽 웹개발 종합반 - 4주차

Woonys 2021. 9. 19. 18:21
반응형

4-1 오늘 배울 것

 

4주차에서는 파이썬을 이용한 웹 프레임워크인 플라스크를 배우고 이를 활용해 웹페이지를 만드는 방법을 배운다.

 

서버: 컴퓨터에 돌아가는 하나의 프로그램! 포토샵이니 엑셀이니와 같이!

근데 웹페이지를 만들려면 서버와 클라이언트가 각각 있어야 하는데 컴퓨터가 각각 있어야 되나? 그러면 컴터 한 대 더 사야되나? 놉! 내 컴에 서버 만들고 내 컴 브라우저에서 접속한다! => 로컬 개발 환경

 

4-5주차는 로컬 개발환경에서 웹페이지 만드는 걸 배우고 => 이후에는 클라우드에다가 올려서 작업하는 걸 배운다! => 24시간 내 컴을 켜놓지 않아도 모든 사람들이 접속 가능!

 

4-3 Flask 시작하기 : 서버 만들기

 

프레임워크, 라이브러리 둘 다 남이 짜둔 걸 가져다 쓰는 것. 그러면 무슨 차이일까?

프레임워크: 쉽게 말해 남이 짜둔 뼈대를 가져다가 쓰고 거기에 내가 살을 붙이는 개념. 프레임워크를 쓰면 하나의 프레임워크 안에서 코드를 짜게 된다.

 

라이브러리: 내가 뼈대를 짜는데 거기에 필요한 살을 남한테서 빌려오는 개념. 라이브러리는 필요에 따라 여러 개를 불러와서 쓴다. 100개든 1000개든!

 

플라스크는 프레임워크! 짜둔 뼈대 안에서 내 코드를 짠다고 생각하면 된다.

 

아래 코드를 입력하면 단 몇 줄 만으로 내 서버가 만들어진 것을 확인할 수 있다!

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)

 

*port? 말 그대로 항구 개념! 인터넷 세상에서 뚫어놓은 항구 번호. 문의 번호라고 생각하면 됨.

 

4-4. Flask 시작하기 - HTML 파일 주기

 

일일이 파이썬 코드 내에서 HTML 코드 치면? 너무 불편해! => html 파일 따로 작성한 다음에 얘를 불러오는 게 훨씬 낫지!

 

플라스크: 프레임워크다 보니 정해진 폴더 구조가 있어 -> 이걸 따르자! 위에서 app.py를 만든 것도 (심지어 이름을 app.py로 지정한 것도 마찬가지) 플라스크 규칙을 따른 것!

 

Flask 서버를 만들 때는 항상 프로젝트 폴더 안에,

ㄴstatic 폴더 (이미지, css파일을 넣어둡니다)

ㄴtemplates 폴더 (html파일을 넣어둡니다)

ㄴapp.py 파일 이렇게 들어감!

 

templates 폴더 안에 index.html 파일을 하나 만들어보자.

 

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    하나만 입력해 봅시다.
</body>
</html>

 다음에는 app.py에서 templates 폴더를 불러온 뒤 그 안에 있는 index.html 파일을 불러온다

 

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

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


if __name__ == '__main__':
   app.run('0.0.0.0',port=5000,debug=True)

자, 그 다음에 localhost:5000/을 웹 브라우저를 통해 들어가면?

웹페이지에 아래와 같이 뜨는 것을 볼 수 있다.

이게 어떻게 실행된 거냐? 하면

1)웹브라우저 주소창에 localhost:5000/을 입력한다 -> 이때 중요! 이동하는 페이지의 상세 주소는 "/"이다.

2) app.py에서 플라스크가 '/'에 해당하는 루트를 불러온다.  @app.route('/')라고 입력해 둔 아래 코드를 실행시킨다.

3) home() 함수를 실행하면 templates 폴더 내 index.html 파일을 불러다가 웹브라우저에 띄운다

 

여기서 질문! 아니, 그냥 index.html 코드 작성해서 웹브라우저 창에 띄운 거랑 굳이굳이 플라스크 이용해서 localhost:5000/으로 띄운 거랑 무슨 차이가 있지? 내용은 똑같은데?

 

=> 서버를 이용해 웹페이지를 호출해서 띄웠냐 그렇지 않고 그냥 html 코드를 웹브라우저에 직통으로 올렸냐의 차이! 전자는 현재는 로컬 환경이긴 하나 조금 손을 쓰면 다른 컴퓨터에서도 동일한 html 코드를 불러올 수 있는 반면, 후자는 따로 코드를 주지 않는 이상 접근이 불가능!

 

그러니 이제는 서버를 run한 다음 플라스크를 통해서 들어가도록 하자!

 

4-5. Flask 시작하기 - 본격 API 만들기

 

API란 무엇? 은행이 고객을 받기 위해 만든 창구처럼 서버가 클라이언트 요청을 받기 위해 만든 창구라고 생각!

 

은행에서도 고객이 돈 빌리려면 신분증, 통장 들고와야 하는 규칙이 있듯 클라이언트도 서버한테 요청하기 위해서는 규칙을 만족해줘야!

API에서 규칙: POST/GET! (이외에도 여러 가지 있으나 여기서는 이 두가지만!)

 

리마인드

POST: 통상적으로 데이터 생성/변경/삭제를 요청할 때

GET: 데이터 조회(read)를 요청할 때

 

*서버에 요청할 때 이제까지 뭘 썼더라? Ajax!로 콜을 날렸지.

이제부터 할 일: (서버에서 API 만들고 - Ajax로 클라이언트 단에서 콜하고)를 반복! 

 

1) 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!'})

 

2)GET 요청 확인하는 Ajax 코드를 입력

 

GET 요청이 잘 되는지 확인해보기 위해 웹 브라우저 콘솔 창을 띄워서 아래 코드를 입력한다.

 

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

이때 url: "/test?title_give="봄날은간다"를 보면, /test까지는 웹페이지 주소를 의미하고 ? 뒤부터는 해당 정보를 뜻한다. 이는 querystring으로, GET방식에서는 url을 통해 정보를 조회한다. 여기서는 title_give라는 이름으로 "봄날은간다"를 가져오라는 요청을 한다!

 

이번에는 POST

 

3) 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!'})

 

이를 app.py에 입력 후 저장한 뒤, 콘솔 창에서 Ajax 콜을 날려본다.

 

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

위의 GET 방식에서 콜을 날릴 때와 무엇이 다른지 보자.

*url: 위에서는 /test 뒤에 ?~~~와 같이 querystring 방식으로 정보를 전달했던 반면 여기서는 url이 변경되지 않는다.

*data: GET 방식에서는 data:{}로 빈 딕셔너리가 반환되었는데 POST 방식에서는 GET 방식에서 url을 통해 전해졌던 정보가 data 키 안에 밸류로 들어간다.

 

 

4-8. POST 연습 - 리뷰 저장하기

 

본격적으로 API를 만들어보자. 유념해야 할 순서는 아래와 같다.

 

1) 클라이언트와 서버 확인하기

2) 서버부터 만들기

3) 클라이언트 만들기

4)완성 확인하기

 

이미 다 만들어뒀어서 어떻게 만들었는지 확인한다.

 

서버 쪽 창구를 확인하자. app.py을 열어본다.

## 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': '저장 완료!'})

서버의 역할은 클라이언트에서 제공한 데이터를 받아와 DB에 저장한다.

 

/review 페이지는 데이터를 주고받는 방식이 post로 되어 있다.

titie/author/review_receive 라는 변수는 각각 request.form 형식으로 데이터를 받아와서 저장하는데, 'title/author/review_give'로부터 form을 받는다. 그럼 저 _give 데이터는 어디서 받아오나?를 봐야겠지?

 

이제 클라이언트 쪽에서 어떻게 데이터를 주는지 보자. templates 폴더의 index.html을 열어본다. (클라이언트 단)

            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();
                    }
                })
            }

makereview function을 보면 title, author, bookReview 태그로부터 값을 받아와 변수에 저장한 뒤, ajax 콜을 통해 데이터를 post 형식으로 전송하는 것을 볼 수 있다.

 

4-8. GET 연습 - 리뷰 보여주기

 

이번에는 GET을 이용해 리뷰 조회하는 것을 해보자. 순서는 POST와 동일하다.

 

1) 클라이언트와 서버 확인하기

2) 서버부터 만들기
3) 클라이언트 만들기

4) 완성 확인하기

 

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

 

서버 쪽에서는 'sample_give'라는 이름으로 클라이언트 단에서 데이터를 받아온다. 그럼 클라이언트 쪽에서는?

 

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

GET 방식을 이용해 url로 데이터를 전송하고, 데이터 전송에 성공하면 "msg"를 alert하게 되어 있다. 여기서 msg 는 위의 서버 단에서 return 값에 들어 있다.

 

이제 서버 쪽부터 코드를 짜보자. 이 때, 서버가 클라이언트로부터 데이터를 받아와야 할 게 있나? 놉! 이미 데이터는 DB에 다 저장되어 있으니, 클라이언트로부터 뭔가를 받아올 필요가 없다. 그러니 위에 sample_receive 변수가 필요 없다. 그냥 데이터 바로 데이터 조회하면 되지!

 

@app.route('/review', methods=['GET'])
def read_reviews():
    # 아래 두 줄은 필요 없음 => 클라이언트로부터 데이터를 받아오는 게 아님!
    # sample_receive = request.args.get('sample_give')
    # print(sample_receive)
    reviews = list(db.bookreview.find({}, {'_id': False}))
    return jsonify({'all_reviews': reviews})

db에서 모든 리뷰를 긁어와야 하니 pymongo의 db를 이용해 db.bookreview.find()를 이용한다. (이때 bookreview: 우리가 리뷰 저장한 콜렉션 이름!)

 

그러면 클라이언트의 역할은 뭘까? all_reviews 데이터를 db로부터 끌어오면 그걸 for문으로 하나하나 펼쳐서 보여주면 땡!

 

일단 코드가 잘 작동하는지부터 본다.

 

            function showReview() {
                $.ajax({
                    type: "GET",
                    url: "/review?sample_give=샘플데이터",
                    data: {},
                    success: function (response) {
                        let reviews = response['all_reviews']
                        console.log(reviews)
                    }
                })
            }

아래를 실행하면 콘솔 창에 리뷰 데이터를 array 형태로 통으로 끌어오는 것을 볼 수 있다.

 

이제 각 속성별로 변수를 지정해서 통으로 말고 나눠서 끌어오자. title, author, review에 대해 변수를 지정한 다음, 콘솔.log를 이용해 제대로 데이터를 끌어오는지 확인하자.

 

            function showReview() {
                $.ajax({
                    type: "GET",
                    url: "/review?sample_give=샘플데이터",
                    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']

                            console.log(title, author, review)
                        }
                    }
                })
            }

잘 되는 걸 볼 수 있다.

 

이 때 주의! let title = reviews[i]['title']에서 reviews는 app.py에서 작성한 코드인 'all_reviews' 데이터를 받아다가 response 형태로 저장한 걸 받아온 변수다.

 

경로를 보면 DB (doc 형태) => 서버(db.bookreview.find{}로 데이터 불러온 뒤 json 형식으로 {'all_reviews':reviews} 데이터 보관) => 클라이언트(서버에서 보관해둔 all_reviews를 펼쳐서 보여줌)

반응형