Skip to content

Commit e5bbacb

Browse files
authored
Merge pull request #59 from codeit9-temporary/feature/AuthStore
Feat: AuthStore 구현
2 parents bd01a01 + 778c091 commit e5bbacb

File tree

6 files changed

+113
-6
lines changed

6 files changed

+113
-6
lines changed

components/HeaderMenu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import Star from "@/public/icons/star.png";
44
import Link from "next/link";
55
import SubmitButton from "./SubMitButton";
66
import { useRouter } from "next/router";
7+
import useAuthStore from "@/store/useAuthStore";
78

89
const HeaderMenu = () => {
9-
const isLoggedIn = false;
10+
const { user, isLoggedIn } = useAuthStore();
1011
const router = useRouter();
1112

1213
return (
@@ -40,8 +41,7 @@ const HeaderMenu = () => {
4041
</Link>
4142
<div className="flex items-center gap-[6px] text-[14px] leading-[16.71px] font-normal">
4243
<Image src={Profile} width={28} height={28} alt="프로필" />
43-
{/* 임시 유저 네임 */}
44-
<span className="hidden md:block lg:block">전상민</span>
44+
<span className="hidden md:block lg:block">{user?.name}</span>
4545
</div>
4646
</div>
4747
)}

hooks/useForm.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useState, ChangeEvent, FormEvent } from "react";
22
import { useRouter } from "next/router";
33
import { postSignIn, postSignUp } from "@/lib/api/auth";
4+
import useAuthStore from "@/store/useAuthStore";
45
import { TbWashDryP } from "react-icons/tb";
56

67
interface FormValues {
@@ -21,6 +22,7 @@ const useForm = (isSignUp = false) => {
2122
const [values, setValues] = useState<FormValues>(INITIAL_VALUES);
2223
const [errors, setErrors] = useState<FormValues>(INITIAL_VALUES);
2324
const router = useRouter();
25+
const { login } = useAuthStore();
2426

2527
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
2628
const { name, value } = e.target;
@@ -92,7 +94,7 @@ const useForm = (isSignUp = false) => {
9294
alert("회원가입 실패: 이메일 또는 비밀번호를 확인해주세요.");
9395
}
9496
} else {
95-
const data = await postSignIn({ email, password });
97+
const data = await login({ email, password });
9698

9799
if (data) {
98100
router.push("/");

lib/api/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axiosInstance, { proxy } from "./axiosInstanceApi";
22

3-
interface signInProps {
3+
export interface signInProps {
44
email: string;
55
password: string;
66
}
@@ -9,7 +9,7 @@ interface signUpProps extends signInProps {
99
name: string;
1010
}
1111

12-
interface easySignInProps {
12+
export interface easySignInProps {
1313
token: string;
1414
redirectUri: string;
1515
}

pages/api/users/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { NextApiRequest, NextApiResponse } from "next";
2+
import { parse } from "cookie";
3+
import axiosInstance from "@/lib/api/axiosInstanceApi";
4+
5+
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
6+
const cookies = parse(req.headers.cookie || "");
7+
const accessToken = cookies.accessToken;
8+
9+
switch (req.method) {
10+
case "GET":
11+
// 현재 유저 조회
12+
try {
13+
const response = await axiosInstance.get(`/users`, {
14+
headers: { Authorization: `Bearer ${accessToken}` },
15+
});
16+
return res.status(200).json(response.data);
17+
} catch (err) {
18+
console.error(err);
19+
return res.status(500).json({ message: "프로필 조회에 실패했습니다." });
20+
}
21+
22+
default:
23+
res.setHeader("Allow", ["GET"]);
24+
return res.status(405).end(`메서드 ${req.method}는 허용되지 않습니다.`);
25+
}
26+
};
27+
28+
export default handler;

store/useAuthStore.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { create } from "zustand";
2+
import { persist } from "zustand/middleware";
3+
import { User } from "@/types/AuthTypes";
4+
import {
5+
postSignIn,
6+
signInProps,
7+
easySignInProps,
8+
postEasySignIn,
9+
} from "@/lib/api/auth";
10+
import { getUserInfo } from "@/lib/api/user";
11+
12+
interface AuthStore {
13+
user: User | null;
14+
isLoggedIn: boolean;
15+
login: (body: signInProps) => Promise<boolean>;
16+
SNSLogin: (
17+
provider: "google" | "kakao",
18+
body: easySignInProps
19+
) => Promise<boolean>;
20+
logout: () => void;
21+
}
22+
23+
const useAuthStore = create<AuthStore>()(
24+
persist(
25+
(set) => ({
26+
user: null,
27+
isLoggedIn: false,
28+
29+
login: async (body) => {
30+
try {
31+
const { email, password } = body;
32+
const response = await postSignIn({ email, password });
33+
if (response) {
34+
const userInfo = await getUserInfo();
35+
if (userInfo) {
36+
set({ isLoggedIn: true, user: userInfo });
37+
return true;
38+
}
39+
}
40+
} catch (error) {
41+
console.error("로그인 중 에러가 발생했습니다", error);
42+
}
43+
return false;
44+
},
45+
46+
SNSLogin: async (provider, body) => {
47+
try {
48+
const response = await postEasySignIn(provider, body);
49+
if (response) {
50+
const userInfo = await getUserInfo();
51+
if (userInfo) {
52+
set({ isLoggedIn: true, user: userInfo });
53+
return true;
54+
}
55+
}
56+
} catch (error) {
57+
console.error("소셜 로그인 중 에러가 발생했습니다.", error);
58+
}
59+
return false;
60+
},
61+
62+
logout: () => set({ user: null, isLoggedIn: false }),
63+
}),
64+
{
65+
name: "auth-storage",
66+
}
67+
)
68+
);
69+
70+
export default useAuthStore;

types/AuthTypes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface User {
2+
id: number;
3+
name: string;
4+
imageSource: string;
5+
email: string;
6+
createdAt: string;
7+
}

0 commit comments

Comments
 (0)