회원 관리 기능 구현하기

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,
  },
};

 

이제 회원가입과 로그인을 구현했습니다. 회원가입 시 사용자가 입력한 이메일, 이름, 비밀번호를 검증하고, 스토어에 저장합니다. 로그인 시 이메일과 비밀번호를 검증하고, 로그인 성공 시 사용자 정보를 로컬 스토리지에 저장합니다.

 

로그인

 

 

 

로그인 전
로그인 후