정화 코딩
이화마켓 웹어플리케이션 개발 : 로그인/회원가입 화면 구현하기 본문
현재 이화마켓 웹어플리케이션을 개발하는 과정 중에 있는데, 그 중 로그인/회원가입 화면은 어느 서비스에서든 활용할 수 있는 필수적인 화면이라고 생각한다. 따라서 웹어플리케이션 개발을 하고자 하는 다른 사람들에게 도움이 되었으면 좋겠다고 생각하여 우리가 이 화면을 어떻게 구현하였는지에 대해 적어보고자 한다.
회원가입 화면
💡 기능
- 회원가입 버튼이 클릭되면 사용자가 입력한 아이디, 비밀번호, 닉네임을 받아 백엔드로 넘긴다.
- 아이디가 중복되지 않는지 체크한다. 중복된 아이디라면 이를 알려주는 메세지 창을 보여주고 회원가입 화면으로 이동한다. 중복되지 않은 아이디라면 정상적으로 데이터베이스에 사용자 정보를 추가하고 로그인 화면으로 이동한다. (비밀번호는 암호화하여 저장한다.)
💡 구현
- app.py 일부
@application.route("/signup")
def signup():
return render_template("signup.html")
네비게이션 바에서 회원가입 버튼을 클릭하면 회원가입 화면으로 이동한다.
- signup.html
{% extends "index.html" %}
{% block section %}
{% with mesg = get_flashed_messages() %}
{% if mesg !=[] %}
<script>alert("{{ mesg[0] }}")</script>
{% endif %}
{% endwith %}
<style>
.wrapper {
width: 700px;
height: 350px;
padding: 40px;
margin: auto;
box-sizing: border-box;
}
#title {
display: flex;
align-items: center;
justify-content: center;
}
#signup-form>input {
width: 100%;
height: 40px;
box-sizing: border-box;
margin-bottom: 16px;
border-radius: 6px;
border: 1px solid #c4c4c4;
background-color: #F8F8F8;
}
#signup-form>input[type="submit"] {
color: rgb(36, 81, 100);
font-size: 16px;
background-color: rgb(163, 223, 249, 0.75);
margin-top: 20px;
}
</style>
<div class="wrapper">
<br>
<h2 id="title">회원가입</h2>
<hr><br>
<form method="post" action="/signup_post" id="signup-form" style="width: 70%; margin: auto;">
<p>ID : </p>
<input type="text" name="id" required>
<p>password : </p>
<input type="password" name="pw" required>
<p>Nickname : </p>
<input type="text" name="nickname"><br><br>
<input type="submit" value="회원가입" id="signupBtn" /></p>
</form>
</div>
{% endblock section %}
회원가입 화면의 html 파일이다. index.html로부터 확장되어 위에 네비게이션 바가 보이고, style은 html 파일 내부에 정의하였다. 사용자가 입력한 정보들은 form에 담겨 post 방식으로 전달되고 "/signup_post"가 이 정보들을 처리하도록 한다.
- app.py 일부
@application.route("/signup_post", methods=['POST'])
def register_user():
data = request.form
pw = request.form['pw']
pw_hash = hashlib.sha256(pw.encode('utf-8')).hexdigest()
if DB.insert_user(data, pw_hash):
return render_template("login.html")
else:
flash("user id already exist!")
return render_template("signup.html")
정보를 전달받은 "/signup_post"는 비밀번호를 암호화한 뒤, DB 함수 insert_user를 통해 데이터베이스에 사용자 정보를 추가한다.
- database.py 일부
# 회원가입
def insert_user(self, data, pw):
user_info = {
"pw": pw,
"nickname": data['nickname']
}
if self.user_duplicate_check(str(data['id'])):
self.db.child("users").child(data['id']).child(
"user_info").set(user_info)
return True
else:
return False
# 회원가입 시 중복 체크
def user_duplicate_check(self, id_string):
users = self.db.child("users").get()
if str(users.val()) == "None": # 첫 회원가입
return True
else:
if id_string in users.val():
return False
return True
중복된 아이디가 없을 때만 정상적으로 데이터베이스에 사용자 정보가 추가되고, 그렇지 않을 때는 False가 반환되게 한다. 단, 사용자 정보가 비어 있을 때, 즉 첫 회원가입의 경우에는 아이디 중복을 체크하지 않고 무조건 추가되도록 한다.
- 화면
로그인 화면
💡 기능
- 로그인 버튼이 클릭되면 사용자가 입력한 아이디, 비밀번호를 받아 백엔드로 넘긴다.
- 데이터베이스에 저장된 사용자 정보들을 하나씩 체크하며 일치하는 아이디가 있는지 체크하고, 있다면 비밀번호가 일치하는지 확인한다.
- 일치하는 아이디가 없거나 비밀번호가 틀렸으면 이를 알려주는 메세지 창을 보여주고 로그인 화면으로 이동한다. 아이디롸 비밀번호가 모두 일치해 로그인에 성공하였다면 session에 사용자의 아이디 값을 저장하고 홈화면으로 이동한다.
- 로그인 버튼과 회원가입 버튼은 마이 페이지 버튼과 로그아웃 버튼으로 바뀐다.
- 모든 페이지에서 session에 접근할 수 있어, 현재 로그인된 사용자의 정보를 찾을 수 있다.
💡 구현
- app.py 일부
@application.route("/login")
def login():
return render_template("login.html")
네비게이션 바에서 로그인 버튼을 클릭하면 로그인 화면으로 이동한다.
- login.html
{% extends "index.html" %}
{% block section %}
{% with mesg = get_flashed_messages() %}
{% if mesg !=[] %}
<script>alert("{{ mesg[0] }}")</script>
{% endif %}
{% endwith %}
<style>
.wrapper {
width: 700px;
height: 350px;
padding: 40px;
margin: auto;
box-sizing: border-box;
}
#title {
display: flex;
align-items: center;
justify-content: center;
}
#login-form>input {
width: 100%;
height: 40px;
box-sizing: border-box;
margin-bottom: 16px;
border-radius: 6px;
border: 1px solid #c4c4c4;
background-color: #F8F8F8;
}
#login-form>input[type="submit"] {
color: rgb(36, 81, 100);
font-size: 16px;
background-color: rgb(163, 223, 249, 0.75);
margin-top: 20px;
}
#signup-btn {
width: 100%;
height: 40px;
box-sizing: border-box;
margin-bottom: 16px;
border-radius: 6px;
border: 1px solid #c4c4c4;
background-color: #F8F8F8;
font-size: 16px;
margin-top: 20px;
}
</style>
<div class="wrapper">
<br>
<h2 id="title">로그인</h2>
<hr><br>
<form action="/login_confirm" method="post" id="login-form" style="width: 70%; margin: auto;">
<p>ID : </p>
<input type="text" name="id">
<p>password : </p>
<input type="password" name="pw"><br><br>
<input type="submit" value="로그인" id="loginBtn" /><br>
</form>
<!-- <p>아직 회원이 아니신가요?</p> -->
<div style="width: 70%; margin: auto;">
<a href="/signup"><button onclick="/signup" id="signup-btn">회원가입</button></a>
</div>
</div>
{% endblock section %}
로그인 화면의 html 파일이다. index.html로부터 확장되어 위에 네비게이션 바가 보이고, style은 html 파일 내부에 정의하였다. 사용자가 입력한 정보들은 form에 담겨 post 방식으로 전달되고 "/login_cnofirm"가 이 정보들을 처리하도록 한다.
- app.py 일부
@application.route("/login_confirm", methods=['POST'])
def login_user():
id = request.form['id']
pw = request.form['pw']
pw_hash = hashlib.sha256(pw.encode('utf-8')).hexdigest()
if DB.find_user(id, pw_hash):
session['id'] = id
return redirect(url_for('hello'))
else:
flash("Wrong ID or PW!")
return render_template("login.html")
정보를 전달받은 "/login_cnofirm "는 비밀번호를 암호화한 뒤, DB 함수 find_user를 통해 해당하는 아이디와 비밀번호를 가진 사용자가 있는지 확인한다. 정상적으로 로그인이 되면 session에 아이디 값을 저장한다. session은 모든 화면에서 접근할 수 있는 데이터이다.
- database.py 일부
def find_user(self, id, pw):
users = self.db.child("users").get()
for user in users.each():
user_id = user.key()
if user_id == id:
user_data = user.val()
user_info = user_data.get("user_info")
if user_info.get("pw") == pw:
return True
else:
return False
return False
해당하는 아이디가 존재하고 비밀번호까지 일치하면 정상적으로 로그인되고, 그렇지 않을 때는 False가 반환되게 한다.
- index.html 일부
<body>
<nav class="navbar">
<div class="navbar__logo">
<a href="/"><img src="/static/images/logo.png" id="navbar-logo" alt="이화마켓" height="40px"></a>
</div>
<ul class="navbar__menu">
<li><a href="/reg_item">Register Items</a></li>
<li><a href="/user_reviews/{{session['id']}}/">My Reviews</a></li> <!--일단 누르면 현재 세션의 아이디로 들어가게 함-->
</ul>
<ul class="navbar__login">
<li><a href="/product_list">모두의 마켓</a></li>
{% if session['id'] %}
<li><a href="/my_page/{{session['id']}}/" id="nav-mypage">{{session['id']}}님의 마이 페이지</a></li>
<li><a href="/logout" id="nav-logout">로그아웃</a></li>
{% else %}
<li><a href="/login" id="nav-login">로그인</a></li>
<li><a href="/signup" id="nav-signup">회원가입</a></li>
{% endif %}
</ul>
</nav>
<div id="navbar-gra"></div>
<section>
{% block section %}
{% endblock section %}
</section>
</body>
session에 아이디 값이 있으면, 즉 로그인 되어있는 상태이면 네비게이션 바 우측에 마이 페이지와 로그아웃 버튼이 보이도록 하고, 로그인 되어있지 않은 상태이면 로그인과 회원가입 버튼이 보이도록 한다.
- 화면
로그아웃
💡 기능
- 로그아웃 버튼이 클릭되면 session을 초기화한다.
💡 구현
- app.py 일부
@application.route("/logout")
def logout_user():
session.clear()
return redirect(url_for('hello'))
'Web Development' 카테고리의 다른 글
[Node.js] Google OAuth 2.0으로 로그인/로그아웃 구현 (0) | 2024.08.02 |
---|---|
[Node.js] jwt 토큰으로 회원가입/로그인/로그아웃 구현 (0) | 2024.07.22 |
[Back-end] codeit : 프로그래밍과 데이터 in JavaScript (0) | 2024.05.21 |
[Back-end] codeit : 프로그래밍 핵심 개념 in JavaScript (0) | 2024.05.21 |
[Back-end] codeit : 프로그래밍 시작하기 in JavaScript (0) | 2024.05.19 |