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)


