Syw.Frontend

🧩 Vue 2로 배우는 프론트엔드 기초

1단계. Vue 2 + Express + Axios 인증 기반 투두앱 만들기

1-23. Vuex에 회원가입 API 호출 로직(action)으로 리팩토링하기

✅ 1단계: Vuex auth 모듈에 register 액션 추가

📁 src/store/modules/auth.js 하단 actions 부분에 아래 코드 추가:

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 || '로그인 실패',
      };
    }
  },

  // 🔹 회원가입 액션 추가
  async register(_, { username, password }) {
    try {
      await axios.post('/api/auth/register', {
        username,
        password,
      });
      return { success: true };
    } catch (error) {
      return {
        success: false,
        message: error.response?.data?.message || '회원가입 실패',
      };
    }
  },
};

✅ 2단계: Register.vue에서 axios → store.dispatch 변경

📁 Register.vue <script> 수정:

export default {
  name: 'RegisterPage',
  data() {
    return { username: '', password: '' };
  },
  methods: {
    async handleRegister() {
      const result = await this.$store.dispatch('auth/register', {
        username: this.username,
        password: this.password,
      });

      if (result.success) {
        alert('회원가입 완료! 로그인 해주세요.');
        this.$router.push('/login');
      } else {
        alert(result.message);
      }
    },
  },
};

✅ 3단계: 회원가입 후 자동 로그인 처리

📦 auth.js 모듈의 register 액션을 아래처럼 수정합니다:

async register({ dispatch }, { username, password }) {
  try {
    await axios.post('/api/auth/register', { username, password });

    // 🔐 회원가입 성공 → 자동 로그인 실행
    return await dispatch('login', { username, password });
  } catch (error) {
    return {
      success: false,
      message: error.response?.data?.message || '회원가입 실패',
    };
  }
}

📌 Register.vue는 그대로 유지 가능합니다:

const result = await this.$store.dispatch('auth/register', {
  username: this.username,
  password: this.password,
});

if (result.success) {
  alert('회원가입 완료! 로그인 해주세요.');
  this.$router.push('/login');
} else {
  alert(result.message);
}

✅ 4단계: Axios 인터셉터로 토큰 자동 삽입 + 에러 통일 처리

📁 src/utils/axios.js 파일 생성

import axios from 'axios';

// ✅ 인스턴스 생성
const instance = axios.create({
  baseURL: '', // ✅ '/api' 제거
  timeout: 5000,
});

// ✅ 요청 인터셉터: 토큰 자동 삽입
instance.interceptors.request.use((config) => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// ✅ 응답 인터셉터: 공통 에러 처리
instance.interceptors.response.use(
  (res) => res,
  (err) => {
    if (err.response?.status === 401) {
      alert('로그인 정보가 만료되었습니다.');
      localStorage.removeItem('token');
      localStorage.removeItem('username');
      location.href = '/login';
    } else if (err.response?.data?.message) {
      alert(err.response.data.message);
    } else {
      alert('알 수 없는 오류가 발생했습니다.');
    }
    return Promise.reject(err);
  }
);

export default instance;

🔁 기존 axios import 전체 교체

모든 axios 사용처에서:

// 기존
import axios from 'axios';

// 변경
import axios from '@/utils/axios';

📁 src/components/TodoApp.vue 파일 수정

✏️ 예시 변경 전:

const res = await axios.get(API_URL, this.authHeader());

✅ 변경 후:

const res = await axios.get(API_URL);

✅ 전체적으로 수정이 필요한 부분

- const res = await axios.get(API_URL, this.authHeader());
+ const res = await axios.get(API_URL);

- const res = await axios.post(API_URL, { title, completed: false }, this.authHeader());
+ const res = await axios.post(API_URL, { title, completed: false });

- await axios.delete(`${API_URL}/${id}`, this.authHeader());
+ await axios.delete(`${API_URL}/${id}`);

- await axios.put(`${API_URL}/${id}`, { title }, this.authHeader());
+ await axios.put(`${API_URL}/${id}`, { title });

- await axios.put(`${API_URL}/${id}`, { completed: updated.completed }, this.authHeader());
+ await axios.put(`${API_URL}/${id}`, { completed: updated.completed });

✅ 요약

  • authHeader()는 이제 필요 없음 → 삭제해도 됩니다
  • axios 요청 시 헤더 자동으로 들어감 → 인터셉터에서 처리 완료
기능 구현 여부
회원가입 성공 시 자동 로그인
토큰 자동 헤더 삽입 (Authorization)
에러 메시지 통일 (error.message)
유지보수 및 확장성 ✅ 향상

FE 저장소

GitHub - heroyooi/vue2-app at ch23

💬 댓글

    ※ 로그인 후 댓글을 작성할 수 있습니다.