Vue.js + Express + MySQL로 Node API 서버 구성하기 Quick Start — Part 3

Mix All — 로그인/회원가입 기능 개발하기

조진주
hivelab-dev
10 min readJun 12, 2019

--

Part1에서는 Vue.js와 Express를, Part2에서는 Express와 MySQL 를 다뤄보았습니다.

마지막 Part3에서는 앞서 소개한 Vue.js, Express, MySQL을 모두 활용해 간단한 회원 가입 및 로그인 기능을 제작하기 위한 주요 코드를 설명합니다.

가입

아이디, 이름, 비밀번호 세 가지 데이터를 받는 단순한 폼입니다. 프론트엔드에서 SignUp.vue 컴포넌트를 생성합니다.

각 입력창에는 v-model 디렉티브를 넣어 입력받는 데이터를 바인딩합니다. 가입하기 버튼에는 클릭 이벤트 발생 시 signUp 메소드를 실행하게 합니다.

<div class="input_row">
<label for="id">아이디</label>
<input type="text" id="id" v-model="user.userid">
</div>
<div class="input_row">
<label for="name">이름</label>
<input type="text" id="name" v-model="user.name">
</div>
<div class="input_row">
<label for="password">비밀번호</label>
<input type="password" id="password" v-model="user.password">
</div>
<button :click="signUp">가입하기</button>

컴포넌트의 데이터에는 user 라는 객체를 준비합니다. 이 객체 안에는 아이디, 이름, 비밀번호를 저장할 수 있는 userid, name, password 속성이 있습니다.

data: function () {
return {
user: {
userid: '',
name: '',
password: ''
}
}
},

signUp 메소드에서는 axios로 /api/users/signUp 을호출하여, 입력받은 데이터(this.user)를 user 객체에 저장합니다. 정상 처리 되면, 성공 메시지를 노출하고 login 페이지로 이동을 시키며, 실패하면 에러 메시지를 띄웁니다.

methods: {
signUp: function (event) {
this.$http.post('/api/users/signUp', {
user: this.user
})
.then((res) => {
if (res.data.success == true) {
alert(res.data.message);
this.$router.push('/login')
}
if (res.data.success == false) {
alert(res.data.message);
}
})
.catch(function (error) {
alert('error')
})
}
}

다음은 백엔드의 routes/users.js에 넣어줄 부분입니다.
입력 받은 데이터를 user 객체에 저장한 뒤, DB에 동일한 아이디를 가진 데이터가 없다면 user를 DB에 넣고 그렇지 않다면 에러 메시지를 제공합니다.

user 데이터를 DB에 넣을 때, bcrypt라는 패키지를 사용하여 비밀번호를 암호화합니다.

router.post('/signUp', function (req, res) {
const user = {
'userid': req.body.user.userid,
'name': req.body.user.name,
'password': req.body.user.password
};
connection.query('SELECT userid FROM users WHERE userid = "' + user.userid + '"', function (err, row) {
if (row[0] == undefined){ // 동일한 아이디가 없을경우,
const salt = bcrypt.genSaltSync();
const encryptedPassword = bcrypt.hashSync(user.password, salt);
connection.query('INSERT INTO users (userid,name,password) VALUES ("' + user.userid + '","' + user.name + '","' + encryptedPassword + '")', user, function (err, row2) {
if (err) throw err;
});
res.json({
success: true,
message: 'Sing Up Success!'
})
}
else {
res.json({
success: false,
message: 'Sign Up Failed Please use anoter ID'
})
}
});

});

로그인

프론트엔드에 login.vue를 생성하고 아래 코드와 같이 폼을 구성합니다.

<div class="input_row">
<label for="id">아이디</label>
<input type="text" id="id" v-model="user.userid">
</div>
<div class="input_row">
<label for="password">비밀번호</label>
<input type="password" id="password" v-model="user.password">
</div>
<button v-on:click="login">로그인</button>
<a href="/signUp">가입하기</a>

script 부분은 가입하기와 거의 동일합니다.

data: function () {
return {
user: {
userid: '',
password: ''
}
}
},
methods: {
login: function (event) {
this.$http.post('/api/users/login', {
user: this.user
})
.then(
(res) => { //로그인 성공
alert(res.data.message);
},
(err) => { // error 를 보여줌
alert('Login failed! please check your id or password');
})
.catch(err => {
alert(err);
})
}
}

백엔드의 users.js에서는 입력받은 아이디와 동일한 사용자를 찾습니다. 데이터가 있으면, 비밀번호를 한번 더 체크합니다.

router.post('/login', function (req, res) {
const user = {
'userid': req.body.user.userid,
'password': req.body.user.password
};
connection.query('SELECT userid, password FROM users WHERE userid = "' + user.userid + '"', function (err, row) {
if (err) {
res.json({ // 매칭되는 아이디 없을 경우
success: false,
message: 'Login failed please check your id or password!'
})
}
if (row[0] !== undefined && row[0].userid === user.userid) {
bcrypt.compare(user.password, row[0].password, function (err, res2) {
if (res2) {
res.json({ // 로그인 성공
success: true,
message: 'Login successful!'
})
}
else {
res.json({ // 매칭되는 아이디는 있으나, 비밀번호가 틀린 경우 success: false,
message: 'Login failed please check your id or password!'
})
}
})
}
})
});

사용자 정보 확인

가입된 사용자의 아이디, 이름을 확인할 수 있는 페이지입니다.

프론트엔드에 userList.vue 컴포넌트를 생성합니다. /api/users/를 호출해 백엔드로부터 사용자 정보를 받은 후, users 배열에 저장합니다.

data () {
return {
users: []
}
},
created () {
this.$http.get('/api/users')
.then((response) => {
this.users = response.data
})
}

users 안에 들어온 데이터 수 만큼 반복하여 번호, 아이디, 이름을 출력합니다.

<div v-for="(user, index) in users" :key="index" class="user-wrap">
<h2>No. {{index + 1}}</h2>
<dl>
<dt>아이디</dt>
<dd>{{user.userid}}</dd>
<dt>이름</dt>
<dd>{{user.name}}</dd>
</dl>
</div>

백엔드의 users.js에서는 테이블(users)에 있는 모든 데이터를 가져오는 처리를 합니다.

router.get('/', function (req, res) {
connection.query('SELECT * FROM users', function (err, rows) {
if (err) throw err;
res.send(rows);
});
});

이 글에서는 다루지 않지만 여기에 유효성 검사, 세션 체크 등의 기능을 추가한다면 보다 완벽한 회원가입/로그인 기능이 될 것입니다.

🔍 하이브랩과 함께 할 멋진 FE개발자를 찾고 있습니다.

--

--