signupData
에 저장한다. POST
방식으로 데이터를 백앤드로 보내주기 때문에 method를 잘 맞춰야 한다. 또한, JSON 형식으로 데이터를 보내주었다. window.location.replace(url)
을 사용해바로 로그인 페이지로 이동하게 해주었다. base url
이 되는 부분을 변수로 작성해 사용했기 때문에 백틱
으로 url을 감싸 주었다.async function handleSignup() {
// signup 페이지에서 사용자가 입력하는 이메일과 비밀번호 값을 저장
const signupData = {
email: document.getElementById('floatingInput').value,
password: document.getElementById('floatingPassword').value
}
// 위에서 받아온 signupData를 백앤드 쪽으로 밀어주는 부분
const response = await fetch(`${back_base_url}/signup`, {
method: 'POST',
body: JSON.stringify(signupData)
})
console.log(response)
if (response.status == 201) {
alert('회원가입에 성공하셨습니다!')
window.location.replace(`${front_base_url}/login.html`);
} else {
alert('회원가입에 실패하셨습니다. 다시 시도해주세요!')
window.location.reload();
}
}
정규표현식
을 적용해 각각의 형식이 아닌 것들이 들어오면 자동적으로 걸러지게 만들었다. import re
를 통해 모듈을 받아줘야 하며, 정규표현식과 사용자가 입력한 이메일 간의 검증이 올바르지 않다면 None
값이 출력된다. 성공하게 되면 아래와 같이 출력된다. <re.Match object; span=(0, 20), match='qwertyui11@naver.com'>
<re.Match object; span=(0, 11), match='qwertyui11!'>
insert_one()
함수를 통해 user
데이터베이스에 저장된다.@app.route("/signup", methods=['POST'])
def sign_up():
# 프론트 단에서 쏴준 데이터를 JSON 형식으로 받음
data = json.loads(request.data)
print("1", data)
email_receive = data.get('email')
password_receive = data.get('password')
# 정규표현식을 받아와 해당 변수에 저장
email_val = re.compile("^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
password_val = re.compile(
"^.*(?=^.{8,}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%*^&+=]).*$")
# 이메일 또는 비밀번호의 값이 비어있다면 에러메세지 호출
if email_receive == "" or password_receive == "":
return jsonify({"msg": "비어있는 값을 입력해주세요."})
# 이메일의 정규표현식과 내가 받아온 이메일이 일치하지 않는다면 에러메시지 호출
# 만약 매치가 되지 않는다면 None 반환
if not email_val.match(email_receive):
return jsonify({"msg": "이메일을 제대로 입력해주세요."})
else:
print("2", email_val.match(email_receive))
email = email_receive
# 비밀번호의 정규표현식과 내가 받아온 비밀번호가 일치하지 않는다면 에러메시지 호출
# 만약 매치가 되지 않는다면 None 반환
if not password_val.match(password_receive):
return jsonify({"msg": "비밀번호를 제대로 입력해주세요."})
else:
print("3", password_val.match(password_receive))
password = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
doc = {
'email': email,
'password': password
}
db.user.insert_one(doc)
return jsonify({'msg': 'Signup success!'}), 201
** 해당 부분에서 더 보완해야 할 점은 도메인
체크이다. 이상한 도메인을 넣어도 위의 검증만 통과하면 회원가입이 될 것이니 그 부분에 대한 필터가 필요할 것이다.
게시글
의 내용을 상세히 표현하는 방법을 배웠다. 또한 css를 전혀 생각하지 않는(너무 내 스타일인) 회원가입
버튼을 로그인창에 만들어 주어 회원가입을 하지 않은 사용자들을 위한 배려심을 나타내 보았다. 마지막으로 로그아웃
과 로그인
버튼을 메인 페이지에 나타내 주었다.회원가입
버튼<button type="button" onclick="location.href='signup.html';">회원가입</button>
location.href='singup.html
을 사용해 해당 버튼을 누를 시 회원가입 페이지로 이동할 수 있도록 설정해 주었다. 로그아웃
및 로그인
버튼게시글 작성하러 가기
옆에 버튼이 있고 해당 버튼은 로그아웃
으로 표시가 된다. 또한 로그인한 사용자의 이메일
이 화면 좌상단에 표시된다. 로그인
으로 바뀌게 되고, 해당 페이지를 새로고침시키게 된다. 로그아웃이 된 상태이기 때문에 좌상단의 사용자 이메일은 나오지 않게 된다. // 로그아웃 기능.
// 로그아웃 시 로컬 스토리지에 저장되어 있던 유저의 token 값을 삭제하고
// 해당 페이지에서 새로고침만 진행한다.
async function logout() {
localStorage.removeItem('token')
window.location.replace(`${frontend_base_url}/`)
}
async function checkLogin() {
// getName()에서 email 값을 return한다 아예
// 그 값을 사용하는 것
const email = await getName();
console.log(email)
const useremail = document.getElementById('useremail')
const loginoutButton = document.getElementById('loginout')
// email 값이 있다면(로그인이 되어 있다는 거잖아)
if (email) {
// 로그인한 사용자의 이메일 값을 보여주고
useremail.innerText = email
// 로그인을 했으니까 버튼은 로그아웃이겠지?
loginoutButton.innerText = '로그아웃'
// 그래서 저 버튼에 logout() 함수를 걸어주는거야
loginoutButton.setAttribute('onclick', "logout()")
} else {
// 로그아웃된 상태이니 로그인을 해야겠지?
useremail.innerText = '로그인해주세요.'
// 그러니까 버튼안의 텍스트는 로그인이 되야지
loginoutButton.innerText = '로그인'
// 로그인하려고 버튼 누르면 로그인 페이지로 보내면 되겠지?
loginoutButton.setAttribute('onclick', "location.href='/login.html'")
}
}
// 위의 함수 실행
checkLogin();
article_detail
페이지에 보여주는 기능을 구현하였다. title
만 보여졌었는데 이번에는 모든 내용을 보여주도록 하겠다. _id
의 값이 각각 요소들의 고유값이기 때문에 많이 활용되는 것을 알 수 있다. 코드를 짜면서 헷갈릴 수도 있지만 딱 이것만 기억하면 될 것 같다. 백앤드 -> 프론트앤드
: 뭐든지 JSON 형식
으로 넘겨준다.(jsonify) 그러므로 str 값으로 꼭 바꿔줘야 한다. 프론트앤드 -> 백앤드
: 여기서도 그대로 str 값으로 넘겨준다. 하지만 우리가 _id
를 활용해 db의 값을 꺼내려면 원래의 값인 ObjectId
값이 필요하다. 'article': article
를 프론트앤드 쪽으로 넘겨주게 된다. @app.route('/article/<article_id>', methods=["GET"])
def get_article_detail(article_id):
print(article_id)
# 위의 get_article 에서 json 형식으로 데이터를 보내기 위해 _id 값을 str화 하였으니, db에서 해당 값을 찾을 땐 꼭 ObjectId화 해야한다.
article = db.article.find_one({'_id': ObjectId(article_id)})
print(article)
# 다시 _id를 str화 해주면서 모든 article에 담겨 있는 값을 json형식으로 반환할 수 있게 해준다.
article['_id'] = str(article['_id'])
return jsonify({'msg': 'success', 'article': article})
fetch
부분을 보면 알 수 있듯이, article_id
를 넣어서 GET 요청을 보내주며, response_json.article
를 보면 알 수 있듯이 JSON 형식으로 데이터를 넘겨주게 된다. article_id
를 가진 url로 페이지를 전환할 수 있도록 해주는 함수이다. async function getArticleDetail(article_id) {
const response = await fetch(`${backend_base_url}/article/${article_id}`, {
method: "GET"
})
response_json = await response.json()
console.log(response_json)
return response_json.article
}
async function articleDetail(article_id) {
console.log(article_id)
const url = `${frontend_base_url}/article_detail.html?id=${article_id}`
location.href = url
}
getArticleDetail(article_id);
를 통해 얻은 값을 article에 저장한다. 그리고 게시글 상세 페이지에 반영될 각 부분에 innerText
를 통해 값을 넣어줘 페이지에서 보여주도록 하였다.const urlParams = new URLSearchParams(window.location.search);
const article_id = urlParams.get('id');
console.log(article_id)
getArticleDetail(article_id);
async function loadArticles(article_id) {
const article = await getArticleDetail(article_id);
console.log(article)
const title = document.getElementById('title')
const content = document.getElementById('content')
const email = document.getElementById('user_email')
const time = document.getElementById('time')
title.innerText = article.title
content.innerText = article.content
email.innerText = article.email
time.innerText = article.time
}
loadArticles(article_id)