회원 관리 기능 구현하기
ㆍProject Diary/Vue (Roblox WebSite)
Vue.js에서 회원 관리 기능 방법 기록
Part1. 회원가입
회원가입은 사용자가 이메일, 이름, 비밀번호를 입력하고 가입하는 기능입니다. 먼저, 회원가입 폼을 만들어 보겠습니다.
회원가입 폼 구현
<template>
<div class="join__section">
<form @submit.prevent="fnRegisterUser">
<div class="wrapper">
<div class="wrapper__title" :class="{ dark: changeDarkMode }">
{{ $t("[3].joinSection.RJoin") }}
</div>
<div class="wrapper__info">
<i class="fa-solid fa-envelope" :class="{ dark: changeDarkMode }"></i>
<input
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.emailPlaceholder')"
v-model="dEmail"
ref="email"
@input="inputEmail"
/>
<div class="error" :class="{ on: existEmailClass }">
{{ $t("[3].joinSection.errorExistEmail") }}
</div>
<div class="error" :class="{ on: emailClass }">
{{ $t("[3].joinSection.errorFormatEmail") }}
</div>
</div>
<div class="wrapper__info">
<i class="fa-solid fa-user" :class="{ dark: changeDarkMode }"></i>
<input
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.namePlaceholder')"
v-model="dName"
ref="name"
/>
</div>
<div class="wrapper__info">
<i class="fa-solid fa-lock" :class="{ dark: changeDarkMode }"></i>
<input
type="password"
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.pwPlaceholder')"
v-model="dPassword"
ref="pw"
/>
</div>
<div class="wrapper__info">
<i class="fa-solid fa-check" :class="{ dark: changeDarkMode }"></i>
<input
type="password"
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.pwConfirmPlaceholder')"
v-model="dPasswordOk"
ref="pwOk"
@input="inputPwOk"
/>
<div class="error" :class="{ on: passwordMismatch }">
{{ $t("[3].joinSection.errorMismatch") }}
</div>
</div>
<div class="divideLine" :class="{ dark: changeDarkMode }"></div>
<button class="registerBtn" type="submit">{{ $t("[3].join") }}</button>
</div>
</form>
</div>
</template>
- <form @submit.prevent="fnRegisterUser">: 폼 제출 이벤트를 가로채고 fnRegisterUser 메서드를 호출합니다.
- 각 입력 필드 (<input>)는 v-model을 사용하여 데이터 바인딩을 합니다. dEmail, dName, dPassword, dPasswordOk가 각각 이메일, 이름, 비밀번호, 비밀번호 확인을 저장합니다.
- <button type="submit">: 제출 버튼으로, 클릭 시 폼이 제출됩니다.
회원가입 폼의 로직 구현
다음은 회원가입 폼의 JavaScript 로직입니다.
<script>
export default {
data() {
return {
dEmail: "",
dName: "",
dPassword: "",
dPasswordOk: "",
existEmailClass: false,
isValidEmail: true,
passwordMismatch: false,
existEmail: [],
};
},
created() {
this.existEmail = this.$store.getters.fnGetOuser; // 기존 사용자 목록 가져오기
},
computed: {
emailClass() {
return !this.isValidEmail && this.dEmail !== ""; // 이메일 유효성 검사
},
changeDarkMode() {
return this.$store.getters.fnGetDark; // 다크모드 상태 가져오기
},
},
methods: {
fnRegisterUser() {
// 회원가입 폼 검증
if (!this.dEmail) {
this.$refs.email.focus();
alert(this.$t("[3].joinSection.emailPlaceholder"));
return;
} else if (!this.isValidEmail) {
this.$refs.email.focus();
alert(this.$t("[3].joinSection.errorFormatEmail"));
return;
} else if (!this.dName) {
this.$refs.name.focus();
alert(this.$t("[3].joinSection.namePlaceholder"));
return;
} else if (!this.dPassword) {
this.$refs.pw.focus();
alert(this.$t("[3].joinSection.pwPlaceholder"));
return;
} else if (!this.dPasswordOk) {
this.$refs.pwOk.focus();
alert(this.$t("[3].joinSection.pwConfirmPlaceholder"));
return;
} else if (this.dPassword !== this.dPasswordOk) {
this.$refs.pwOk.focus();
alert(this.$t("[3].joinSection.errorMismatch"));
return;
}
// 회원가입 처리
this.$store.commit("fnRegisterUser", {
email: this.dEmail,
name: this.dName,
pw: this.dPassword,
});
if (this.$store.getters.fnGetMessage) {
// 가입 성공
this.dEmail = "";
this.dName = "";
this.dPassword = "";
this.dPasswordOk = "";
this.$router.push("/loginView");
alert(this.$t("[3].joinSection.joinDone"));
} else {
// 이메일 중복 오류
alert(this.$t("[3].joinSection.errorExistEmail"));
}
},
inputEmail() {
this.isValidEmail = this.dEmail.includes("@"); // 이메일 유효성 검사
this.existEmailClass = this.existEmail.some(item => item.email === this.dEmail); // 이메일 중복 검사
},
inputPwOk() {
this.passwordMismatch = this.dPassword !== this.dPasswordOk; // 비밀번호 일치 검사
},
},
};
</script>
- data(): 컴포넌트의 데이터 속성을 정의합니다.
- created(): 컴포넌트가 생성될 때 호출되며, 스토어에서 기존 이메일 목록을 가져옵니다
- .computed: 계산된 속성으로, 이메일 유효성 검사와 다크 모드 전환을 처리합니다.
- methods: 회원가입과 관련된 메서드들입니다.
- fnRegisterUser(): 폼 검증을 하고, 스토어에 fnRegisterUser 커밋을 호출하여 회원가입을 처리합니다
- .inputEmail(): 이메일 입력 시 유효성을 검사하고, 이미 존재하는 이메일인지 확인합니다.
- inputPwOk(): 비밀번호와 비밀번호 확인이 일치하는지 확인합니다.
Store에 회원가입 로직 추가
// 회원가입 시 사용자가 입력한 이메일, 이름, 비밀번호를 검증하고, 스토어에 저장
fnRegisterUser(state, payload) {
const { email, name, pw } = payload;
const findEmail = state.oUser.some(item => item.email === email);
if (!findEmail) {
state.oUser.push({ email, name, pw });
state.message = true;
} else {
state.message = false;
}
},
01
Part1. 로그인
로그인 폼 구현
<template>
<div class="login__section">
<form @submit.prevent="fnLogin">
<div class="wrapper">
<div class="wrapper__title" :class="{ dark: changeDarkMode }">
{{ $t("[3].joinSection.RLogin") }}
</div>
<div class="wrapper__info">
<i class="fa-solid fa-envelope" :class="{ dark: changeDarkMode }"></i>
<input
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.emailPlaceholder')"
v-model="dEmail"
ref="email"
/>
</div>
<div class="wrapper__info">
<i class="fa-solid fa-lock" :class="{ dark: changeDarkMode }"></i>
<input
type="password"
class="wrapper__input"
:class="{ dark: changeDarkMode }"
:placeholder="$t('[3].joinSection.pwPlaceholder')"
v-model="dPassword"
ref="pw"
/>
</div>
<div class="divideLine" :class="{ dark: changeDarkMode }"></div>
<button class="registerBtn" type="submit">{{ $t("[3].login") }}</button>
</div>
</form>
</div>
</template>
로그인 폼의 로직 구현
<script>
export default {
data() {
return {
dEmail: "",
dPassword: "",
};
},
methods: {
fnLogin() {
if (!this.dEmail) {
alert(this.$t("[3].joinSection.emailPlaceholder"));
this.$refs.email.focus();
return;
} else if (!this.dPassword) {
alert(this.$t("[3].joinSection.pwPlaceholder"));
this.$refs.pw.focus();
return;
}
this.$store.commit("fnLogin", {
email: this.dEmail,
pw: this.dPassword,
});
if (this.$store.getters.fnGetLogined) {
this.$router.push(this.$store.getters.fnGetPrevPath || "/");
this.$store.commit("savePrevPath", null); // 이전 경로 초기화
} else {
alert(this.$t("[3].joinSection.notMember"));
}
},
},
computed: {
changeDarkMode() {
return this.$store.getters.fnGetDark;
},
},
};
</script>
- data(): 컴포넌트의 데이터 속성을 정의합니다.
- methods: 로그인과 관련된 메서드입니다.
- fnLogin(): 폼 검증을 하고, 스토어에 fnLogin 커밋을 호출하여 로그인을 처리합니다. 로그인 성공 시 이전 경로 또는 홈으로 이동합니다. 로컬 스토리지에 사용자 정보를 저장합니다.
Store에 로그인 로직 추가
다음은 로그인과 관련된 Vuex Store 코드입니다
export default {
state: {
oUser: [
{ email: "manager@gmail.com", name: "매니저", pw: "1234" },
{ email: "user1@gmail.com", name: "user1", pw: "5678" },
],
message: false,
logined: null,
prevPath: null,
},
mutations: {
fnRegisterUser(state, payload) {
const { email, name, pw } = payload;
const findEmail = state.oUser.some(item => item.email === email);
if (!findEmail) {
state.oUser.push({ email, name, pw });
state.message = true;
} else {
state.message = false;
}
},
// 로그인 관련 추가
fnLogin(state, payload) {
const { email, pw } = payload;
const user = state.oUser.find(item => item.email === email && item.pw === pw);
if (user) {
state.logined = user;
localStorage.setItem("loginedUser", JSON.stringify(user)); // 로컬 스토리지에 로그인 정보 저장
} else {
state.logined = null;
}
},
savePrevPath(state, payload) {
state.prevPath = payload;
},
fnLogout(state) {
state.logined = null;
localStorage.removeItem("loginedUser"); // 로컬 스토리지에서 로그인 정보 삭제
},
},
getters: {
fnGetOuser: (state) => state.oUser,
fnGetMessage: (state) => state.message,
fnGetLogined: (state) => state.logined,
fnGetPrevPath: (state) => state.prevPath,
},
};
이제 회원가입과 로그인을 구현했습니다. 회원가입 시 사용자가 입력한 이메일, 이름, 비밀번호를 검증하고, 스토어에 저장합니다. 로그인 시 이메일과 비밀번호를 검증하고, 로그인 성공 시 사용자 정보를 로컬 스토리지에 저장합니다.