모든 웹 서비스의 기본, 회원가입 기능을 구현해보자.
프론트는 HTML과 CSS를, 백은 Python과 Firebase를 통해 구현했고, 개발 툴로는 VScode를 사용했다.
개발 환경을 구축하는 과정은 아래 링크에 자세히 설명되어있으니 참고하면 좋을 것 같다.
(출처: 어?이게왜되조 에이스조원 감딸기 블로그)
https://gamddalki.tistory.com/5
1. HTML / CSS
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/static/global.css" />
<link rel="stylesheet" href="/static/sign-up.css" />
<title>sign-up</title>
</head>
<body>
<a href="/">
<img class="logo" src="/static/logo_black.png" alt="logo" /> <!--EatWha 로고-->
</a>
{% with mesg = get_flashed_messages() %} {% if mesg !=[] %}
<script>
alert("{{ mesg[0] }}");
</script>
{% endif %} {% endwith %}
<form class="sign_up_form" action="/signup" method="post">
<input type="text" name="nickname" placeholder="닉네임" />
<input type="text" name="id" required placeholder="아이디" />
<input type="password" name="pw" required placeholder="비밀번호" />
<input type="password" name="pw2" required placeholder="비밀번호 확인" />
<button type="submit" value="생성">회원가입</button>
</form>
<section class="login_section">
<div class="already_signed_up">이미 회원이신가요?</div>
<a href="/login">
<button class="login_button">로그인하기</button>
</a>
</section>
</body>
</html>
</body>
</html>
▲회원가입 화면 HTML
body {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}
.logo {
width: 150px;
height: 100px;
}
.sign_up_form {
display: flex;
flex-direction: column;
gap: 15px;
}
.sign_up_form input, .sign_up_form button {
width: 300px;
height: 55px;
border-radius: 18px;
padding: 15px;
font-size: 18px;
}
.sign_up_form button{
background-color: #FD5D5D;
color: white;
}
.login_section {
display: flex;
align-items: center;
}
.already_signed_up {
color: #AFABAB;
font-size: 17px;
}
.login_button {
border: 0;
box-shadow: none;
background-color: transparent;
text-decoration: underline;
color: #808080;
font-size: 17px;
}
/* footer */
footer {
width: 100%;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
background-color: #E7E6E6;
}
.copyright {
font-size: 16px;
color: #AFABAB;
}
▲회원가입 화면 CSS
EatWha는 편리하고 깔끔한 UX/UI를 고려하여 홈 화면에 별도의 회원가입 버튼을 만들지 않았다.
홈에서 로그인 버튼을 클릭하면 아래와 같은 로그인 화면으로 이동하게 되는데 로그인 화면 하단에서 회원가입 페이지로 이동하는 링크를 찾을 수 있다.
로그인 버튼 아래의 "회원가입하기"를 클릭하면 아래와 같은 회원가입 화면으로 이동한다.
회원가입 과정에서는 닉네임, 아이디, 비밀번호를 받는다.
그리고 입력한 비밀번호가 맞는지 한 번 더 확인하면 회원가입이 완료된다.
(+) 만약 시간적 여유가 생겨서 잇화를 디벨롭 할 수 있다면 회원가입 단계에서 이메일이나 휴대폰 번호를 통한 본인인증 기능을 추가하면 좋을 것 같다.
이렇게 필수적인 요소들만 배치하고 시그니처 색상으로 포인트를 준 깔끔한 회원가입 화면이 완성되었다.
이제 본격적인 기능을 구현해보자.
2. Python
#회원가입 화면
@application.route('/signup', methods=['POST', 'GET'])
def sign_up():
if request.method == 'POST':
data=request.form
pw=request.form['pw']
pw_hash=hashlib.sha256(pw.encode('utf-8')).hexdigest()
print(data)
if DB.insert_user(data, pw_hash):
return render_template("login.html")
else:
flash("중복된 ID 입니다!")
return render_template("sign-up.html")
else :
return render_template("sign-up.html")
▲app.py
#회원가입
def insert_user(self, data, pw):
user_info={
"id":data['id'],
"pw":pw,
"nickname":data['nickname']
}
if self.user_duplicate_check(str(data['id'])):
self.db.child("user").push(user_info)
print(data)
return True
else:
return False
def user_duplicate_check(self, id_string):
users=self.db.child("user").get()
print("users###", users.val())
if str(users.val()) == "None":
return True
else:
for res in users.each():
value=res.val()
if value['id']==id_string:
return False
return True
▲database.py
POST 방식으로 닉네임, 아이디, 비밀번호 등 필요한 데이터를 입력받고 이를 DB로 넘겨주는데 만약 사용자가 입력한 ID가 기존 DB에 이미 존재한다면 "중복된 ID 입니다!" 라는 메시지 창을 띄워 중복된 ID의 회원가입을 방지한다. 또, 비밀번호의 경우에는 사용자가 입력한 비밀번호를 문자 그대로 전달하는 것이 아니라 해시값으로 변경해서 전달하는 코드도 추가했다.
이렇게 완성된 회원가입 화면에서 회원가입 절차를 밟고나서 Firebase 실시간 데이터 베이스 창에 들어가보면,
★!!~ TADA ~!!★
내가 입력한 정보가 다음과 같은 해시값으로 예쁘게 잘 들어가는 것을 확인할 수 있다.
비밀번호 역시 해시값으로 잘 저장된다.
3. 탈퇴하기
회원가입 기능을 만들었으면 회원탈퇴 기능도 만들어야 하는 것이 인지상정.
프로젝트에 필수로 추가해야 하는 기능도 아니었고 extra credit 요소도 아니었지만 진짜 출시할 서비스를 만든다고 하면 빠질 수 없는 게 탈퇴 기능이기때문에 한번 구현해보았다.
탈퇴 기능의 HTML과 CSS는 로그인 및 회원가입 화면과 거의 유사하다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>login</title>
<link rel="stylesheet" href="/static/global.css" />
<link rel="stylesheet" href="/static/withdrawl.css" />
</head>
<body>
<a href="/">
<img class="logo" src="/static/logo_black.png" alt="logo" />
</a>
{% with mesg = get_flashed_messages() %} {% if mesg !=[] %}
<script>
alert("{{ mesg[0] }}");
</script>
{% endif %} {% endwith %}
<form class="withdrawl_form" action="/withdrawl" method="post">
<div class="login_again">탈퇴하시려면 비밀번호를 다시 입력해주세요.</div>
<input type="password" name="pw" id="pw" placeholder="비밀번호" />
<button type="submit" value="탈퇴하기">탈퇴하기</button>
</form>
</body>
</html>
▲탈퇴하기 HTML
body {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
}
.logo {
width: 150px;
height: 100px;
}
.login_form {
display: flex;
flex-direction: column;
gap: 15px;
}
.withdrawl_form input, .withdrawl_form button {
width: 300px;
height: 55px;
border-radius: 18px;
padding: 15px;
font-size: 18px;
}
.withdrawl_form button{
background-color: #FD5D5D;
color: white;
}
/* footer */
footer {
width: 100%;
height: 150px;
display: flex;
justify-content: center;
align-items: center;
background-color: #E7E6E6;
}
.copyright {
font-size: 16px;
color: #AFABAB;
}
▲탈퇴하기 CSS
#탈퇴하기 화면
@application.route('/withdrawl', methods=['POST', 'GET'])
def withdrawl():
if request.method == 'POST':
id=session['id']
pw=request.form['pw']
pw_hash=hashlib.sha256(pw.encode('utf-8')).hexdigest()
print(id)
print(pw)
print(pw_hash)
if DB.withdrawl(id, pw):
flash("지금까지 EatWha를 이용해주셔서 감사합니다. 언제든지 다시 돌아오세요.")
session.clear()
return redirect(url_for('home'))
else :
flash("비밀번호가 틀렸습니다")
return redirect(url_for('withdrawl'))
else :
return render_template("withdrawl.html")
▲app.py
#탈퇴하기
def withdrawl(self, id, pw):
users = self.db.child("user").get()
for res in users.each():
value = res.val()
key = res.key()
if value['id'] == id and value['pw'] == pw:
print(key)
self.db.child("user").child(key).remove()
return True
return False
▲database.py
기능 또한 app.py 와 database.py 파일에 추가해주었다.
잇화에서 회원탈퇴를 하기 위해서는 현재 비밀번호를 한 번 더 입력해야한다. 그렇게 입력받은 데이터를 해시값으로 변환하고, 그 값을 firebase에 저장된 비밀번호 DB와 비교하여 해당 사용자의 데이터를 삭제하는 방식으로 구현했다.
TIP
firebase에서 직접 데이터를 삭제하는 방식이 아닌 python 코드로 DB에 접근해서 데이터를 삭제하는 경우에는 .remove() 기능을 사용해야한다. delete(), deleteValue(), removeValue() 전부 사용해봤지만 .remove() 외의 모든 명령어들은 데이터를 삭제하지 못했다.
로그인 후 마이페이지 화면을 스크롤 해서 내리면 최하단에서 "탈퇴하기" 버튼을 찾을 수 있다.
탈퇴하기를 클릭하면 다음과 같은 탈퇴 창을 볼 수 있다.
현재 로그인 되어있는 계정의 비밀번호를 한 번 더 입력하고나면
firebase 데이터 베이스에서 사용자 정보가 삭제되고,
로그아웃 된 홈 화면으로 돌아간다.
firebase에 접속해서 콘솔을 보면 이전의 "billy" 계정이 삭제된 것을 확인할 수 있다.
오는 사람 막지 않고 가는 사람 잡지 않는 쿨한 서비스를 제공하고 싶어 어려움 끝에 탈퇴 기능을 구현해놓기는 했지만...
제작자로서 어떤 사용자도 탈퇴하기 기능을 사용하지 않았으면 하는 바람이 가장 크다 ㅎㅎ
(저희 UI도 예쁘고요 데이터도 많고요 가지마세요 계속 잇화와 함께해주세요...~)
'CSE > Capstone Design' 카테고리의 다른 글
[C#] Inkspire - Map 기반 스토리 진행 시스템 구현 (0) | 2024.05.21 |
---|---|
[Python/chatGPT API] NPC 생성 함수 구현 (0) | 2023.11.24 |
[기획] Inkspire : NLP와 생성형 AI 기술을 사용한 텍스트 RPG (0) | 2023.11.24 |