본문 바로가기
개발(Develop)/웹(Web) _프로젝트project

웹 / 페이스북 좋아요 기능 웹 사이트 만들기(2) - DB에 있는 데이터를 활용해 클라이언트에게 시각화하기

by 왁왁s 2021. 6. 10.

내용이 길 것 같아, 게시글을 나누어 프로젝트를 진행해보겠다.

개발환경 설정 및 데이터베이스(DB) 준비는 아래 참고 ▼

페이스북 좋아요 기능 웹 사이트 만들기(1) - 개발환경 설정 및 크롤링을 통한 데이터베이스(DB) 준비

 

 

 

기본 틀 웹페이지의 모습이다.

디자인 부분에 있어서 조금 허접(?)한 느낌이 있지만

좋아요나 없애기 등, 필요한 기능에 대해서는 충실한 편이다.

웹 페이지 HTML 기본 틀


index.html 파일 / My favorite actor . HTML 기본 틀 코드
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <title>나만의 영화배우 순위|좋아요or싫어요</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"/>
        <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
        <style>
            .center {
                text-align: center;
            }

            .star-list {
                width: 500px;
                margin: 20px auto 0 auto;
            }

            .star-name {
                display: inline-block;
            }

            .star-name:hover {
                text-decoration: underline;
            }

            .card {
                margin-bottom: 15px;
            }
        </style>
        <script>
            $(document).ready(function () {
                showStar();
            });

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

            function likeStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/like',
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response['msg']);
                    }
                });
            }

            function deleteStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/delete',
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response['msg']);
                    }
                });
            }

        </script>
    </head>
    <body>
        <section class="hero is-warning">
            <div class="hero-body">
                <div class="container center">
                    <h1 class="title">
                        My Favorite Actor🙈
                    </h1>
                    <h2 class="subtitle">
                        내가 좋아하는 배우 순위♥
                    </h2>
                </div>
            </div>
        </section>
        <div class="star-list" id="star-box">
            <div class="card">
                <div class="card-content">
                    <div class="media">
                        <div class="media-left">
                            <figure class="image is-48x48">
                                <img
                                        src="http://www.nbnnews.co.kr/news/photo/201903/245329_298210_28.jpg"
                                        alt="Placeholder image"
                                />
                            </figure>
                        </div>
                        <div class="media-content">
                            <a href="#" target="_blank" class="star-name title is-4">문채원 (좋아요: 1004)</a>
                            <p class="subtitle is-6">오늘의 연애(영화제목)</p>
                        </div>
                    </div>
                </div>
                <footer class="card-footer">
                    <a href="#" onclick="likeStar('문채원')" class="card-footer-item has-text-info">
                        좋아요
                        <span class="icon">
              <i class="fas fa-thumbs-up"></i>
            </span>
                    </a>
                    <a href="#" onclick="deleteStar('문채원')" class="card-footer-item has-text-danger">
                        없애기
                        <span class="icon">
              <i class="fas fa-ban"></i>
            </span>
                    </a>
                </footer>
            </div>
        </div>
    </body>
</html>


해당 프로젝트에서는 app.py 파일에서 서버와 API를 제공하고, 데이터베이스(DB)를 활용할 것이다.

서버, API, DB를 사용하는 코드는 아래에 있으며, app.py에 들어갈 코드이다.

 

기본 틀 아래와 같고, 기본 틀을 기준으로 필요한 부분은 고쳐서 쓸 것이다.

 

app.py 파일 / 서버, API 제공 기본 틀 코드
from pymongo import MongoClient

from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

client = MongoClient('localhost', 27017)
db = client.dbhwanActor


# HTML 화면 보여주기
@app.route('/')
def home():
    return render_template('index.html')


# API 역할을 하는 부분
@app.route('/api/list', methods=['GET'])
def show_stars():
    sample_receive = request.args.get('sample_give')
    print(sample_receive)
    return jsonify({'msg': 'list 연결되었습니다!'})


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


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


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


그러면 바로 코드를 수정해가면서 프로젝트를 진행해보자.


클라이언트에게 데이터베이스에 있는 정보 시각화 하기


우선 서버 부분에서 어떠한 일을 해줘야 할까?

이번에는 클라이언트로부터 받을 데이터가 없기 때문에

 

1편 게시글에서 채워준 데이터베이스에 있는 데이터를 받아와

Ajax 부분에 제공해주는 역할을 하면 된다.

 

여기서 기능을 한번 추가해보자.

바로 클라이언트가 자신이 좋아하는 배우들을 보기 쉽게,

좋아요 수가 많은 순서대로 정렬을 해서 제공해주는 것이다 

 

많은 순서대로 정렬을 하는데, 마침!!!

pymongo에서 그 기능을 제공하고 있다. 우리는 가져와 사용하기만 하면 된다.

 

새로운 기능 pymongo로 '데이터 정렬하기'

바로 'sort( )' 메소드이다.

구글에 'pymongo 정렬'이라고 치면 sort 메소드에 대한 설명이 나오는데,

많은 것들 중 나는 w3schools의 설명을 가져왔다.

 

원래는 영어로 되어 있는데 구글 번역기를 돌리다보니 말이 어색하다.

 


sort( ) 메소드란?

collection.find().sort(fieldname, direction

 

find( ) 메서드 뒤에 오는데, 데이터베이스에서 가져온 정보를

fieldname을 기준으로 오름차순이나 내림차순으로 정렬을 해주는 '정렬 메소드'이다.

 

fieldname 

해당 매개변수는 필수로 적어줘야 하는 요소로 정렬의 기준을 나타낸다.

이번 프로젝트에서 fieldname은 '좋아요 수'가 되는 것이다.

그러면 데이터베이스에 좋아요 수를 어떤 필드로 저장했는지 보면 된다.

 

direction 

해당 매개변수는 선택적으로 적어주며 데이터들의 정렬 방향을 나타내는 정수이다.

적지 않으면 기본 값으로 '1'이 들어가 있는데, 이는 오름차 을 뜻한다.

그런데 내림차 순으로 데이터를 정렬하고 싶다면 '-1'을 적어주면 된다.


그럼 바로 우리의 프로젝트에 적용해보자.

우리는 우선 서버에서 mongoDB 데이터베이스에 'mystar'이란 

컬렉션으로 저장한 배우들의 정보를 가지고 와야 한다.

 

가지고 오는데, 위에서 다룬 sort( ) 메소드를 사용해 좋아요 순을 기준으로

데이터를 가져오도록 하겠다. 좋아요 수가 많은 것부터 정렬되어야 하므로 '-1' 내림차 순으로 정렬한다.

 

app.py 파일 / GET 방식_데이터베이스에서 데이터를 정렬해서 가져오는 코드
@app.route('/api/list', methods=['GET'])
def show_stars():
    actor = list(db.mystar.find({}, {"_id" : False }).sort("like", -1))
    return jsonify({'actor_like': actor})

 


서버 GET 부분 작성이 완료되었으니 클라이언트 부분을 보자.

 

클라이언트 부분에서는

위에 있는 기본틀에서 showStar( ) 함수의 ajax 부분을 고쳐주면 된다.

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

클라이언트 부분에서는 'actor_like' 키(key) 값으로 서버로 부터 제공받은

데이터베이스의 데이터를 활해서 클라이언트에게 보여주도록 하여야 한다.

 

기존에 '문채원'으로 해놨던 카드 형식에 데이터베이스에서 가져온 데이터를

넣어서 카드를 붙여나가면 될 것 같다.

바로 코드로 작성해보자.

 

index.html 파일 / GET 방식_서버로부터 데이터 받아와 클라이언트에게 보여주는 코드
function showStar() {
    $.ajax({
        type: 'GET',
        url: '/api/list?sample_give=샘플데이터',
        data: {},
        success: function (response) {
            let actors = response["actor_like"]
            for(let i = 0; i < actors.length; i++){
               let name = actors[i]["name"]
               let img_url = actors[i]["img_url"]
               let recent = actors[i]["recent"]
               let url = actors[i]["url"]
               let like = actors[i]["like"]
               let temp_html = `<div class="card">
                                  <div class="card-content">
                                     <div class="media">
                                       <div class="media-left">
                                             <figure class="image is-48x48">
                                             <img
                                                  src="${img_url}"
                                                       alt="Placeholder image"
                                               />
                                             </figure>
                                                 </div>
                                                 <div class="media-content">
                                                     <a href="${url}" target="_blank" class="star-name title is-4">${name} (좋아요: ${like})</a>
                                                     <p class="subtitle is-6">${recent}</p>
                                                 </div>
                                             </div>
                                         </div>
                                        <footer class="card-footer">
                                             <a href="#" onclick="likeStar('${name}')" class="card-footer-item has-text-info">
                                                 좋아요
                                                 <span class="icon">
                                       <i class="fas fa-thumbs-up"></i>
                                     </span>
                                             </a>
                                             <a href="#" onclick="deleteStar('${name}')" class="card-footer-item has-text-danger">
                                                 없애기
                                                 <span class="icon">
                                       <i class="fas fa-ban"></i>
                                    </span>
                                             </a>
                                         </footer>
                                     </div>`
               $("#star-box").append(temp_html)

              }
          }
     });
}


좋아요 버튼을 눌렀을 때 좋아요 수 카운팅 하는 기능 넣기


어덯게 하면 좋아요 버튼을 눌렀을 때 좋아요 수가 올라가게 할 수 있을까?


흠..

배우들 마다 좋아요 버튼이 하나씩 있는 것을 볼 수 있다.

그렇다면 클라이언트가 '엠마 스톤'을 좋아요 했다면, 엠마 스톤이라는 '이름'을 받아

데이터베이스에서 찾은 다음에, 좋아요 수에 대한 데이터를 +1 증가시켜주면 될 것 같다.

 

그럼 서버(app.py 파일) 파일부터 코드를 작성해보자.

 

좋아요 버튼에 대한 API 기본 틀은 아래와 같다.

 

app.py 파일 / 좋아요 버튼 API 기본 골격 코드 
# 좋아요 카운팅 버튼 API
@app.route('/api/like', methods=['POST'])
def like_star():
    name_receive = request.form['name_give']
    
    return jsonify({'msg': 'like 연결되었습니다!'})

우선 서버에서는 클라이언트로부터 '배우(actor)의 이름(name)'을 받아와야 한다.

그리고 받아온 이름으로 데이터베이스에서 딕셔너리를 찾은 후, 좋아요(like)와 관련된 

데이터를 가져와 +1 을 시킨 후, 다시 덮어 씌워주면(update)된다.

 

데이터베이스에서 하나의 값을 찾는 메소드는 find_one( )이다.

그리고 데이터베이스 내에 있는 데이터 값을 업데이트, 변경하는 메소드는 update_one( )이다.

 

find_one( ), update_one( ) 자세한 사용법은 아래 클릭 ▼ 

데이터베이스(DB) /  pymongo라이브러리 / find_one() 명령어/ update_one() 명령어

 


그러면 기본 골격 코드를 수정해, 우리가 필요로 하는 코드로 만들어보자.

 

코드설명

 

POST 방식이므로 request.for[ ' ' ] 형태로 클라이언트로부터 데이터를 받아오고

받아온 이름(name_receive)을 사용해 데이터베이스에 저장되어 있는 딕셔너리를 찾아 가져온다.

딕셔너리에서 좋아요(like)와 관련 데이터를 찾은 후, 우리가 필요한 부분을 수정한 후에

다시 데이터베이스에 업데이트(update) 해준다. 완료가 되면 '좋아요 완료!'와 같은 알림(msg)을 뜨게 한다.

 

app.py 파일 / POST 방식_ 좋아요 카운팅 API 코드 
# 좋아요 카운팅 버튼 API
@app.route('/api/like', methods=['POST'])
def like_star():
    name_receive = request.form['name_give']
    target_actor = db.mystar.find_one({'name': name_receive})
    current_like = target_actor['like']
    plus_like = current_like + 1

    db.mystar.update_one({'name': name_receive},{'$set':{'like': plus_like}})

    return jsonify({'msg': '좋아요 +1'})

서버(app.py) 파일에서 필요한 부분은 작성완료 했다. 클라이언트(index.html) 부분으로 가보자.

 


likeStar( ) 함수 부분을 고쳐야 한다. 아래는 기본 골격 코드이다.

 

index.html 파일 / 좋아요 버튼 눌렀을 때 실행되는 함수_기본 골격 코드
            function likeStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/like',
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response['msg']);
                    }
                });
            }

likeStar( ) 함수를 보게 되면 괄호 안에 'name'이 있는 것을 볼 수 있다.

이는 매개변수로 likeStar( ) 함수에 name이라는 이름으로 값을 전달해주는 것이다.

그럼 무엇을 전달해주는 것인지 확인해보자.

 

맨 위에 index.html 기본 골격 코드를 보게 되면 '좋아요'라는 버튼을 눌렀을 때

실행되는 코드를 보면 onclick = "likeStar('문채원')" 인 것을 볼 수 있다.

해당 함수는 배우의 이름 값(name)을 전달해주는 것 알 수 있다.


클라이언트 부분은 매우 간단하다. POST 방식의 data를 넘길 때

likeStar 함수의 매개변수로 받아온 'name'을 서버로 넘겨주면 되는 것이다.

그리고 '좋아요 완료'라는 식의 알림을 뜨게 하고, 

window.location.reload( )로 브라우저를 새로고침하게 한다.

 

index.html 파일 / 좋아요 버튼 눌렀을 때 실행되는 함수 _완성 코드
            function likeStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/like',
                    data: {name_give : name},
                    success: function (response) {
                        alert(response['msg']);
                        window.location.reload()
                    }
                });
            }

이제 실행이 잘 되는지 해보자.

 

우선 localhost:5000으로 서버에 접속하게 되면

크롤링 해온 배우들이 카드의 형태로 잘 업로드 되는 것을 확인할 수 있다.

그리고 좋아요 버튼을 눌렀을 때 '좋아요 +1'이라는 알림창이 뜨고 브라우저가 새로고침 되는 것을

확인할 수 있다.

 

좋아요 버튼을 누르면 좋아요 수가 카운팅 되고, 좋아요가 많은 배우부터

'내림차순'으로 포스팅 되고 있는 것을 확인할 수 있다.

 

여기까진 완료 !

추가적으로 데이터베이스 mongoDB도 확인해보자. Robo 3T를 실행한다.

 

좋아요에 해당하는 like 부분에 데이터가 잘 들어간 것을 확인할 수 있다.



그러면 마지막으로 ! 

 

원래 가장 좋아하던 배우가 있었는데, 어떤 사건으로 인해

꼴도 보기 싫어졌을 때 사용할 수 있는 기능

바로 '없애기' 즉, 삭제하기 기능이 남았다.

 

가장 쉽다!


좋아요를 더하는 기능과 마찬가지로, 클라이언트로부터 받은 이름(name)으로

해당 배우의 데이터를 찾고 그냥 삭제해주면 되는 것이다!

바로 코드로 보자.

-

설명할 것도 없다. 

db.mystar.delete_one을 사용할 수만 있으면 누구나 할 수 있다!

 

delete_one( ) 사용법 자세한 설명은 아래에 ▼

데이터베이스(DB) /  pymongo라이브러리 / delete_one() 명령어

app.py 파일 / 삭제하기 버튼 API 코드
# 삭제하기 버튼 API
@app.route('/api/delete', methods=['POST'])
def delete_star():
    name_receive = request.form['name_give']
    db.mystar.delete_one({'name' : name_receive})
    return jsonify({'msg': '삭제가 완료되었습니다.'})

바로 클라이언트 부분은 index.html 파일에서 deleteStar(name) 함수를 보도록 하자.

 

마찬가지로 'deleteStar 함수'의 매개변수로 이름을 받아오고,

받아온 이름을 data : {name_give : name}으로 서버에 넘겨주는 작업만 해주면 된다.

그리고 알림창과 새로고침 기능까지 추가 !

 

index.html 파일 / 삭제 버튼을 눌렀을 때 실행되는 함수 코드
            function deleteStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/delete',
                    data: {name_give:name},
                    success: function (response) {
                        alert(response['msg']);
                        window.location.reload()
                    }
                });
            }

그럼 바로 잘 실행되는지 확인해보자.

강동원 배우가 조금.. 꺼려졌다고 가정하고 '없애기' 버튼을 눌러보자.

 

그럼 '삭제가 완료되었습니다.'라는 알림창이 뜨게 되고

 


1순위였던 강동원 배우가 없어지고

4순위였던 봉준호 감독이 치고 올라온 것을 확인할 수 있다.

끝 !

댓글