팀원들과 함께 작성했던 프로젝트 코드 리뷰를 해보고자 한다. 그간 TIL에 적었을때에는 마감기한이 있어서 제대로 쓰지도 못하고 제출하는 경우가 있었는데 주말이라 자유시간도 있고 한 주에 있었던 내용의 주축이 팀프로젝트였기에 복기한다는 마인드로 작성해보고자 한다.(CSS의 경우 손을 아예 대지도 못했기에 생략하도록 하겠다.)
메인 페이지에 불러올 팀원의 정보 명세는 다음과 같다
//url: /data
{
"name": "string",
"age":"int",
"mbti":"string",
"gender":"string",
"shortDesc":"string",
"thumbnail":"string"//image link
}
client = MongoClient("mongodb+srv://animal:test@tiger.46jdijc.mongodb.net/?retryWrites=true&w=majority") # DB주소 키 값
db = client['cai'] # db는 cai라는 db
collection = db['cai'] # collection은 db속 cai라는 테이블(콜렉션)
# 메인페이지 데이터 가져오기
@app.route("/data", methods=["GET"])
def load_teammate():
all_contents = list(collection.find({},{"name":True,"age":True,"gender":True,"mbti":True,"shortDesc":True, "thumbnail":True,'_id':False}))
return jsonify({'result':all_contents})
get
메서드를 사용해 "/data"
요청이 올때 db에 접속하고
all_contents
라는 변수에 name
, age
, gender
, mbti
, shortDesc
, thumbnail
을 넣고 id값은 제외 시켰다.
그리고 all_contents
를 result
라는 키를 갖게 한뒤 리턴해준다.
// 메인페이지 제네레이터
function listing() {
fetch('/data').then((res) => res.json()).then((data) => {
let rows=data['result']
let i =2;
rows.forEach((a) => {
let name = a['name']
let age = a['age']
let gender = a['gender']
let mbti = a['mbti']
let shortDesc = a['shortDesc']
//프론트 디자인 양식에 맞춰 수정필요
let temp_html = `
<div class = "commonBoxStyle box${i}">
<a href="/profile/${name}/">
<div class="overlay">
<div class="contents" id="_${i}">
<span>${name}</span><br><br>
<span>연령:</span> ${age}<br>
<span>성별:</span> ${gender}<br>
<span>MBTI:</span> ${mbti}
<br><br>
<span>한줄 소개</span>
<br>${shortDesc}
</div>
</div>
</a>
</div>`
$('.container').append(temp_html)// sellector(컨테이너) 수정필요
i++;
});
$('.container>p').remove()
i=2
rows.forEach((a) => {
let thumbnail = a['thumbnail']
$('.box'+i).css("background-image",'url('+thumbnail+')')
$('.box'+i).css("background-size","cover")
$('.box'+i).css("background-position","center")
if(i==3){
$('.box'+i).css("background-position","top")
}
i++;
});
})
}
메인페이지가 열리게 되면 팀원들의 데이터 정보를 가져오는 listing
함수가 실행된다.
fetch
를 통해 api에 요청을 보내고 result
를 키로 갖는 값을 rows라는 변수에 저장했다.
우리 팀은 동적으로 데이터가 삽입되는 페이지를 구성했기 때문에 db속 데이터 갯수에 따라 div
의 갯수가 늘어난다.
동적으로 박스들이 늘어남에 따라 박스들 마다 id를 jquery로 붙혀줬는데 i가 2로 시작하는것을 확인 할 수 있는데 이는 첫번째 박스는 우리가 프로젝트의 이름과 좋아요 갯수를 표시하자고 합의 했기때문에 id가 2부터 시작하기로 했다.
밑에 remove
로 container
클래스 안에 <p>
타입을 제거하는 코드가 있는데 이는 동적으로 박스들을 불러오기전 불러오는 중임을 알리기위해 <p>
타입으로 구성된 LODING 이라는 문구를 제거하기 위함이다.
<p style="font-size:large">LOADING...</p>
메인페이지 좋아요 기능은 불러오기 기능과 업데이트 기능이 있다. 각각의 명세는 다음과 같다
// 좋아요 불러오기
// url: /likes
{
"like":"int"
}
// 좋아요 업데이트
// url: /likes
{
"like_give":"int" // click count
}
client = MongoClient("mongodb+srv://animal:test@tiger.46jdijc.mongodb.net/?retryWrites=true&w=majority") # DB주소 키 값
db = client['cai'] # db는 cai라는 db
likes_coll = db['likes'] # 메인페이지 좋아요 콜렉션
# 페이지 좋아요
@app.route("/likes", methods=["GET"])
def like_show():
like = likes_coll.find_one({},{"_id":False,"like":True,})
like['like']=int(like['like'])
return jsonify({'result':like})
#like 수정. front로부터 버튼이 눌린횟수를 받아와 업데이트
@app.route("/likes", methods=["PUT"])
def like_update():
like_receive= int(request.form['like_give'])#클릭수받음
old_data=likes_coll.find_one({},{'_id':False,})#DB의 구 like
new_like=int(old_data['like'])+like_receive#합산
likes_coll.update_one({'like':old_data['like']}, {'$set':{'like':new_like}})#반영
return jsonify({'msg':'좋아요가 반영되었습니다'})
get방식으로 좋아요를 db에서 불러오고, put방식으로 좋아요를 업데이트한다.
좋아요 업데이트의 경우 프론트로부터 클릭 수를 받아와 이전 좋아요 수와 합산하여 업데이트 한다.
var click=0;
var loaded_like=0;
// 좋아요 업데이트
function likes_update() {
let formData = new FormData();
formData.append("like_give", click);
fetch('/likes',{method:"PUT", body: formData}).then((res) => res.json()).then((data) => {
})
}
// 좋아요 불러오기
function show_likes() {
fetch('/likes').then((res) => res.json()).then((data) => {
like = data['result']
loaded_like = Object.values(like)[0]
$('#likecount1').text(loaded_like)
})
}
// 버튼 클릭 이벤트
function like_click(){
click++;
let new_like=click+loaded_like
$('.box1>a>h1').text('좋아요!: '+ new_like)
}
먼저 클릭 수를 받을 click
변수를 선언하고, 불러올 좋아요 수를 담을 loaded_like
를 선언했다.
likes_update
함수는 click
을 like_give
로 백엔드로 보내준다.
show_likes
함수는 loaded_like
변수에 불러온 좋아요 갯수를 입력하고 likecount1
박스에 text형태로 넣어준다.
<!--좋아요 버튼표시 html문서, 버튼을 클릭할때 마다 함수 실행-->
<button class="likeBtn" onclick="like_click()">like</button>
like_click
함수는 발생할때 마다 click
을 늘려주고, 좋아요 표시박스에 기존 좋아요 횟수와 클릭 수를 합산한 결과를 표시해준다.
만화 추천의 기능에는 등록, 불러오기, 삭제가 있다.
만화추천 기능의 명세는 다음과 같다.
// 만화 등록
// url: /guestbook
{
"name":"string",
"comment":"string"
}
// 만화 불러오기
// url: /guestbook
{
"result":[ //list of docts
{"name":"string", "comment":"string", "id_":"int"},
{"name":"string", "comment":"string","id_":"int"},
...
]
}
client = MongoClient("mongodb+srv://animal:test@tiger.46jdijc.mongodb.net/?retryWrites=true&w=majority") # DB주소 키 값
db = client['cai'] # db는 cai라는 db
recomm = db['recomm'] # 메인페이지 만화추천 콜렉션
# 만화추천 올리기
@app.route("/recommbook", methods=["POST"])
def recommbook_post():
name_receive = request.form['name_give']
comment_receive = request.form['comment_give']
num_list = list(recomm.find({},{'_id':False}))
num = 1
if num_list:
num = int(num_list[-1]['id_'])+1
doc = {
'name': name_receive,
'comment': comment_receive,
'id_': num
}
recomm.insert_one(doc)
return jsonify({'msg': 'Saved!'})
# 만화추천 보기
@app.route("/recommbook", methods=["GET"])
def recommbook_get():
all_comments = list(recomm.find({},{'_id':False}))[::-1]
return jsonify({'result': all_comments})
# 만화추천 삭제하기
@app.route("/recommbook/<int:id_>", methods=["DELETE"])
def recommbook_delete(id_):
recomm.delete_one({'id_':id_})
return jsonify({'msg':'good'})
만화추천 보기 all_comments
선언 부분에 -1은 방명록을 볼때 최신순으로 보기위해 기재하였다.
만화추천 방명록 역시 동적으로 추가되는 형태를 선택했는데 회원가입기능 없이 누구든 좋지 않은 글을 보면 삭제할 수 있도록 만들어 놓았다 id_
는 동적으로 id값을 부여해준 값이다.
// 만화추천 보여주기
function show_comm(){
fetch('/recommbook').then((res) => res.json()).then((data) => {
let rows = data['result']
$('#comment-list').empty()
rows.forEach((v) => {
let name = v['name']
let comment = v['comment']
let id_ = v['id_']
let html_temp = `<div class="card">
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>${comment}</p>
<footer class="blockquote-footer">${name}</footer>
</blockquote>
<buttontoken interpolation">${id_})" type="button" class="btn btn-dark">
삭제하기
</button>
</div>
</div>`
$('#comment-list').append(html_temp)
})
})
}
// 만화추천 올리기
function save_comment() {
let name = $('#name').val()
let comment = $('#comment').val()
//빈 문자열 확인
if (name.trim()=='' || comment.trim()==''){
alert("내용을 입력해주세요")
return;
}
let formData = new FormData();
formData.append("name_give", name);
formData.append("comment_give", comment);
fetch('/recommbook', { method: "POST", body: formData, }).then((res) => res.json()).then((data) => {
window.location.reload()
});
}
// 만화추천 삭제
function delete_comm(id) {
fetch('/recommbook/'+id, {method: "DELETE"}).then((res) => res.json()).then((data) =>{
window.location.reload();
});
}
만화 방명록이 동적으로 추가될 때 삭제할 값을 만들어주기 위해 id_
값을 동적으로 집어 넣게 만들었다.
save_comment
함수는 name
이나 comment
중 어느 것이라도 값이 들어가 있지 않다면 내용을 입력하라는 경고문을 띄운 뒤 함수를 종료 시키게 했다.
메인페이지와 중복된 기능들이 많이 있기때문에 설명은 최대한 생략하겠다.
프로필 상세조회 명세는 다음과 같다.
// url: /profile/{name}/data
{
"name": "string",
"age":"int",
"mbti":"string",
"gender":"string",
"goal_style":"string"
"pro_con":"string",
"blog":"string",// blog link
"tmi":"string",
"imglink":"string"//image link
}
client = MongoClient("mongodb+srv://animal:test@tiger.46jdijc.mongodb.net/?retryWrites=true&w=majority") # DB주소 키 값
db = client['cai'] # db는 cai라는 db
collection = db['cai'] # collection은 db속 cai라는 테이블(콜렉션)
@app.route("/profile/<string:name>/data", methods=["GET"])
def load_profile(name):
profile = collection.find_one({'name':name},{"_id":False,"shortDesc":False,"thumbnail":False,})
return jsonify({'result':profile})
find_one
으로 한 명분의 데이터만 가져온다
var link = document.location.href
var string = decodeURI(link);
var urlname = string.slice(30, -1)
function listing() {
fetch('/profile/'+ urlname +'/data').then((res) => res.json()).then((data) => {
let a = data['result']
$('.container').empty()// 프론트 변경에 따라 변경 필요
let name = a['name']
let age = a['age']
let gender = a['gender']
let mbti = a['mbti']
let tmi = a['tmi']
let imglink=a['imglink']//별개이미지 사용
let pro_con =a['pro_con']
let goal_style = a['goal_style']
let blog=a['blog']
//프론트 디자인 양식에 맞춰 수정필요
let temp_html = `
<div class="item">
<h3>TMI</h3>
<p>${tmi}</p>
</div>
<div id="imgbox" class="item"></div>
<div class="item">
<h3>목표/협업스타일 등</h3>
<p>${goal_style}</p>
</div>
<div class="item">
<h3>INFO</h3>
이름: ${name}<br>
연령: ${age}<br>
성별: ${gender}<br>
MBTI: ${mbti}
<div class="p_likebox">
<div id="likecount1">
</div>
<button class="custom-btn like">like it</button>
</div>
</div>
<div class="item">블로그 주소:<a href="${blog}">${blog}</a></div>
<div class="hide"></div>
<div class="item">
<h3>나의 장단점</h3>
<p>${pro_con}</p>
</div>`
$('.container').append(temp_html)
insert_personal_like(); // 좋아요 로드 함수
$('#imgbox').css("background-image","url("+ imglink+")")
$('.origin').remove()
})
}
메인페이지에서 작성했던 구조와 매우 유사하다.
프로필 페이지 좋아요 명세는 다음과 같다
// 프로필 페이지 좋아요 불러오기
// url: /likes/{name}/personal
{
"like":"int"
}
// 프로필 페이지 좋아요 수정
// url: /likes/{name}/personal
{
"like_give":"int" // click count
}
client = MongoClient("mongodb+srv://animal:test@tiger.46jdijc.mongodb.net/?retryWrites=true&w=majority") # DB주소 키 값
db = client['cai'] # db는 cai라는 db
personal_like = db['personal_like'] # 개인페이지 좋아요 컬랙션
# 개인페이지 좋아요
@app.route("/likes/<string:name>/personal", methods=["GET"])
def personal_like_show(name):
like_P = personal_like.find_one({"name":name},{"like":True,'_id':False,})
like_P['like']=int(like_P['like'])
return jsonify({'result':like_P})
#개인페이지 좋아요 업데이트
@app.route("/likes/<string:name>/personal", methods=["PUT"])
def personal_like_update(name):
like_P_receive= int(request.form['like_give'])#클릭수받음
old_data=personal_like.find_one({"name":name},{'like':True,'_id':False,})#DB의 구 like
new_like=int(old_data['like'])+like_P_receive#합산
personal_like.update_one({'name':name}, {'$set':{'like':new_like}})#반영
return jsonify({'msg':'좋아요가 반영되었습니다'})
var link = document.location.href
var string = decodeURI(link);
var urlname = string.slice(30, -1)
var click=0;
var loaded_like=0;
// 좋아요 불러오기
function insert_personal_like(){
fetch('/likes/' + urlname + '/personal').then((res) => res.json()).then((data) => {
like = data['result']
loaded_like = Object.values(like)[0]
$('#likecount1').append(`좋아요!:<br>${loaded_like}`)
})
}
// 좋아요 업데이트
function likes_update() {
let formData = new FormData();
formData.append("like_give", click);
fetch('/likes/'+urlname+'/personal',{method:"PUT", body: formData}).then((res) => res.json()).then((data) => {
})
}
// 좋아요 버튼 이벤트
function like_click(){
click++;
let new_like=click+loaded_like
$('#likecount1').empty()
$('#likecount1').append(`좋아요!:<br>${new_like}`)
}