[실습_46] 회원가입 CRUD

sese·2022년 8월 9일

새싹

목록 보기
12/39

회원가입 정보를 DATABSE에 연결하고 로그인, 수정, 삭제까지 가능하게 하기


1. 회원가입 페이지 만들기

아래와 같이 간단한 회원가입 페이지를 만들어 주었다.

views - index.ejs

<form id="form_register">
    <fieldset style="width: 300">
        <legend>회원가입</legend>
        <input type="text" name="name" placeholder="NAME" required> <br>
        <input type="text" name="id" placeholder="ID" required> <br>
        <input type="password" name="pw" placeholder="PASSWORD" required> <br> 
        <input type="email" name="email" placeholder="E-MAIL"> <br><br>
        <!-- onclick함수를 등록해주기 위해 button type을 "button"으로 지정해주었다. -->
        <button type="button" onclick="register();">회원가입</button>
    </fieldset>
</form>

2. DB 구축

데이터베이스에 회원 정보를 저장할 테이블도 구축해주었다.

3. 회원가입 정보를 DB에 저장해주기

alert를 띄우기 위해, 동적 폼 전송을 이용하였다.

views - index.ejs

function register() {
    let form = document.getElementById("form_register");

    axios({
      method: "post",
      url: "http://localhost:8080/user/register",
      // input창에 입력된 4개의 정보를 데이터로 보내주었다.
      data: {
        id: form.id.value,
        name: form.name.value,
        pw: form.pw.value,
        email: form.email.value
      }
    }).then((response) => {
      return response.data;
    }).then((data) => {
      // res.send("성공적으로 회원가입 되었습니다. 가입하신 정보로 로그인해주세요.");
      // 그래서 data = "성공적으로 회원가입 되었습니다..."
      // alert 띄어주기
      alert(data);
      // 현재 링크를 "/user/login"으로 옮겨준다.
      window.location.href = "/user/login";
    })
}

routes - index.js

// 'localhost:8080/user/' 경로를 접속했을 때
router.get("/", user.index);
// 위에서 post한 데이터 요청
router.post("/register", user.register);

controller - UserController.js

exports.index = (req, res) => {
    // index.ejs 파일 불러오기
    res.render("index");
}

exports.register = (req, res) => {
    //{id: , name: , pw: , email: }
    console.log(req.body);
    User.register(req.body, function(result) {
        console.log(result);
        res.send("성공적으로 회원가입 되었습니다. 가입하신 정보로 로그인해주세요.");
    });
}

model - User.js

// data = req.body, cb = function(result) {}
exports.register = (data, cb) => {
    // name = data.name, id = data.id ...
    const {name, id, pw, email} = data;

    let sql = `INSERT INTO user VALUES ("${name}", "${id}", "${pw}", "${email}")`;
    cnn.query(sql, (err, rows) => {
        if (err) throw err;
        // rows = OkPacket 객체로 우리가 필요로하는 정보는 담겨져 있지 않다.
        cb( rows );
    })
}

그럼 회원가입 버튼을 눌렀을 때 alert 가 뜨고 DB에 정보가 잘 저장된 것을 볼 수 있다. 동적 폼 전송은 유효성 검사를 따로 해주어야 하기 때문에 지금은 형식이 맞지 않아도 폼 전송이 된다.

그리고 확인 버튼을 누르면 로그인 페이지로 이동하게 된다.

4. 로그인 페이지 만들기

login.ejs 파일에 로그인 페이지도 만들어 주었다.

사진 속에 보이는 로그인 폼과 함께 로그인에 성공했을 경우 프로필 페이지로 정보를 넘겨주기 위해 일반 폼 전송을 이용한 보이지 않는 폼도 만들어주었다.

views - login.ejs

<!-- 폼 전송을 위한 폼 (일반 폼 전송) -->
<form id="form_submit" action="user/profile" method="POST">
    <input type="hidden" name="id">
</form>
<!-- 보이는 로그인 폼 (동적 폼 전송) -->
<form id="login_form">
    <fieldset style="width: 300">
        <legend>로그인</legend>
        <input type="text" name="id" placeholder="ID"> <br>
        <input type="text" name="pw" placeholder="PW"> <br> <br>
        <!-- 로그인에 실패했을 때 실패 문구를 추가해줄 곳이다 -->
        <div style="height: 30; color: red;"></div>
        <button type="button" onclick="login();">로그인</button>
    </fieldset>
</form>

5. DB에서 정보를 검색해 로그인 가능하게 하기

views - index.ejs

function login() {
    let form = document.getElementById("login_form");

    axios({
  		method: "post",
  		url: "http://localhost:8080/user/login",
        // input창에 입력된 id와 pw
  		data: {
  			id: form.id.value,
  			pw: form.pw.value
  		}
    }).then((response) => {
  		return response.data;
  	}).then((data) => {
        // data = 로그인에 성공했을 경우 true, 실패했을 경우 false
        // 실패했을 때
  		if (!data) {
  			let html = "<p>아이디 또는 비밀번호가 틀렸습니다.</p>";
  			$("div").html(html);
        // 성공했을 때
  		} else {
  			alert("로그인 성공");
  			let form_submit = document.getElementById("form_submit");
            // 숨겨진 input값에 input창에 입력된 값 넣어주기
  			form_submit.id.value = form.id.value;
            // 폼 전송하기 -> /user/profile로
  			form_submit.submit();
  		}
  	})
}

routes - index.js

// 'localhost:8080/user/login' 경로를 접속했을 때
router.get("/login", user.login_page);
// "/user/login"으로 post한 데이터 요청
router.post("/login", user.login);
// 로그인 성공시 일반 폼 전송 부분
router.post("/profile", user.profile);

controller - UserController.js

exports.login_page = (req, res) => {
    // "/user/login"에 접속하면 login.ejs 파일 불러오기
    res.render("login");
}

exports.login = (req, res) => {
    // {id: , pw: }
    User.login(req.body, function(result) {
        // result = rows
        console.log(result);
        // result = [] 즉, 일치하는 정보를 찾지 못했을 경우
        if (result.length == 0) {
            res.send(false);
        } else {
            res.send(true);
        }
    });
}

model - User.js

// data = req.body, cb = function(result) {}
exports.login = (data, cb) => {
    // id와 pw가 일치하는 정보 가져오기 (id는 primary key로 중복이 안되므로 하나밖에 없음)
    let sql = `SELECT * from user WHERE id = "${data.id}" AND pw = "${data.pw}"`;
    cnn.query(sql, (err, rows) => {
        if (err) throw err;
        // rows = [RowDataPacket {name: ,id: ,pw: ,email: }]
        cb( rows );
    })
}

결과: 
로그인 실패시 -> 아이디 또는 비밀번호가 틀렸다는 문구가 div 안에 추가된다.
로그인 성공시 -> alert 가 뜨고 프로필 페이지로 이동한다.



6. 프로필 화면에 사용자 정보 가져오기

위에서 로그인 성공시 일반 폼 전송으로 post한 부분의 user.profile 함수를 만들어줘야 한다.

routes - index.js
router.post("/profile", user.profile);

controller - UserController.js

exports.profile = (req, res) => {
    // 일반 폼 전송으로 <input name="id">만 존재한다
    // {id: }
    console.log(req.body);
    User.get_user(req.body, function(result) {
        // result = rows
        // result[0] = {id: , name: , pw: , email: }
        console.log(result[0]);
        res.render("profile", {data: result[0]});
    });
}

model - User.js

// data = req.body, cb = function(result) {}
exports.get_user = (data, cb) => {
    // id가 일치하는 정보 가져오기
    let sql = `SELECT * from user WHERE id = "${data.id}"`
    cnn.query(sql, (err, rows) => {
        if (err) throw err;
        // rows = [RowDataPacket {id: , name: , pw: , email: }]
        cb( rows );
    })
}

views - profile.ejs
controller에서 res.render로 보내준 데이터를 사용하여 화면에 사용자 정보를 띄어준다.

<form id="form_profile">
    ID : <input type="text" name="id" value="<%=data.id%>" readonly> <br>
    NAME : <input type="text" name="name" value="<%=data.name%>" required> <br>
    PASSWORD : <input type="password" name="pw" value="<%=data.pw%>" required> <br> 
    E-MAIL : <input type="email" name="email" value="<%=data.email%>" required> <br><br>
    <button type="button" onclick="editProfile();">수정</button>
    <button type="button" onclick="deleteProfile();">탈퇴</button>
</form>

그럼 다음과 같이 프로필 화면에 사용자 정보가 적히는 것을 볼 수 있다. idprimary key 로 수정이 불가능하게 readonly 속성을 넣어주었으며, 나머지 정보들도 필수로 입력될 수 있게 required 속성을 넣어주었다.


8. 새로운 정보를 입력하고 수정 버튼을 누르면 데이터베이스에 정보를 업데이트 한다.

views - profile.ejs

function editProfile() {
  	let form = document.getElementById("form_profile");

  	axios({
  		method: "patch",
  		url: "http://localhost:8080/user/edit",
  		data: {
  			id: form.id.value,
            name: form.name.value,
            pw: form.pw.value,
            email: form.email.value
  		}
  	}).then((response) => {
  		return response.data;
  	}).then((data) => {
        // data: "회원정보가 수정되었습니다"
  		alert(data);
  	})
}

routes - index.js

router.patch("/edit", user.edit);

controller - UserController.js

exports.edit = (req, res) => {
    // {id: , name: , pw: , email: }
    console.log(req.body);
    User.update(req.body, function(result) {
        console.log(result);
        res.send("회원정보가 수정 되었습니다.");
    });
}

model - User.js

exports.update = (data, cb) =>  {
    let sql = `UPDATE user SET name = "${data.name}", pw = "${data.pw}", email = "${data.email}" WHERE id = "${data.id}"`;
    cnn.query(sql, (err, rows) => {
        if (err) throw err;
        cb( rows );
    })
}

수정 버튼을 누르면 데이터베이스에서 회원정보가 잘 업데이트 된 것을 확인할 수 있다.


9. 탈퇴 기능

views - profile.ejs

function deleteProfile() {
                
  	axios({
  		method: "delete",
  		url: "http://localhost:8080/user/delete",
  		data: {
  			id: '<%=data.id%>'
  		}
  	}).then((response) => {
  		return response.data;
  	}).then((data) => {
        // data: "회원 탈퇴되었습니다."
  		alert(data);
        // 로그인 화면으로 돌아간다.
  		window.location.href = "/user/login";
  	})
}

routes - index.js

router.delete("/delete", user.delete);

controller - UserController.js

exports.delete = (req, res) => {
    User.delete(req.body, function(result) {
        console.log(result);
        res.send("회원 탈퇴되었습니다.");
    });
}

model - User.js

exports.delete = (data, cb) =>  {
    //id가 data.id인 정보를 지운다
    let sql = `DELETE from user WHERE id = "${data.id}"`;
    cnn.query(sql, (err, rows) => {
        if (err) throw err;
        cb( rows );
    })
}

결과:  탈퇴 되었다는 alert 가 뜬 후 로그인 페이지로 이동한다.

완성 코드   👈🏻   깃허브

profile
예전 글은 다크모드로 봐야 잘 보일 수도 있습니다.

0개의 댓글