간단하게 해결했지만 너무 어렵게 생각했는지 좀 빙빙 돌려서 오래 걸렸다. 아래는 전체 코드가 아닌 해결 과정을 정리했다.
현재 코드에서는 유저 데이터만 저장이 되어 로그인이 백엔드에 연동은 되었지만, localstorage에 토큰은 저장이 되지 않는 상태였다.
import axios, { AxiosResponse } from 'axios';
import { axiosInstance } from '../axiosInstance';
import { useUser } from '../components/user/hooks/useUser';
import { User } from '../types/types';
interface UseAuth {
signin: (email: string, password: string) => Promise<void>;
signup: (email: string, password: string, nickname: string) => Promise<void>;
signout: () => void;
}
type UserResponse = { user: User };
type ErrorResponse = { message: string };
type AuthResponseType = UserResponse | ErrorResponse;
export function useAuth(): UseAuth {
const SERVER_ERROR = 'There was an error contacting the server.';
const { clearUser, updateUser } = useUser();
async function authServerCall(
urlEndpoint: string,
email: string,
password: string,
nickname?: string,
): Promise<void> {
try {
const { data, status }: AxiosResponse<AuthResponseType> =
await axiosInstance({
url: urlEndpoint,
method: 'POST',
data: { email, password, nickname },
headers: { 'Content-Type': 'application/json' },
});
if (status === 201) {
// eslint-disable-next-line no-alert
alert(`status code : ${status}! 회원가입 성공`);
return;
}
} catch (errorResponse) {
const status =
axios.isAxiosError(errorResponse) && errorResponse?.response?.status
? errorResponse?.response?.status
: SERVER_ERROR;
status === 409
? // eslint-disable-next-line no-alert
alert(`status code : ${status}! already a member!`)
: // eslint-disable-next-line no-alert
alert(`status code : ${status}!`);
}
}
type accessToken = string;
async function authLoginServerCall(
urlEndpoint: string,
email: string,
password: string,
): Promise<void> {
try {
const { data, status }: AxiosResponse<AuthResponseType, accessToken> =
await axiosInstance({
url: urlEndpoint,
method: 'POST',
data: { email, password },
headers: { 'Content-Type': 'application/json' },
});
if (status === 201 || status === 200) {
// eslint-disable-next-line no-alert
alert(`status code : ${status}! 로그인 성공`);
if ('user' in data) {
// update stored user data
updateUser(data.user);
}
// eslint-disable-next-line no-console
console.log('data', data);
// API 요청하는 콜마다 헤더에 accessToken 담아 보내도록 설정
// axios.defaults.headers.common[
// 'Authorization'
// ] = `Bearer ${accessToken}`;
// const user: User = { accessToken: token };
// setStoredUser({ data });
// setStoredUser(user);
}
// if ('user' in data && 'accessToken' in data.user) {
if ('user' in data && 'accessToken' in data.user) {
// eslint-disable-next-line no-console
console.log(data);
// update stored user data
updateUser(data.user);
}
} catch (errorResponse) {
const status =
axios.isAxiosError(errorResponse) && errorResponse?.response?.status
? errorResponse?.response?.status
: SERVER_ERROR;
status === 409
? // eslint-disable-next-line no-alert
alert(`status code : ${status}! already a member!`)
: // eslint-disable-next-line no-alert
alert(`status code : ${status}!`);
}
}
async function signin(email: string, password: string): Promise<void> {
authLoginServerCall('/members/signin', email, password);
// authServerCall('/members/signin', email, password);
}
async function signup(
email: string,
password: string,
nickname: string,
): Promise<void> {
authServerCall('/members/signup', email, password, nickname);
}
function signout(): void {
// clear user from stored user data
clearUser();
// eslint-disable-next-line no-alert
alert(`logged out!`);
}
return {
signin,
signup,
signout,
};
}
문제가 되는 부분은 이거였다. 팀원 분이 작성하신 코드인데, 타입 문제도 많고 무엇보다 안 돌아간다. jwt 인증방식이고 뭐고 잘 몰랐던 상태에서 보니 나는 이게 타입 문제만 해결되면 맞는 코드이지 않을까? 싶어서 좀 파봤지만 이게 어떤 식으로 돌아가는지 도저히 이해도 안 되고 에러도 해결이 안됐다. 그래서 localstorage에 토큰을 어떻게 저장하고 그걸 로그인 할 때만 빼올 수 있을까? 고민을 많이했다.
// axios.defaults.headers.common[
// 'Authorization'
// ] = `Bearer ${accessToken}`;
// const user: User = { accessToken: token };
// setStoredUser({ data });
// setStoredUser(user);
}
토큰 관련해서 어떻게 처리해야하는지 받은 슬랙
처음에는 localstorage.setItem()을 사용해서 로그인 시에 토큰을 가져오려고 시도했다.
localStorage.setItem('accessToken', data);
근데 이렇게하면 타입이 안 맞는다 ㅎㅎ..
localStorage.setItem('accessToken', JSON.stringify(data));
// eslint-disable-next-line no-console
console.log(localStorage);
JSON.stringify를 사용해서 넣어줬다. 그리고 콘솔 창을 확인했는데 아무것도 안 떴다 ^^ 지금 생각해보면 당연하다 아무것도 안 했는데 어떻게 받아옴?
지금 함수가 서버콜이랑 서버로그인콜로 나뉘어져 있는데, 서버 콜쪽 header에 authorization을 추가해줬다.
Promise<void> {
try {
const { data, status }: AxiosResponse<AuthResponseType> =
await axiosInstance({
url: urlEndpoint,
method: 'POST',
data: { email, password, nickname },
headers: { 'Content-Type': 'application/json'
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,},
});
이렇게 코드를 작성하면 회원가입을 완료했을 때 localstorage에 token을 생성하고, 로그인할 때 생성했던 토큰을 return한다.
그냥 간단한 구현인데 TIL써야하니까 썼다