[0519] TIL 26일차

nikevapormax·2022년 5월 18일
0

TIL

목록 보기
25/116
post-custom-banner

😂 거북이반 인스타 클론코딩

😭 복습

- 회원가입

  • 이번에 정규표현식을 한 번 해봐야겠다 다짐하고 찾아봤는데 생각보다 너무 쉬웠다. 역시 그냥 닥치고 했어야 했다. 안좋은 점으로는 실습을 할 때 모든 것을 진심으로 쳐야되는 부분이다.

이메일 & 비밀번호 정규표현식 참고

  • Javascript 부분
    • signup 페이지에서 사용자가 입력하는 email과 password의 값을 id를 통해 가져와 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();
    }
}
  • python 부분
    • 이메일과 비밀번호를 받는 부분에서 정규표현식을 적용해 각각의 형식이 아닌 것들이 들어오면 자동적으로 걸러지게 만들었다.
    • 정규표현식을 사용하려면 import re를 통해 모듈을 받아줘야 하며, 정규표현식과 사용자가 입력한 이메일 간의 검증이 올바르지 않다면 None 값이 출력된다. 성공하게 되면 아래와 같이 출력된다.
      <re.Match object; span=(0, 20), match='qwertyui11@naver.com'>
       <re.Match object; span=(0, 11), match='qwertyui11!'>
    • 검증을 통과하게 되면, 비밀번호는 해싱과정을 한 번 더 거쳐준다. 검증을 거친 email과 password는 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를 전혀 생각하지 않는(너무 내 스타일인) 회원가입 버튼을 로그인창에 만들어 주어 회원가입을 하지 않은 사용자들을 위한 배려심을 나타내 보았다. 마지막으로 로그아웃로그인 버튼을 메인 페이지에 나타내 주었다.

- 버튼

  • 회원가입 버튼
    • html 파일에 아래와 같이 버튼을 생성해주었다.
      <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();

- 게시글

  • db에 저장되어 있는 게시글의 상세 내용을 article_detail 페이지에 보여주는 기능을 구현하였다.
  • 원래는 메인 페이지에서 게시글을 달면 메인 페이지에 어떤 글이 몇 번째로 달렸는지에 대해서만 나왔다. 즉 , article의 title만 보여졌었는데 이번에는 모든 내용을 보여주도록 하겠다.
  • 백앤드 쪽의 내용을 먼저 살펴보겠다.
    • 맨 위의 route를 보면 지금까지 작성했던 것들과 다르다는 것을 알 수 있다. 변수형 url 이라는 녀석인데, 특정 article에 대한 GET method의 요청이 도달할 때 해당 article의 _id 값도 같이 보내주는 것이다. 즉 js 부분에서 _id 값을 추출해서 넘겨줘야 제대로 된 article의 상세 내용을 돌려받을 수 있는 것이다.
    • 아무래도 _id의 값이 각각 요소들의 고유값이기 때문에 많이 활용되는 것을 알 수 있다. 코드를 짜면서 헷갈릴 수도 있지만 딱 이것만 기억하면 될 것 같다.
      • 백앤드 -> 프론트앤드 : 뭐든지 JSON 형식으로 넘겨준다.(jsonify) 그러므로 str 값으로 꼭 바꿔줘야 한다.
      • 프론트앤드 -> 백앤드 : 여기서도 그대로 str 값으로 넘겨준다. 하지만 우리가 _id를 활용해 db의 값을 꺼내려면 원래의 값인 ObjectId 값이 필요하다.
    • 위의 요청들이 성공적으로 진행되면, article의 정보가 담겨있는 '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})
  • 그 다음으로는 _id 값을 비롯한 article의 정보를 넘겨주는 js 부분을 보도록 하겠다.
    • 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)

😂 YOLO 실습

😭 실습 결과

  • YOLO의 튜토리얼을 체험해 볼 수 있는 사이트에서 YOLO를 기반으로 한 모델을 만들어 봤다. 이번 프로젝트에서 사용할 생각이었지만, 해당 모델에 우리가 사용할 3만장 가량 되는 데이터셋을 어떻게 연결시켜야할 지 잘 모르겠는 것과 CNN과 같은 기법들을 어떻게 적용해야할 지 감이 안와 결국 너무 아깝지만 현재는 사용하지 않는 것으로 하였다.

profile
https://github.com/nikevapormax
post-custom-banner

0개의 댓글