Skip to content

Commit 722eb03

Browse files
committed
feat: 리프레시 토큰만 쿠키 나머지 정보 로컬 스토리지에 저장
1 parent 88b977f commit 722eb03

File tree

6 files changed

+64
-70
lines changed

6 files changed

+64
-70
lines changed

app/components/common/Dialog-new/Dialog.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,4 @@ const Dialog = forwardRef<HTMLFormElement, DialogProps>((props) => {
124124
);
125125
});
126126

127-
Dialog.defaultProps = {
128-
type: "",
129-
};
130-
131127
export default Dialog;

app/components/common/Hint-Dialog-new/Dialog.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,4 @@ const Dialog = forwardRef<HTMLFormElement, DialogProps>((props) => {
9191
);
9292
});
9393

94-
Dialog.defaultProps = {
95-
type: "",
96-
};
97-
9894
export default Dialog;

app/hooks/useClickOutside.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useEffect, RefObject } from "react";
99
* @param {boolean} ignoreSiblings - 형제 요소 클릭 시에도 닫힐지 여부
1010
*/
1111
function useClickOutside(
12-
ref: RefObject<HTMLElement | HTMLElement[]>,
12+
ref: React.RefObject<HTMLElement | HTMLElement[] | HTMLFormElement | null>,
1313
handler: (event: MouseEvent) => void,
1414
isActive = true,
1515
targetIndex = 0,

app/signup/CodeInput.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,29 @@ interface Props {
1313

1414
export default function CodeInput(props: Props) {
1515
const { disabled, numbers, setNumbers } = props;
16-
const inputRefs = useRef(Array(6).fill(null)); // 6개의 ref를 저장할 배열
16+
const inputRefs = useRef<(HTMLInputElement | null)[]>(
17+
Array.from({ length: 6 }, () => null)
18+
);
1719

1820
const { mutateAsync: postVerification, isError = false } =
1921
usePostVerification();
2022
const signUpState = useSignUpValue();
2123

2224
const handleInputChange = (index: number, value: string) => {
23-
// 입력값이 숫자가 아니거나 길이가 1을 넘어가면 입력을 막음
2425
if (!/^\d$/.test(value)) return;
2526

26-
const newNumbers = [...numbers]; // 기존 숫자 배열 복사
27-
newNumbers[index] = value; // 해당 인덱스의 값을 업데이트
28-
setNumbers(newNumbers); // 업데이트된 배열을 상태로 설정
27+
const newNumbers = [...numbers];
28+
newNumbers[index] = value;
29+
setNumbers(newNumbers);
2930

30-
// 다음 인풋 필드로 포커스 이동
3131
if (value !== "" && index < 5) {
32-
inputRefs.current[index + 1].focus();
32+
inputRefs.current[index + 1]?.focus();
3333
}
3434
};
3535

3636
useEffect(() => {
3737
setTimeout(() => {
38-
inputRefs.current[0].focus();
38+
inputRefs.current[0]?.focus();
3939
}, 1000);
4040
}, []);
4141

@@ -47,13 +47,12 @@ export default function CodeInput(props: Props) {
4747
if (isError) {
4848
setTimeout(() => {
4949
setNumbers(Array(6).fill(""));
50-
inputRefs.current[0].focus();
50+
inputRefs.current[0]?.focus();
5151
}, 1000);
5252
}
5353
}
5454
}, [numbers, isError]);
5555

56-
// 입력값을 삭제하는 함수
5756
const handleInputDelete = (
5857
index: number,
5958
e: React.KeyboardEvent<HTMLInputElement>
@@ -63,9 +62,8 @@ export default function CodeInput(props: Props) {
6362
newNumbers[index] = "";
6463
setNumbers(newNumbers);
6564

66-
// 이전 인풋 필드로 포커스 이동
6765
if (index > 0) {
68-
inputRefs.current[index - 1].focus();
66+
inputRefs.current[index - 1]?.focus();
6967
}
7068
}
7169
};
@@ -79,9 +77,11 @@ export default function CodeInput(props: Props) {
7977
value={number}
8078
error={isError && numbers.join("").length === 0}
8179
onChange={(e) => handleInputChange(index, e.target.value)}
82-
onKeyDown={(e) => handleInputDelete(index, e)} // 삭제 이벤트 처리
83-
maxLength={1} // 한 글자만 입력할 수 있도록 설정
84-
ref={(input) => (inputRefs.current[index] = input)} // ref를 배열에 저장
80+
onKeyDown={(e) => handleInputDelete(index, e)}
81+
maxLength={1}
82+
ref={(input) => {
83+
inputRefs.current[index] = input;
84+
}}
8585
disabled={disabled}
8686
inputMode="numeric"
8787
/>

app/utils/storageUtil.ts

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import Cookies from "js-cookie";
2+
13
const ACCESS_TOKEN = "accessToken";
24
const REFRESH_TOKEN = "refreshToken";
35
const SHOP_NAME = "shopName";
46
const ADMIN_CODE = "adminCode";
57
const STATUS = "status";
68
const THEME_ID = "themeId";
79
const ACCESS_TOKEN_EXPIRES_IN = "accessTokenExpiresIn";
8-
910
interface LoginInfo {
1011
accessToken: string;
1112
shopName: string;
@@ -14,35 +15,45 @@ interface LoginInfo {
1415
refreshToken: string;
1516
}
1617

17-
const setStorage = (storage: Storage, key: string, value: any) => {
18+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
19+
export const setLocalStorage = (key: string, value: any) => {
1820
if (typeof window !== "undefined") {
19-
if (!storage) return;
21+
const storage = window.localStorage;
22+
if (!storage) {
23+
return;
24+
}
2025
switch (typeof value) {
21-
case `string`:
26+
case `string`: {
2227
try {
2328
const stringifiedValue = JSON.stringify(value);
2429
storage.setItem(key, stringifiedValue);
2530
} catch (e) {
26-
console.error(`Failed to stringify value for key: ${key}`);
31+
console.error(`failed to stringify`);
2732
}
2833
break;
34+
}
2935
default:
3036
storage.setItem(key, value);
3137
}
3238
}
3339
};
3440

35-
const getStorage = (storage: Storage, key: string, defaultValue = null) => {
41+
export const getLocalStorage = (key: string, defaultValue = null) => {
3642
if (typeof window !== "undefined") {
37-
if (!storage) return null;
43+
const storage = window.localStorage;
44+
if (!storage) {
45+
return null;
46+
}
3847
return storage.getItem(key) ?? defaultValue;
3948
}
40-
return null;
4149
};
4250

43-
const removeStorageItem = (storage: Storage, key: string) => {
51+
export const removeLocalStorageItem = (key: string) => {
4452
if (typeof window !== "undefined") {
45-
if (!storage) return;
53+
const storage = window.localStorage;
54+
if (!storage) {
55+
return;
56+
}
4657
storage.removeItem(key);
4758
}
4859
};
@@ -56,59 +67,48 @@ export const setLoginInfo = (loginInfo: LoginInfo) => {
5667
accessTokenExpiresIn,
5768
} = loginInfo;
5869

59-
const sessionStorage = window.sessionStorage;
60-
setStorage(sessionStorage, ACCESS_TOKEN, accessToken);
61-
setStorage(sessionStorage, REFRESH_TOKEN, refreshToken);
62-
setStorage(sessionStorage, SHOP_NAME, shopName?.replaceAll(`"`, ""));
63-
setStorage(sessionStorage, ADMIN_CODE, adminCode?.replaceAll(`"`, ""));
64-
setStorage(sessionStorage, ACCESS_TOKEN_EXPIRES_IN, accessTokenExpiresIn);
65-
};
66-
67-
export const getLoginInfo = (): LoginInfo => {
68-
const sessionStorage = window.sessionStorage;
69-
return {
70-
accessToken: getStorage(sessionStorage, ACCESS_TOKEN) || "",
71-
refreshToken: getStorage(sessionStorage, REFRESH_TOKEN) || "",
72-
shopName: getStorage(sessionStorage, SHOP_NAME) || "",
73-
adminCode: getStorage(sessionStorage, ADMIN_CODE) || "",
74-
accessTokenExpiresIn:
75-
Number(getStorage(sessionStorage, ACCESS_TOKEN_EXPIRES_IN)) || 0,
76-
};
77-
};
78-
79-
export const removeLoginInfo = () => {
80-
const sessionStorage = window.sessionStorage;
81-
removeStorageItem(sessionStorage, ACCESS_TOKEN);
82-
removeStorageItem(sessionStorage, REFRESH_TOKEN);
83-
removeStorageItem(sessionStorage, SHOP_NAME);
84-
removeStorageItem(sessionStorage, ADMIN_CODE);
85-
removeStorageItem(sessionStorage, ACCESS_TOKEN_EXPIRES_IN);
70+
setLocalStorage(ACCESS_TOKEN, accessToken);
71+
Cookies.set(REFRESH_TOKEN, refreshToken, {
72+
secure: true,
73+
sameSite: "Strict",
74+
expires: 7,
75+
});
76+
setLocalStorage(SHOP_NAME, shopName?.replaceAll(`"`, ""));
77+
setLocalStorage(ADMIN_CODE, adminCode?.replaceAll(`"`, ""));
78+
setLocalStorage(ACCESS_TOKEN_EXPIRES_IN, accessTokenExpiresIn);
8679
};
8780

8881
export const setStatus = (status: string) => {
89-
setStorage(window.localStorage, STATUS, status);
82+
setLocalStorage(STATUS, status);
9083
};
9184

9285
export const setSelectedThemeId = (themeId: number) => {
93-
setStorage(window.localStorage, THEME_ID, themeId);
86+
setLocalStorage(THEME_ID, themeId);
9487
};
9588

96-
export const getStatus = () => getStorage(window.localStorage, STATUS);
97-
98-
export const getSelectedThemeId = () =>
99-
getStorage(window.localStorage, THEME_ID);
89+
export const getLoginInfo = (): LoginInfo => {
90+
return {
91+
accessToken: getLocalStorage(ACCESS_TOKEN) || "",
92+
refreshToken: Cookies.get(REFRESH_TOKEN) || "",
93+
shopName: getLocalStorage(SHOP_NAME) || "",
94+
adminCode: getLocalStorage(ADMIN_CODE) || "",
95+
accessTokenExpiresIn: Number(getLocalStorage(ACCESS_TOKEN_EXPIRES_IN)) || 0,
96+
};
97+
};
98+
export const getStatus = () => getLocalStorage(STATUS);
99+
export const getSelectedThemeId = () => getLocalStorage(THEME_ID);
100100

101101
export const removeAccessToken = () => {
102-
removeStorageItem(window.sessionStorage, ACCESS_TOKEN);
102+
removeLocalStorageItem(ACCESS_TOKEN);
103103
};
104104

105105
export const removeThemeId = () => {
106-
removeStorageItem(window.localStorage, THEME_ID);
106+
removeLocalStorageItem(THEME_ID);
107107
};
108108

109109
export const removeLocalStorageAll = () => {
110110
if (typeof window !== "undefined") {
111111
window.localStorage.clear();
112-
window.sessionStorage.clear();
112+
Cookies.remove(REFRESH_TOKEN);
113113
}
114114
};

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"devDependencies": {
4949
"@svgr/webpack": "^8.0.1",
5050
"@types/http-proxy": "^1.17.15",
51+
"@types/js-cookie": "^3.0.6",
5152
"@types/lodash": "^4.17.13",
5253
"@types/styled-components": "^5.1.26",
5354
"@typescript-eslint/eslint-plugin": "^5.61.0",
@@ -60,6 +61,7 @@
6061
"eslint-plugin-react": "^7.32.2",
6162
"eslint-plugin-react-hooks": "^4.6.0",
6263
"husky": "^8.0.3",
64+
"js-cookie": "^3.0.5",
6365
"prettier": "^2.8.8"
6466
}
6567
}

0 commit comments

Comments
 (0)