스프링 부트 + vue.js 로 게시판 만들기 - 2

2023. 4. 27. 19:53초기 과업/BackEnd

작성자알 수 없는 사용자

728x90
반응형

 

안녕하세요. 기깔나는 사람들에서 백엔드를 맡고있는 박영광입니다.

 

이번 시간에는 저번 시간에 API를 모두 개발했으니 vue.js로 프론트엔드를 구현해보려고 합니다.

우선 로그인, 회원가입 화면만 먼저 구성하도록 할게요.

 

제가 프론트엔드는 거의 문외한이다 보니, 자세한 설명 보다는 어떤 라이브러리를 사용했고, 화면 구성을 어떻게 했는지만 간단하게 살펴보도록 하겠습니다.

 


페이지 헤더

<template>
  <div id="app">
    <page-header>
      <router-view/>
    </page-header>
  </div>
</template>

<script>
import PageHeader from "@/components/PageHeader.vue";

export default {
  name: 'App',
  components: {
    PageHeader
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

App.vue  코드입니다. 모든 페이지에 고정적으로 홈, 로그인, 회원가입 등의 페이지들로 바로 이동할 수 있도록 헤더를 만들어서 App.vue에 추가해주었어요.

 

<template>
  <header>
    <div id="nav">
      <router-link to="/">
        <v-btn variant="text">Home</v-btn>
      </router-link>
      <template v-if="isLoggedIn">
        <v-btn variant="text">{{ userName }}님 환영합니다</v-btn>
        <v-btn variant="text" @click="logout">로그아웃</v-btn>
      </template>
      <template v-else>
        <router-link to="/signUp">
          <v-btn variant="text">회원가입</v-btn>
        </router-link>
        <router-link to="/signIn">
          <v-btn variant="text">로그인</v-btn>
        </router-link>
      </template>
      <router-view></router-view>
    </div>
  </header>
  <hr/>
</template>

<script>
export default {
  computed: {
    isLoggedIn() {
      alert('isLoggedIn');
      alert(this.$store.state.isLogin);
      return this.$store.state.isLogin;
    },
    userName() {
      return this.$store.state.userName;
    }
  },
  methods: {
    logout() {
      // 로그아웃 처리
      this.$store.commit("logout");
    }
  }
};
</script>

<style scoped>

</style>

PageHeader.vue 코드 입니다. 여기서 라이브러리 몇 개 짚고 넘어가도록 할게요.

 

먼저 앞에 v- 가 붙어 있는 태그들을 확인할 수 있으실거에요. 이 태그는 Vuetify 라는 라이브러리를 사용해서 보다 화면의 요소들을 이쁘게 보이게 하려고 사용했어요. 너무 기본으로 하다보니까 가독성이 많이 떨어지더라구요. 어떻게 설치하고 사용하는 지는 공식 홈페이지에 잘 설명되어 있으니 보고 따라해보시면 좋을 것 같아요.

 

다음은 router인데요. 이름에서 유추할 수 있듯이 페이지 간의 이동을 위해 사용해주었어요!

 

마지막으로, store라는 것을 확인할 수 있는데요. 기본적으로 로그인 상태를 체크해주기 위해서 상태 관리를 해주는 라이브러리인 vuex를 사용해주었어요. vuex를 통해서 로그인 여부 같은 변수들을 설정해주고 전역적으로 위와 같이 관리할 수 있어요.

 


로그인, 회원가입 화면

<template>
  <div class="container">
    <h1>로그인</h1>
    <form>
      <div class="form-group">
        <v-text-field label="email" type="email" id="email" v-model="email" required>
        </v-text-field>
      </div>
      <div class="form-group">
        <v-text-field label="password" type="password" id="password" v-model="password" required>
        </v-text-field>
      </div>
      <v-btn type="submit" @click.prevent="submitForm">로그인</v-btn>
    </form>
  </div>
</template>

<script>
import axios from 'axios';
import router from "@/router";
import jwt_decode from 'jwt-decode';

export default {
  name :'signIn',
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    signIn() {
      const data = {
        email: this.email,
        password: this.password
      };
      axios.post('/api/members/signin', data)
          .then(response => {
            console.log(response.data);
            localStorage.setItem('accessToken', response.data.data.accessToken);

            const token = jwt_decode(response.data.data.accessToken);
            this.$store.commit("setIsLogin", true);
            this.$store.commit("setUserName", token.sub);

            localStorage.setItem('refreshToken', response.data.data.refreshToken);
            alert("로그인 완료");
            router.push('/');
          })
          .catch(error => {
            alert('에러 발생')
            console.log(error);
          });
    },
    submitForm() {
      this.emailError = '';
      this.passwordError = '';
      if (!this.email) {
        this.emailError = '이메일을 입력하세요.';
      }
      if (!this.password) {
        this.passwordError = '비밀번호를 입력하세요.';
      }

      if (!this.emailError && !this.passwordError) {
        this.signIn();
      }
    }
  }
}
</script>
<template>
  <div class="container">
    <h1>회원 가입</h1>
    <form>
      <div class="form-group">
        <v-text-field label="email" type="email" id="email" v-model="email" required>
        </v-text-field>
      </div>
      <div class="form-group">
        <v-text-field label="password" type="password" id="password" v-model="password" required>
        </v-text-field>
      </div>
      <v-btn type="submit" @click.prevent="submitForm">회원 가입</v-btn>
    </form>
  </div>
</template>

<script>
import axios from 'axios';
import router from "@/router";

export default {
  name :'signUp',
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    signUp() {
      const data = {
        email: this.email,
        password: this.password
      };
      axios.post('/api/members/signup', data)
          .then(response => {
            console.log(response.data);
            alert("회원 가입 완료");
            router.push('/');
          })
          .catch(error => {
            alert('에러 발생')
            console.log(error);
          });
    },
    submitForm() {
      this.emailError = '';
      this.passwordError = '';
      if (!this.email) {
        this.emailError = '이메일을 입력하세요.';
      }
      if (!this.password) {
        this.passwordError = '비밀번호를 입력하세요.';
      }

      if (!this.emailError && !this.passwordError) {
        this.signUp();
      }
    }
  }
}
</script>

 

로그인과 회원가입 vue코드입니다. 화면 구성은 거의 동일하게 해주었어요. 회원가입, 로그인에서는 axios를 사용해서 백엔드로 http 요청을 보내고 response를 받아오게 했어요. 로그인은 백엔드에서 jwtToken을 반환해주기 때문에 해당 토큰을 분석하는 라이브러리인 jwt-decode를 사용해서 해석하고, 그 안에 username을 vuex에 저장해주었어요. 그리고 accessToken 과 refreshToken은 localStorage에 저장해주었어요.


결과 화면

회원가입 화면
로그인 후 화면

위와 같이 성공적으로 구현된 것을 확인할 수 있어요.

 


회고 제목

화면 구성에는 재능도 없고, 흥미도 없어서 최소한의 화면 구성만 했다는 점 참고해주시길 바랍니다 :)

 

 


 

 

 

 

 

728x90
반응형