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

김영민·2021년 9월 14일

Project1. [모두의책리뷰]

POST연습 (리뷰 저장하기)

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

만들어져 있는 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 정보

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창이 뜨면
클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.

서버부터 만들기

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

API 기능은 다음 단계로 구성되어야 합니다.
1. DB에서 리뷰 정보 모두 가져오기
2. 성공 여부 & 리뷰 목록 반환하기

정리하면, 만들 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})

클라이언트 만들기

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

완성 확인하기

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

Project2. [나홀로메모장]

프로젝트 설계 - 만들 API 설계

포스팅API - 카드 생성 (Create)

A. 요청 정보

  • 요청 URL= /memo , 요청 방식 = POST
  • 요청 데이터 : URL(url_give), 코멘트(comment_give)

B. 서버가 제공할 기능

  • URL의 meta태그 정보를 바탕으로 제목, 설명, 이미지URL 스크래핑
  • (제목, 설명, URL, 이미지URL, 코멘트) 정보를 모두 DB에 저장

C. 응답 데이터

  • API가 정상적으로 작동하는지 클라이언트에게 알려주기 위해서 성공 메시지 보내기
  • (JSON 형식) 'result'= 'success'

리스팅API - 저장된 카드 보여주기 (Read)

A. 요청 정보

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

B. 서버가 제공할 기능

  • DB에 저장돼있는 모든 (제목, 설명, URL, 이미지URL, 코멘트) 정보를 가져오기

C. 응답 데이터

  • 아티클(기사)들의 정보(제목, 설명, URL, 이미지URL, 코멘트) → 카드 만들어서 붙이기
  • (JSON 형식) 'articles': 아티클 정보

프로젝트 준비 - URL에서 페이지 정보 가져오기 (meta태그 스크래핑)

meta 태그 스크래핑 하기

  • 크롤링 기본코드
import requests
from bs4 import BeautifulSoup

url = 'https://movie.naver.com/movie/bi/mi/basic.nhn?code=171539'

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get(url,headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')

# 여기에 코딩을 해서 meta tag를 먼저 가져와보겠습니다.
  • select_one을 이용해 meta tag를 가져오기
og_image = soup.select_one('meta[property="og:image"]')
og_title = soup.select_one('meta[property="og:title"]')
og_description = soup.select_one('meta[property="og:description"]')

print(og_image)
print(og_title)
print(og_description)
  • 가져온 meta tag의 content를 가져오기
url_image = og_image['content']
url_title = og_title['content']
url_description = og_description['content']

print(url_image)
print(url_title)
print(url_description)

POST연습 (메모하기)

API 만들고 사용하기 - 포스팅API (Create → POST)

우리가 만들 API 두 가지

1) 포스팅API - 카드 생성 (Create) : 클라이언트에서 받은 url, comment를 이용해서 페이지 정보를 찾고 저장하기
2) 리스팅API - 저장된 카드 보여주기 (Read)

클라이언트와 서버 연결 확인하기

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

[서버 코드 - app.py]

@app.route('/memo', methods=['POST'])
def post_articles():
		sample_receive = request.form['sample_give']
		print(sample_receive)
    return jsonify({'msg': 'POST 연결되었습니다!'})

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

function postArticle() {
  $.ajax({
    type: "POST",
    url: "/memo",
    data: {sample_give:'샘플데이터'},
    success: function (response) { // 성공하면
      alert(response['msg']);
    }
  })
}

<button type="button" class="btn btn-primary" onclick="postArticle()">기사저장</button>

동작 테스트
'기사저장' 버튼을 클릭했을 때, 'POST 연결되었습니다!' alert창이 뜨면
클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.

서버부터 만들기

API 는 약속이라고 했습니다. 위에 미리 설계해 둔 API 정보를 보고 만들어보죠!

메모를 작성하기 위해 서버가 전달받아야하는 정보는 다음 두 가지 입니다.

  • URL(url_give)
  • 코멘트(comment_give)

그리고 URL를 meta tag를 스크래핑해서 아래 데이터를 저장(Create)합니다.

  • URL(url)
  • 제목(title)
  • 설명(desc)
  • 이미지URL(image)
  • 코멘트(comment)

따라서 서버 로직은 다음 단계로 구성되어야 합니다.
1. 클라이언트로부터 데이터를 받기.
2. meta tag를 스크래핑하기
3. mongoDB에 데이터를 넣기

@app.route('/memo', methods=['POST'])
def saving():
    url_receive = request.form['url_give']
    comment_receive = request.form['comment_give']

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(url_receive, headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')

    title = soup.select_one('meta[property="og:title"]')['content']
    image = soup.select_one('meta[property="og:image"]')['content']
    desc = soup.select_one('meta[property="og:description"]')['content']

    doc = {
        'title':title,
        'image':image,
        'desc':desc,
        'url':url_receive,
        'comment':comment_receive
    }

    db.articles.insert_one(doc)

    return jsonify({'msg':'저장이 완료되었습니다!'})

클라이언트 만들기

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

메모를 작성하기 위해 서버에게 주어야하는 정보는 다음 두 가지 입니다.

  • URL (url_give) : meta tag를 가져올 url
  • comment (comment_give) : 유저가 입력한 코멘트

따라서 클라이언트 로직은 다음 단계로 구성되어야 합니다.
1. 유저가 입력한 데이터를 #post-url과 #post-comment에서 가져오기
2. /memo에 POST 방식으로 메모 생성 요청하기
3. 성공 시 페이지 새로고침하기

function postArticle() {
      let url = $('#post-url').val()
      let comment = $('#post-comment').val()

      $.ajax({
          type: "POST",
          url: "/memo",
          data: {url_give:url, comment_give:comment},
          success: function (response) { // 성공하면
              alert(response["msg"]);
              window.location.reload()
          }
      })
  }

완성 확인하기

동작 테스트
https://movie.naver.com/movie/bi/mi/basic.nhn?code=171539 ← 이 URL을 입력하고 기사저장을 눌렀을 때, '포스팅 성공!' alert창이 뜨는지 확인합니다.
(우리는 스크래핑을 사용해 정보를 저장하고 있으니까, meta tag 가 있는 사이트만 저장이 제대로 되겠죠?)


참고!
지금은 카드가 보이지 않습니다. 아직 카드를 보여주는 리스팅 API 를 만들지 않았기 때문이죠.

GET연습 (보여주기)

API 만들고 사용하기 - 리스팅 API (Read → GET)

우리가 만들 API 두 가지

1) 포스팅API - 카드 생성 (Create) : 클라이언트에서 받은 url, comment를 이용해서 페이지 정보를 찾고 저장하기
2) 리스팅API - 저장된 카드 보여주기 (Read)

클라이언트와 서버 연결 확인하기

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

[서버 코드 - app.py]

@app.route('/memo', methods=['GET'])
def read_articles():
    # 1. 모든 document 찾기 & _id 값은 출력에서 제외하기
    # 2. articles라는 키 값으로 영화정보 내려주기
    return jsonify({'result':'success', 'msg':'GET 연결되었습니다!'})

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

function showArticles() {
  $.ajax({
    type: "GET",
    url: "/memo",
    data: {},
    success: function (response) {
      if (response["result"] == "success") {
        alert(response["msg"]);
      }
    }
  })
}

동작 테스트
새로고침했을 때, 'GET 연결되었습니다!' alert창이 뜨면
클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.

서버부터 만들기

API 는 약속이라고 했습니다. 위에 미리 설계해 둔 API 정보를 보고 만들어보죠!

메모를 보여주기 위해 서버가 추가로 전달받아야하는 정보는 없습니다. 조건없이 모든 메모를 보여줄 꺼니까요!

따라서 서버 로직은 다음 단계로 구성되어야 합니다.
1. mongoDB에서 _id 값을 제외한 모든 데이터 조회해오기 (Read)
2. articles라는 키 값으로 articles 정보 보내주기

@app.route('/memo', methods=['GET'])
def listing():
    articles = list(db.articles.find({}, {'_id': False}))
    return jsonify({'all_articles':articles})

클라이언트 만들기

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

메모를 작성하기 위해 서버에게 주어야하는 정보는 없습니다. 조건없이 모든 메모를 가져오기 때문입니다.

따라서 클라이언트 로직은 다음 단계로 구성되어야 합니다.
1. /memo에 GET 방식으로 메모 정보 요청하고 articles로 메모 정보 받기
2. , makeCard 함수를 이용해서 카드 HTML 붙이기
(→ 2주차 Ajax 연습과 같습니다!)

function showArticles() {
    $.ajax({
        type: "GET",
        url: "/memo",
        data: {},
        success: function (response) {
            let articles = response['all_articles']
            for (let i = 0; i < articles.length; i++) {
                let title = articles[i]['title']
                let image = articles[i]['image']
                let url = articles[i]['url']
                let desc = articles[i]['desc']
                let comment = articles[i]['comment']

                let temp_html = `<div class="card">
                                    <img class="card-img-top"
                                         src="${image}"
                                         alt="Card image cap">
                                    <div class="card-body">
                                        <a target="_blank" href="${url}" class="card-title">${title}</a>
                                        <p class="card-text">${desc}</p>
                                        <p class="card-text comment">${comment}</p>
                                    </div>
                                </div>`
                $('#cards-box').append(temp_html)
            }
        }
    })
}

완성 확인하기

동작 테스트
새로고침했을 때, 앞 포스팅 API를 만들고 테스트했던 메모가 보이면 성공입니다.

**참고!
**
card가 정렬되는 순서는 위에서 아래로 채워지고, 왼쪽부터 오른쪽으로 순서대로 채워집니다. 부트스트랩 컴퍼넌트 페이지에 적혀있어요. "Cards are ordered from top to bottom and left to right." (컴퍼넌트 페이지 링크)

profile
“Stay hungry, Stay foolish.”

0개의 댓글