Syw.Frontend

๐Ÿงฉ Vue 2๋กœ ๋ฐฐ์šฐ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ๊ธฐ์ดˆ

1๋‹จ๊ณ„. Vue 2 + Express + Axios ์ธ์ฆ ๊ธฐ๋ฐ˜ ํˆฌ๋‘์•ฑ ๋งŒ๋“ค๊ธฐ

1-22. Vuex์— ๋กœ๊ทธ์ธ API ํ˜ธ์ถœ ๋กœ์ง(action)์œผ๋กœ ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ

๐ŸŽฏ ํ•™์Šต ๋ชฉํ‘œ

  • Vuex auth ๋ชจ๋“ˆ์— login action์„ ์ถ”๊ฐ€ํ•œ๋‹ค
  • ์ปดํฌ๋„ŒํŠธ(Login.vue)์—์„œ๋Š” this.$store.dispatch()๋งŒ ํ˜ธ์ถœํ•˜๋„๋ก ๊ฐ„์†Œํ™”
  • API ์‘๋‹ต ์ฒ˜๋ฆฌ, ์ƒํƒœ ๋ณ€๊ฒฝ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋“ฑ์„ ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ

โœ… 1๋‹จ๊ณ„: auth.js ๋ชจ๋“ˆ์— actions ์ถ”๊ฐ€

// store/modules/auth.js
import axios from 'axios';
import { isTokenExpired } from '@/utils/jwt';

const state = {
  isLoggedIn: false,
  username: localStorage.getItem('username') || '',
};

const mutations = {
  setToken(state, token) {
    localStorage.setItem('token', token);
    state.isLoggedIn = true;
  },
  setUsername(state, name) {
    localStorage.setItem('username', name);
    state.username = name;
  },
  logout(state) {
    localStorage.removeItem('token');
    localStorage.removeItem('username');
    state.isLoggedIn = false;
    state.username = '';
  },
  syncLoginState(state) {
    const token = localStorage.getItem('token');
    const name = localStorage.getItem('username');

    if (!token || isTokenExpired(token)) {
      localStorage.removeItem('token');
      localStorage.removeItem('username');
      state.isLoggedIn = false;
      state.username = '';
    } else {
      state.isLoggedIn = true;
      state.username = name || '';
    }
  },
};

const actions = {
  async login({ commit }, { username, password }) {
    try {
      const res = await axios.post('/api/auth/login', {
        username,
        password,
      });

      commit('setToken', res.data.token);
      commit('setUsername', res.data.username);

      return { success: true };
    } catch (error) {
      return {
        success: false,
        message: error.response?.data?.message || '๋กœ๊ทธ์ธ ์‹คํŒจ',
      };
    }
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
};

โœ… 2๋‹จ๊ณ„: Login.vue์—์„œ Vuex action ์‚ฌ์šฉ

๐Ÿ”ง ๋ณ€๊ฒฝ ์ „

const res = await axios.post('/api/auth/login', { ... });
localStorage.setItem('token', res.data.token);
localStorage.setItem('username', res.data.username);

๐Ÿ”ง ๋ณ€๊ฒฝ ํ›„

const result = await this.$store.dispatch('auth/login', {
  username: this.username,
  password: this.password,
});
if (result.success) {
  this.$router.push('/todos');
} else {
  alert(result.message);
}

โœ… 3๋‹จ๊ณ„: ์ตœ์ข… Login.vue ์ฝ”๋“œ ์˜ˆ์‹œ

<script>
export default {
  name: 'LoginPage',
  data() {
    return { username: '', password: '' };
  },
  methods: {
    async handleLogin() {
      try {
        const result = await this.$store.dispatch('auth/login', {
          username: this.username,
          password: this.password,
        });
        if (result.success) {
          this.$router.push('/todos');
        } else {
          alert(result.message);
        }
      } catch (e) {
        alert('๋กœ๊ทธ์ธ ์‹คํŒจ');
      }
    },
  },
};
</script>

๐Ÿ“ฆ ์š”์•ฝ

์ด ๊ฐ•์˜์—์„œ๋Š” ๋กœ๊ทธ์ธ API ํ˜ธ์ถœ๊ณผ ์ƒํƒœ ์ฒ˜๋ฆฌ๋ฅผ Vuex auth ๋ชจ๋“ˆ์˜ actions๋กœ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์—ญํ• ์ด ๋ถ„๋ฆฌ๋œ ๊ตฌ์กฐ๋กœ ๊ฐœ์„ ๋˜์—ˆ๋‹ค.

GitHub - heroyooi/vue2-app at ch22

๐Ÿ’ฌ ๋Œ“๊ธ€

    โ€ป ๋กœ๊ทธ์ธ ํ›„ ๋Œ“๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.