[36] Node.js, MVC패턴, CRUD를 이용한 회원가입 예제(2) (로그인, 수정, 탈퇴, 조회)

minjeong·2024년 2월 18일
0
post-thumbnail

MVC 패턴 구조와 함께 회원가입, 로그인, 회원정보 수정, 회원 탈퇴를 DB와 연동하여 구현하는 예제를 풀어보자. 이때, CRUD도 이용해보자.

이전에 했던 내용에 이어서 작성해보겠다.
이전 게시글 : https://velog.io/@sally3921/33-Node.js-MVC%ED%8C%A8%ED%84%B4-CRUD-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%98%88%EC%A0%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%88%98%EC%A0%95-%ED%83%88%ED%87%B4-%EC%A1%B0%ED%9A%8C

1. model/Muser.js

  • MySQL과 연결되는 파일이라 쿼리문을 작성한다.
const mysql = require('mysql2/promise');
//다중연결
const conn = mysql.createPool({
    host: process.env.HOST,
    user: 'minjeong',
    password: process.env.DB_PASSWORD,
    database: process.env.DATABASE,
    port: process.env.PORT,
    connectionLimit: 15, //최대 연결수 (기본값 10)
});

exports.MsignUp = async (data) => {
    //data : req.body
    const query = `INSERT INTO user (userid, pw, username) VALUES (?,?,?)`;
    const [result] = await conn.query(query, [data.id, data.pw, data.username]);
    return result;
};

exports.Mlogin = async (data) => {
    const query = `SELECT * FROM user WHERE userid = ? AND pw = ?`;
    const [rows] = await conn.query(query, [data.id, data.pw]);
    return rows;
};

exports.Minfo = async (id) => {
    const query = `SELECT * FROM user WHERE id = ?`;
    const [rows] = await conn.query(query, [id]);
    return rows;
};

exports.Mupdate = async (data) => {
    const query = `UPDATE user SET pw = ?, username = ? WHERE id = ?`;
    const [result] = await conn.query(query, [data.pw, data.username, data.id]);
    return result;
};
exports.Mdelete = async (data) => {
    const query = `DELETE FROM user WHERE id = ?`;
    const [result] = await conn.query(query, [data.id]);
    return result;
};

-> 이때 mysql은 단일연결이 아닌 다중연결로 진행했다.
-> 보간법을 사용해서 보안성을 높였다.

2. views/index.ejs

  • 이 파일은 맨 처음에 app.js를 실행했을때 나오는 홈 화면이다. 그래서 매우 단순하다..! css를 하나도 적용하지 않았다는 점...
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <div>
            <h3>안녕하세요. 방문을 환영합니다!</h3>
            <br />
            <a href="/login">로그인</a>
            <a href="/signUp">회원가입</a>
        </div>
    </body>
</html>

3. views/login.ejs

  • 말그대로 login 페이지이다.
  • 비동기 방식으로 처리하기 위해 axios cdn을 가져왔다. cdn은 head에 추가해주면 된다.
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    </head>
    <body>
        <h2>로그인</h2>
        <form name="login-form">
            <input type="text" id="id" placeholder="아이디" /><br />
            <input type="password" id="pw" placeholder="비밀번호" /><br />
            <button type="button" onclick="login()">로그인</button>
        </form>
        <script>
            function login() {
                const form = document.forms['login-form'];
                axios({
                    method: 'post',
                    url: '/api/user/login',
                    data: {
                        id: form.id.value,
                        pw: form.pw.value,
                    },
                }).then((res) => {
                    console.log('res', res);
                    if (res.data.result) {
                        alert(`${res.data.data.username}님, 로그인 되었습니다.`);
                        document.location.href = `/profile/${res.data.data.id}`; //해당 프로필로 가야하는거니까.
                    } else {
                        alert('아이디 및 비밀번호를 다시 확인해주세요.');
                        form.reset();
                    }
                });
            }
        </script>
    </body>
</html>

➡️ axios 라이브러리를 사용하여 서버에 POST 요청을 보내고, 이 요청의 URL은 /api/user/login이며, 요청 본문으로는 사용자가 입력한 id와 pw 값이 전달된다.
➡️ 서버의 응답을 받으면, then 메서드를 통해 응답을 처리하는 콜백 함수를 실행한다. 콜백 함수는서버의 응답을 콘솔에 출력하고, 응답 데이터의 result 필드가 true라면 로그인 성공 메시지를 보여주고 사용자의 프로필 페이지로 이동한다. 만약 result가 false라면, 로그인 실패 메시지를 보여주고 form 요소를 리셋한다.

4. views/profile.ejs

  • 사용자가 로그인을 하면 이동되는 사용자 정보 조회 페이지이다.
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    </head>
    <body>
        <h1>회원정보 조회</h1>
        <form name="info-form">
            <input type="text" id="id" readonly /><br />
            <input type="password" id="pw" placeholder="비밀번호" /><br />
            <input type="text" id="username" placeholder="이름" />
            <button type="button" onclick="updateFunc()">수정</button>
            <button type="button" onclick="deleteFunc()">탈퇴</button>
            <input type="hidden" id="db" />
        </form>
    </body>
    <script>
        console.log(document.location.href);
        const temp = document.location.href.split('profile/'); //맨 마지막 id를 얻기 위해 split해서 배열로 나눈다.
        console.log(temp);
        //페이지 실행되자마자 즉시 실행하는 함수
        (async function () {
            const result = await axios({
                method: 'get',
                url: `/api/user/info/${temp[1]}`, //id이전이 배열[0]이므로 [1]만 가져온다.
            });
            const { id, userid, pw, username } = result.data.info;
            //데이터를 넣어줌
            document.querySelector('#id').value = userid; 
            document.querySelector('#pw').value = pw;
            document.querySelector('#username').value = username;
            document.querySelector('#db').value = id;
            console.log(result);
        })();
        //수정
        function updateFunc() {
            const form = document.forms['info-form'];
            axios({
                method: 'patch',
                url: '/api/user/update',
                data: {
                    pw: form.pw.value,
                    username: form.username.value,
                    id: Number(form.db.value),
                },
            }).then((res) => {
                console.log('res', res);
                if (res.data.result) {
                    alert('회원정보가 성공적으로 수정되었습니다.');
                    document.location.reload();
                }
            });
        }
        //탈퇴
        function deleteFunc() {
            if (!confirm('탈퇴하시겠습니까?')) {
                return;
            }
            const form = document.forms['info-form'];
            axios({
                method: 'delete',
                url: '/api/user/delete',
                data: {
                    id: Number(form.db.value),//정확하게 하기 위해 Number 처리
                },
            }).then((res) => {
                console.log('res', res);
                if (res.data.result) {
                    alert('탈퇴가 완료되었습니다.');
                    document.location.href = '/';
                }
            });
        }
    </script>
</html>

➡️ <input type="hidden" id="db" /> : id는 보여지면 안되지만 deleteFunc에서 사용해야하므로 hidden 처리하였다.

5. views/signUp.ejs

  • 회원가입 을 위한 페이지이다.
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    </head>
    <body>
        <h2>회원가입</h2>
        <form name="signUp-form">
            <fieldset>
                <legend>회원가입</legend>
                <input type="text" id="username" placeholder="이름" /><br />
                <input type="text" id="id" placeholder="아이디" /><br />
                <input type="password" id="pw" placeholder="비밀번호" /><br />
                <button type="button" onclick="signUp()">회원가입</button>
            </fieldset>
        </form>
        <script>
            function signUp() {
                const form = document.forms['signUp-form'];
                axios({
                    method: 'post',
                    url: '/api/user/signUp',
                    data: {
                        id: form.id.value,
                        pw: form.pw.value,
                        username: form.username.value,
                    },
                }).then((res) => {
                    console.log('res', res);
                    if (res.data.result) {
                        alert('회원가입이 완료되었습니다.');
                        document.location.href = '/login'; //회원가입 알람이 뜨면 로그인할 수 있는 페이지로 이동
                    }
                });
            }
        </script>
    </body>
</html>

마무리

아주 기본적인 예제인 회원가입 및 로그인 페이지를 만들어보았다.
어떤식의 로직으로 흘러가는지 어느정도는 알게되어서 신기하고 재미있었다!
이후엔 sequelize, JWT와 함께 게시판까지 작성해보는 실습을 진행해보겠다.

profile
중요한 건 꺾여도 다시 일어서는 마음

0개의 댓글