자바스크립트 - 프로젝트 (Login)

정영찬·2022년 2월 9일
0

자바스크립트

목록 보기
17/21

로그인 화면의 html 구현은 부트스트랩의 예시중에서 하나를 가져와서 구현했다.

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

    <link href="css/signin.css" rel="stylesheet">

    <!-- Favicons -->
    <link rel="apple-touch-icon" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/apple-touch-icon.png"
        sizes="180x180">
    <link rel="icon" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/favicon-32x32.png" sizes="32x32"
        type="image/png">
    <link rel="icon" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/favicon-16x16.png" sizes="16x16"
        type="image/png">
    <link rel="manifest" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/manifest.json">
    <link rel="mask-icon" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/safari-pinned-tab.svg"
        color="#7952b3">
    <link rel="icon" href="https://getbootstrap.com/docs/5.1/assets/img/favicons/favicon.ico">
    <meta name="theme-color" content="#7952b3">



    <style>
        .bd-placeholder-img {
            font-size: 1.125rem;
            text-anchor: middle;
            -webkit-user-select: none;
            -moz-user-select: none;
            user-select: none;
        }

        @media (min-width: 768px) {
            .bd-placeholder-img-lg {
                font-size: 3.5rem;
            }
        }
    </style>

    <title>Login</title>
</head>

<body class="text-center">

    <form class="form-signin" id="form-login">

        <h1 class="h3 mb-3 fw-normal">Please sign in</h1>

        <div class="form-floating">
            <input type="email" id="email" class="form-control" placeholder="name@example.com">
            <label for="floatingInput">Email address</label>
        </div>
        <div class="form-floating">
            <input type="password" id="password" class="form-control" placeholder="Password">
            <label for="floatingPassword">Password</label>
        </div>

        <div class="checkbox mb-3">
            <label>
                <input type="checkbox" value="remember-me"> Remember me
            </label>
        </div>
        <button class="w-100 btn btn-lg btn-primary btn-login" type="submit">Sign in</button>
        <p class="mt-5 mb-3 text-muted">&copy; 2017–2021</p>
    </form>



    <!-- Bootstrap Bundle with Popper, JQuery  -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
        integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous">
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous">
    </script>

    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="js/login.js"></script>


</body>

</html>

siginin.css 는 부트스트랩의 소스 파일에 기록되어있으므로 그대로 가져왔다.

html,
body {
  height: 100%;
}

body {
  display: flex;
  align-items: center;
  padding-top: 40px;
  padding-bottom: 40px;
  background-color: #f5f5f5;
}

.form-signin {
  width: 100%;
  max-width: 330px;
  padding: 15px;
  margin: auto;
}

.form-signin .checkbox {
  font-weight: 400;
}

.form-signin .form-floating:focus-within {
  z-index: 2;
}

.form-signin input[type="email"] {
  margin-bottom: -1px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}

.form-signin input[type="password"] {
  margin-bottom: 10px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

다음으로 login.js를 구현하자
구현하기전에 먼저 뭘 만들어야할 지 생각해보자.

-sign in 버튼을 누르면 이벤트를 발생하게 해야한다.
-이렇게 하면 버튼을 누를때 login 이벤트 발생으로 index.html로 넘어간다.
-그럼 어떤 이벤트를 만들어야 index.html로 넘어갈까?

-먼저 사용자가 입력한 email과 password 가 일치한지 확인한다.
-그러려면 먼저 입력한 email과 password 를 가져와야겠지.
-일치 한다면 api에서 token을 넘겨주고 token을 확인한뒤 index로 넘긴다.
-일치 하지 않는다면 오류를 보내고 빈값을 보낸다.

먼저 이것들을 염두하고 만들어보자.

async function main() {
    // 버튼에 이벤트 연결
    bindLoginButton();

    // 토큰 체크
    const token = getToken();
    if (token !== null) {
        location.assign('/');
        return;
    }
}
document.addEventListener('DOMContentLoaded', main); 
//브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생  
//DOM이 준비된 것을 확인한 후 원하는 DOM 노드를 찾아 핸들러를 등록해 인터페이스를 초기화할 때 사용
function getToken() { //token값을 가져온다.
    return localStorage.getItem('token');
}
function bindLoginButton() { //singin 버튼을 누르면 login 함수가 실행된다.
    const form = document.querySelector('#form-login');
    form.addEventListener('submit', login);
}
async function login(event) {
    event.preventDefault();
    event.stopPropagation();
  
// html에 있는 email과 password의 입력을 받는 input element를 반환한다. 
    const emailElement = document.querySelector('#email');
    const passwordElement = document.querySelector('#password');
  
// element가 가지고 있는 값을 변수로 선언한다.
    const email = emailElement.value;
    const password = passwordElement.value;
  
    console.log(email, password);

    try {
        const res = await axios.post('https://api.marktube.tv/v1/me', {
            email,
            password,
        }); //email, password를 api에 전달
        const {
            token
        } = res.data; // 그로 인해서 받는 데이터를 token 으로 정의
        if (token === undefined) {
            return; // 정의되지 않으면 종료
        }
        localStorage.setItem('token', token); //토큰을 받아왔으면 gettoken 함수의 토큰 값을 변경한다.
        location = '/';
    } catch (error) {
        const data = error.response.data;
        if (data) {
            const state = data.error;
            if (state === 'USER_NOT_EXIST') {
                alert('사용자가 존재하지 않습니다.');
            } else if (state === 'PASSWORD_NOT_MATCH') {
                alert('비밀번호가 틀렸습니다.');
            }
        }
    }
}

오류 발생 1. res.data undefined

위의 코드를 적어서 실행을 하면 항상 위의 오류가 발생했는데, api에 email과 password 를 보내주고 받아오는 데이터인 res.data가 정의되지 않았다고 한다.

해결: 강의에서 사용한 axios의 버전은

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

이와 같고 내가 사용했던 버전은

<script src="https://unpkg.com/axios@0.2.1/dist/axios.min.js"></script>

이며 2014년 버전이었고, 강의에서 사용한 버전은 2022년 버전으로 다른 axios.min.js였다. 혹시나 해서 강의에서 사용한 코드를 사용한 결과 오류는 사라졌다.

오류 발생 2. cannot gat / ~~

vscode에 내장된 GOlive 기능으로 사이트를 출력하여 결과값을 보는데 위와 같은 화면이 지속적으로 출력되었다. 아예 기능을 못하는것은 아니지만. 맨 끝에 .html 를 붙여서 실행하면 창이 제대로 켜지지만, 사용자에게 매번 그렇게 하라고 할 수는 없다.

해결 package.json에 serve 설치 후 실행

serve 라는 패키지를 설치하고 package.json scripts에 start명령으로 serve 를 실행하게 했더니 오류 문구 없이 제대로 실행됐다.

npm -init //npm초기화
npm -install serve // serve 설치

package.json에서 scripts라는 항목을 만들어 추가한다.

{
  "name": "mynode",
  "version": "1.0.0",
  "description": "my node packege",
  "main": "index.js",
  "scripts": {
    "start": "serve", // start 명령어
    "test": "echo \"Error: no test specified\" && exit 1" 
  },
  "author": "jyc-coder",
  "license": "ISC",
  "dependencies": {
    "serve": "^13.0.2"
  }
}

터미널 창을 띄운 뒤

npm start 

를 입력하면

아래의 창이 뜨고 해당 링크로 들어가면 ,오류 문구 없이 사이트를 이용할 수 있었다.

최악의 오류 발생

index 화면에서 add books 버튼을 눌러도 add.html화면이 나오지 않고 바로 login 화면으로 돌아가버리는 현상이 발생했다.
오류 메세기도 나타나지 않고 바로 로그인 화면으로 돌아가버려서 골머리를 앓던중 코드를 다시 몇번이나 확인해보고 나서야 문제를 알아냈다.
login 메서드 코드의 일부 중에서 그 오류를 발견했는데,

try {
        const res = await axios.post('https//api.marktube.tv/v1/me', {
            email,
            password,
        }); //email, password를 api에 전달

어디가 문제일까?

바로 api주소에서 ':' 가 빠져있었다.

const res = await axios.post('https//:api.marktube.tv/v1/me'

다르게 보면 정말 사소하기 짝이없는 실수이지만 문자 하나의 유무가 결과를 좌우하게 되므로 코딩할 때 신중하게 작업을 해야겠다고 생각했고, 특히 오타를 많이 내지 말아야겠다고 거듭 다짐하게된 하루였다.

profile
개발자 꿈나무

0개의 댓글

관련 채용 정보