지출 내역 APP (개인 프로젝트)
지출 내역 리스트 기능 추가하기 : 2
고래고래00
2024. 6. 13. 11:47
기존 지출 내역 리스트에 기능 추가하기
구현 순서
- 회원가입, 로그인 페이지 및 폼의 UI 생성
- jwt 인증서버를 사용한 회원가입, 로그인 기능 추가 및 인증 상태 관리
- 내비게이션 바 생성 및 라우터 설정
- 프로필 수정 페이지 생성 및 프로필 수정 기능 추가
- json-server와 Tanstack Query를 사용해 지출 CRUD 구현
- 이후 디테일한 부분 및 선택 구현 사항 다루기
2. jwt 인증서버를 사용한 회원가입, 로그인 기능 추가 및 인증 상태 관리
제공되는 jwt(토큰을 이용한 인증 방식) 인증서버를 사용해서 회원가입, 로그인 기능 추가
제공된 API 명세서를 보고 Method 및 URL PATH 등을 설정
현재 로그인 상태인지 로그아웃 상태인지를 확인하기 위해 로그인 상태 및 로그인한 유저의 정보를 Redux로 관리
src/redux/slices/auth.slice.js
더보기
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
isLogin: localStorage.getItem("accessToken") ? true : false,
userInfo: null,
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
login: (state, action) => { // 로그인시 accessToken을 로컬스토리지에 저장
state.isLogin = true;
localStorage.setItem("accessToken", action.payload);
},
logout: (state) => { // 로그아웃시 accessToken을 로컬스토리지에서 삭제
state.isLogin = false;
localStorage.removeItem("accessToken");
state.userInfo = null; // 로그아웃시 담아놨던 유저 정보를 제거
},
setUserInfo: (state, action) => {
state.userInfo = action.payload; // 로그인시 현재 유저의 id, 닉네임과 같은 정보를 담음
},
},
});
export const { login, logout, setUserInfo } = authSlice.actions;
export default authSlice.reducer;
모든 요청은 axios를 이용해야하기 때문에 axios custom instance 생성
src/api/axios.js
더보기
export const authApi = axios.create({
baseURL: 제공된 서버 URL
});
회원가입 기능
required 속성을 넣어도 공백을 넣으면 통과가 되기때문에 공백 또한 필터를 하기 위해 trim을 이용해 한번 더 검사
비밀번호와 비밀번호 확인의 내용이 다른 것 또한 필터링
더보기
const handleSubmitSignUpForm = async (event) => {
event.preventDefault();
setIsIdValid(true);
setIsPasswordValid(true);
setIsPasswordComfirmValid(true);
setIsNicknameValid(true);
// 유효성 검사
if (!id.trim()) return setIsIdValid(false);
if (!password.trim()) return setIsPasswordValid(false);
if (password !== passwordConfirm) return setIsPasswordComfirmValid(false);
if (!nickname.trim()) return setIsNicknameValid(false);
// 회원가입 로직
// 제공된 API 서버의 path로 새로운 유저 데이터 추가(POST) 요청
try {
const response = await authApi.post("/register", {
id,
password,
nickname,
})
const { data } = response;
if (data.success) { // 요청(유저 추가)성공시 알림 및 로그인 페이지으로 이동
alert("회원가입 성공!");
navigate("/login");
} else { // 요청 실패시 알림
alert("Signup failed");
}
} catch (error) {
console.error("Signup error:", error);
alert("Signup failed");
}
};
로그인 기능
회원가입과 유사
더보기
const handleSubmiLoginForm = async (event) => {
event.preventDefault();
setIsIdValid(true);
setIsPasswordValid(true);
if (!id.trim()) return setIsIdValid(false);
if (!password.trim()) return setIsPasswordValid(false);
try {
const response = await authApi.post("/login",
{
id,
password,
}
);
const data = response.data;
if (data.success) {
dispatch(login(data.accessToken));
alert("로그인 성공!");
} else {
alert("Login failed");
}
} catch (error) {
console.error("Login error:", error);
alert("Login failed");
}
};
결과
회원가입