- 2일차 때 정해진 페이지 구상도를 기준으로 각자 HTML 코드를 만들 파트를 배분했다.
- 내가 맡은 파트는 Card 부분.
- 정인님이 잡아주신 틀을 기반으로 진행되었다.
코드 - 시안 (1)
#CSS .card-size { background-color: darkgray; width: 255.5px; height: 300px; margin: 0px 32px 40px 0px; border-radius: 10px; } .card-height { height: 100%; # 카드마다 다른 길이의 내용때문에 짧아지는 카드 길이 보완 } .card-group { width: 1153px; height: auto; margin-bottom: 40px; } .card-img { width: 237.2px; height: 133.9px; # 팀에서 쓰는 api의 이미지 크기를 비율에 맞춰 조금 줄임 object-fit: contain; # width와 height 안쪽으로 이미지 전체가 나오도록 함 border-radius: 10px; margin: 9.1px 9.1px 0px 9.1px; } .title-over { # 타이틀이 길어서 옆으로 빠져나오거나 너비가 달라지지 않도록 생략 height: 30px; width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-over { # 텍스트 길이가 길어져서 빠져나오거나 높이가 달라지지 않도록 생략 width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; } .badge-size { #태그를 꾸며주는 badge의 크기를 알맞게 조절 font-size: 11px; }
# HTML <div id="card-group" class="card-group"> <div id="card" class="card-size"> # 부트스트랩에서 가져온 카드가 부모 태그 크기에 맞춰지기 때문에 크기를 잡아줄 부모태그를 만듬. <div class="card card-height"> <img src="#이미지링크#" class="card-img-top card-img" alt="..."> <div class="card-body"> <h5 class="card-title title-over">#타이틀#</h5> <p class="card-text text-over">#설명#</p> </div> <div class="card-footer"> <small class="text-muted"><span class="badge badge-pill badge-secondary badge-size">#태그#</span></small> </div> </div> </div> </div>
- 결과 :
코드 - 시안 (2)
[ 사실상 CSS 부분만 살짝 바뀌었기에 CSS만 첨부 ]# CSS /*<!-- 여기부터 카드섹션 css -->*/ .card-size { background-color: darkgray; width: 365px; height: 366px; # 카드의 너비, 높이 조금 키움 margin: 0px 13px 40px 0px; # 오른쪽 마진을 살짝 줄임 border-radius: 10px; } .card-height { height: 100%; } .card-group { width: 1153px; height: auto; margin-bottom: 40px; } .card-img { width: 346.75px; height: 195.7px; #이미지의 비율을 높임 object-fit: contain; border-radius: 10px; margin: 9.1px 9.1px 0px 9.1px; } .title-over { height: 30px; width: 320px; # 늘어난 카드 너비에 맞춰 늘림 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-over { width: 320px; # 늘어난 카드 너비에 맞춰 늘림 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; } .badge-size { font-size: 11px; }
- 결과 :
Flask 폴더 구조 만들기
static, templates 폴더 + app.py
기본 뼈대 세우기
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 설정 # POST @app.route('/review', methods=['POST']) def write_review(): sample_receive = request.form['sample_give'] print(sample_receive) return jsonify({'msg': '이 요청은 POST!'}) # GET @app.route('/review', methods=['GET']) def read_reviews(): sample_receive = request.args.get('sample_give') print(sample_receive) return jsonify({'msg': '이 요청은 GET!'}) 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 () { $("#reviews-box").html(""); showReview(); }); # API와 연결 # POST function makeReview() { $.ajax({ type: "POST", url: "/review", data: {sample_give:'샘플데이터'}, success: function (response) { alert(response["msg"]); window.location.reload(); } }) } # GET function showReview() { $.ajax({ type: "GET", url: "/review?sample_give=샘플데이터", data: {}, success: function (response) { alert(response["msg"]); } }) } </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"> <img src="https://previews.123rf.com/images/maxxyustas/maxxyustas1511/maxxyustas151100002/47858355-education-concept-books-and-textbooks-on-the-bookshelf-3d.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"> # API에서 받은 데이터가 들어갈 부분 <tr> <td>왕초보 8주 코딩</td> <td>김르탄</td> <td>역시 왕초보 코딩교육의 명가답군요. 따라하다보니 눈 깜짝할 사이에 8주가 지났습니다.</td> </tr> </tbody> </table> </div> </div> </body> </html>
뼈대에서 필요한 부분 코딩하기
서버 코드 - app.py
@app.route('/review', methods=['POST']) def write_review(): # 클라이언트가 준 title, author, review 가져오기. title_receive = request.form['title_give'] author_receive = request.form['author_give'] review_receive = request.form['review_give'] # DB에 삽입할 review 만들기 doc = { 'title':title_receive, 'author':author_receive, 'review':review_receive } # DB에 정보 저장 db.bookreview.insert_one(doc) # 성공했을 때 성공 메시지 반환하기 return jsonify({'msg': '저장 완료 되었습니다!'})
클라이언트 코드 - index.html
function makeReview() { // 제목, 저자, 리뷰 내용을 input에서 가져오기 let title = $('#title').val(); let author = $('#author').val(); let review = $('#bookReview').val(); // POST /review에 저장 요청 $.ajax({ type: "POST", url: "/review", data: {title_give: title, author_give: author, review_give: review}, success: function (response) { alert(response["msg"]); window.location.reload(); } }) }
- 결과 :
뼈대에서 필요한 부분 코딩하기
서버 코드 - app.py
@app.route('/review', methods=['GET']) def read_reviews(): # DB에서 리뷰 정보 모두 가져오기 reviews = list(db.bookreview.find({}, {'_id': False})) # 2. 성공 시 가져온 리뷰 데이터 반환 return jsonify({'all_reviews': reviews})
클라이언트 코드 - index.html
function showReview() { $('#reviews-box').empty(); $.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); } } }) }
- 결과 :
: app.py로 서버를 구동한 뒤에 html과 연결하여 데이터 베이스 에 input의 데이터를 가져다 넣는것은 처음에는 굉장히 어려운 작 업처럼 느껴졌다. 하지만 강의를 따라 하나하나 해보고 그를 통해 서 이해해가고 깨달아가는 경험은 정말 특별하고 즐거웠다. 프로젝트에서는 오늘 3회차 미팅을 거쳐 FE의 역할을 맡아 일단 카드 섹션 css를 맡았다. 일단은 코드를 최선을 다해 짜보고 결과도 원하는 대로 나온거 같 기는한데, 코딩이야 강의를 통해 조금 익숙해졌다지만 이렇게 팀을 이루어서 하는 프로젝트는 처음이라 그런지 몰라도 영 자신감이 붙 질않는다. 내가 제대로 해낸건지 어딘가 실수 한것은 아닌지 걱정 이 태산이다. 그래도 새로운 경험을 통해서 더욱 내 자신이 성장해가는 것이 느 껴지기에 기분이 매우 좋다.