이번 주에는 팀별로 웹 개발 미니프로젝트를 만들었다.
내용은 팀 소개페이지를 만드는 것이었다.
팀 소개페이지는 메인페이지와 개인페이지로 구성되어 있는데 와이어프레임을 사용해서 틀을 잡았다.
예전에 Node.js에서 MongoDB를 사용하기 위해 mongoose를 사용한 적이 있는데 꽤나 복잡했던 것으로 기억한다.
파이썬에서 쓰는 pymongo가 훨씬 간단하고 직관적이라고 느꼈다.
클라이언트가 메인페이지 URL로 접근하면 서버가 index.html
를 반환해준다.
# app.py
@app.route('/')
def home():
return render_template('index.html')
클라이언트에서 index.html
이 보여지게 된다.
이제, 멤버카드를 만들기 위해 클라이언트가 멤버정보를 요청할 것이다.
멤버정보 요청에 응답하기 위한 서버의 구현은 다음과 같다.
# app.py
@app.route('/members', methods=["GET"])
def send_members():
# DB에서 id, name, profile, mbti를 가져옴
members = list(db.member.find({}, {'_id': 0, 'id': 1, 'name': 1, 'profile': 1, 'mbti': 1}))
return jsonify({'members': members})
클라이언트가 요청하는 코드는 다음과 같다.
// index.html
$(() => {
getMemberList();
});
// 문서가 만들어지면 실행
const getMemberList = () => {
// '/members로 GET API 요청
fetch('/members').then((res) => res.json()).then((data) => {
members = data.members;
const cardDeck = $('.card-deck');
for (const { id, name, profile, mbti } of members) {
// 멤버카드를 동적으로 생성
let card = `<div class="wrap">
<a href="/member/${id}">
<div class="card">
<div class="card-front">
<h5 class="card-text">${name}</h5>
</div>
<div class="card-back">
<img class="card-img" src=${profile}>
<h5 class="card-text">${mbti}</h5>
</div>
</div>
</a>
</div>
`;
cardDeck.append(card);
}
});
}
여기까지 메인페이지 구현을 완성했다.
멤버카드를 누르면 /member/<id>
로 URL 요청을 보낸다.
이 경로의 요청에는 다음과 같이 준비되어 있다.
# app.py
@app.route('/member/<id>')
def send_template(id):
return render_template('./template.html', id=id)
서버가 하는 일은 개인페이지의 틀이 될 template.html
파일과 멤버의 id
를 클라이언트로 전송하는 것이다.
여기서 바로 상세정보를 보내는 것이 성능상 이점이 있을 것이다.
하지만 함수를 간결하게 만들기 위해 분리하게 되었다.
이제 template.html
에서 id
로 상세정보를 요청할 것이다.
라우팅을 구현해주자.
# app.py
@app.route('/member/detail/<id>')
def send_detail(id):
# 숫자로 바꾸기
id = int(id)
# id에 해당하는 멤버의 모든 상세정보
member = dict(db.member.find_one({'id': id}, {'_id': False}))
return jsonify({'member': member})
클라이언트는 다음과 같이 요청한다.
// template.html
// 서버에서 전달된 id를 받는다.
const member_id = '{{ id }}';
$(() => {
getMembersData(member_id);
});
const getMembersData = (id) => {
fetch(`/member/detail/${id}`).then((res) => res.json()).then((data) => {
member = data.member;
console.log(member);
$('head>title').text(member.name);
$('.profile').attr('src', member.profile);
$('header').text(member.name);
const sns = $('.sns > ul');
for (const [snsName, snsUrl] of member.sns) {
let temp = `<li><a class=${snsName} href=${snsUrl} target="blank"></a></li>`
sns.append(temp);
}
$('#about-desc').html(member.about_me);
const skillIcon = $('#skill-icon');
for (const skillUrl of member.skill) {
let temp = `<img class="lan" src=${skillUrl}>`;
skillIcon.append(temp);
}
$('#interests').html(member.interests);
$('#collab-style').html(member.collab_style);
const whatILike = $('#what-i-like');
for (const [contentType, content] of member.what_i_like) {
let temp;
if (contentType === 'text') {
temp = `<h2 class="wil-txt">${content}</h2>`;
} else if (contentType === 'image') {
temp = `<img class="fav" src=${content}>`;
}
whatILike.append(temp);
}
});
}
가져온 데이터를 템플릿에 뿌려서 페이지를 완성한다.
정보 감사합니다.