[WIL #1] 미니프로젝트 코드 리뷰

안떽왕·2023년 3월 19일
0

Weekly I Learned

목록 보기
1/16
post-thumbnail

팀원들과 함께 작성했던 프로젝트 코드 리뷰를 해보고자 한다. 그간 TIL에 적었을때에는 마감기한이 있어서 제대로 쓰지도 못하고 제출하는 경우가 있었는데 주말이라 자유시간도 있고 한 주에 있었던 내용의 주축이 팀프로젝트였기에 복기한다는 마인드로 작성해보고자 한다.(CSS의 경우 손을 아예 대지도 못했기에 생략하도록 하겠다.)

메인페이지


메인페이지의 기능

  1. 팀원들의 정보 조회
  2. 좋아요
  3. 만화추천

1. 팀원 정보조회

메인 페이지에 불러올 팀원의 정보 명세는 다음과 같다

//url: /data
{
	"name": "string",
	"age":"int",
	"mbti":"string",
	"gender":"string",
	"shortDesc":"string",
	"thumbnail":"string"//image link
}

팀원 정보조회 api

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_contentsresult라는 키를 갖게 한뒤 리턴해준다.

메인페이지 동적 팀원정보 js

// 메인페이지 제네레이터
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부터 시작하기로 했다.

밑에 removecontainer클래스 안에 <p>타입을 제거하는 코드가 있는데 이는 동적으로 박스들을 불러오기전 불러오는 중임을 알리기위해 <p>타입으로 구성된 LODING 이라는 문구를 제거하기 위함이다.

<p style="font-size:large">LOADING...</p> 

2. 좋아요

메인페이지 좋아요 기능은 불러오기 기능과 업데이트 기능이 있다. 각각의 명세는 다음과 같다

// 좋아요 불러오기
// url: /likes
{
	"like":"int"
}
// 좋아요 업데이트
// url: /likes
{
	"like_give":"int" // click count
}

메인페이지 좋아요 api

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방식으로 좋아요를 업데이트한다.
좋아요 업데이트의 경우 프론트로부터 클릭 수를 받아와 이전 좋아요 수와 합산하여 업데이트 한다.

메인페이지 좋아요 js

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함수는 clicklike_give로 백엔드로 보내준다.
show_likes함수는 loaded_like변수에 불러온 좋아요 갯수를 입력하고 likecount1박스에 text형태로 넣어준다.

<!--좋아요 버튼표시 html문서, 버튼을 클릭할때 마다 함수 실행-->
<button class="likeBtn" onclick="like_click()">like</button>

like_click함수는 발생할때 마다 click을 늘려주고, 좋아요 표시박스에 기존 좋아요 횟수와 클릭 수를 합산한 결과를 표시해준다.

3. 만화추천

만화 추천의 기능에는 등록, 불러오기, 삭제가 있다.
만화추천 기능의 명세는 다음과 같다.

// 만화 등록
// url: /guestbook
{
	"name":"string",
	"comment":"string"
}
// 만화 불러오기
// url: /guestbook
{
	"result":[ //list of docts
		{"name":"string", "comment":"string", "id_":"int"},
		{"name":"string", "comment":"string","id_":"int"},
		...
	]
}
	

만화추천 api

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값을 부여해준 값이다.

만화추천 js

// 만화추천 보여주기
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중 어느 것이라도 값이 들어가 있지 않다면 내용을 입력하라는 경고문을 띄운 뒤 함수를 종료 시키게 했다.

프로필 페이지


메인페이지와 중복된 기능들이 많이 있기때문에 설명은 최대한 생략하겠다.

프로필 페이지 기능

  1. 팀원들의 정보 상세조회
  2. 좋아요

1. 프로필 정보 상세조회

프로필 상세조회 명세는 다음과 같다.

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

프로필 정보 상세조회 api

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으로 한 명분의 데이터만 가져온다

프로필 정보 상세조회 js

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

메인페이지에서 작성했던 구조와 매우 유사하다.

2. 프로필 페이지 좋아요

프로필 페이지 좋아요 명세는 다음과 같다

// 프로필 페이지 좋아요 불러오기
// url: /likes/{name}/personal
{
	"like":"int"
}
// 프로필 페이지 좋아요 수정
// url: /likes/{name}/personal
{
	"like_give":"int" // click count
}

프로필 페이지 좋아요 api

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':'좋아요가 반영되었습니다'})

프로필 페이지 좋아요 js

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}`)
	
}
profile
이제 막 개발 배우는 코린이

0개의 댓글