Skip to content

Commit 87a31f0

Browse files
authored
✨ GNB 생성 및 토큰 저장, 삭제 로직 구현 (#29)
* ✨ token을 저장하는 global context 설정 * ♻️ query 사용 시 DI를 통해 주입하도록 설정 * ✨ 로그아웃, refresh token 재발급 API 등록 * ✨ guard route 생성 * ✨ GNB 생성 * 🧪 GNB 테스트 추가 * 🎨 포매팅 적용
1 parent 4f2e4f1 commit 87a31f0

22 files changed

Lines changed: 714 additions & 154 deletions

.storybook/preview.tsx

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,66 @@
11
import type { Preview } from '@storybook/react-vite';
22
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
33
import { initialize, mswLoader } from 'msw-storybook-addon';
4+
import { type ReactNode, useState } from 'react';
45
import { MemoryRouter } from 'react-router';
6+
7+
import { useAuthQuery } from '../src/feature/auth/application/auth-query';
58
import { implAuthUsecase } from '../src/feature/auth/usecase/auth-usecase';
9+
import { QueryContext } from '../src/feature/shared/context/query-context';
10+
import { TokenContext } from '../src/feature/shared/context/token-context';
611
import { UsecaseContext } from '../src/feature/shared/context/usecase-context';
712
import { externalCall, implApi } from '../src/infrastructure/api';
13+
import { implTokenRepository } from '../src/infrastructure/token/token-repository';
814
import { handlers } from '../src/mocks/handlers';
915
import '../src/index.css';
1016

1117
initialize({ onUnhandledRequest: 'bypass' });
1218

19+
/**
20+
* QueryClientProvider 안에서 렌더되는 내부 컴포넌트.
21+
* module 레벨에 정의해야 story 전환 시 불필요한 remount를 방지할 수 있다.
22+
*/
23+
const StoryAuthProviders = ({ children }: { children: ReactNode }) => {
24+
const [token, setToken] = useState<string | null>(null);
25+
const api = implApi({ externalCall });
26+
const tokenRepository = implTokenRepository({ setToken });
27+
const authUsecase = implAuthUsecase({ api, tokenRepository });
28+
const authQuery = useAuthQuery({ authUsecase });
29+
30+
return (
31+
<QueryContext.Provider value={{ authQuery }}>
32+
<TokenContext.Provider value={{ token }}>
33+
<UsecaseContext.Provider value={{ authUsecase }}>
34+
{children}
35+
</UsecaseContext.Provider>
36+
</TokenContext.Provider>
37+
</QueryContext.Provider>
38+
);
39+
};
40+
1341
const preview: Preview = {
1442
parameters: {
1543
msw: { handlers },
1644
},
1745
loaders: [mswLoader],
1846
decorators: [
1947
(Story) => {
20-
const queryClient = new QueryClient({
21-
defaultOptions: {
22-
queries: { refetchOnWindowFocus: false, retry: false },
23-
mutations: { retry: false },
24-
},
25-
});
26-
const api = implApi({ externalCall });
27-
const authUsecase = implAuthUsecase({ api });
48+
const [queryClient] = useState(
49+
() =>
50+
new QueryClient({
51+
defaultOptions: {
52+
queries: { refetchOnWindowFocus: false, retry: false },
53+
mutations: { retry: false },
54+
},
55+
})
56+
);
2857

2958
return (
3059
<MemoryRouter>
3160
<QueryClientProvider client={queryClient}>
32-
<UsecaseContext.Provider value={{ authUsecase }}>
61+
<StoryAuthProviders>
3362
<Story />
34-
</UsecaseContext.Provider>
63+
</StoryAuthProviders>
3564
</QueryClientProvider>
3665
</MemoryRouter>
3766
);

src/App.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2+
import { useState } from 'react';
3+
import { useAuthQuery } from '@/feature/auth/application/auth-query';
24
import { implAuthUsecase } from '@/feature/auth/usecase/auth-usecase';
5+
import { QueryContext } from '@/feature/shared/context/query-context';
6+
import { TokenContext } from '@/feature/shared/context/token-context';
37
import { UsecaseContext } from '@/feature/shared/context/usecase-context';
8+
import { RouterProvider } from '@/feature/shared/routes/router-provider';
49
import { externalCall, implApi } from '@/infrastructure/api';
5-
import { RouterProvider } from './feature/shared/routes/router-provider';
10+
import { implTokenRepository } from '@/infrastructure/token/token-repository';
611

712
const queryClient = new QueryClient({
813
defaultOptions: {
@@ -13,15 +18,28 @@ const queryClient = new QueryClient({
1318
},
1419
});
1520

16-
export const App = () => {
21+
const AppContent = () => {
22+
const [token, setToken] = useState<string | null>(null);
1723
const api = implApi({ externalCall });
18-
const authUsecase = implAuthUsecase({ api });
24+
const tokenRepository = implTokenRepository({ setToken });
25+
const authUsecase = implAuthUsecase({ api, tokenRepository });
26+
const authQuery = useAuthQuery({ authUsecase });
27+
28+
return (
29+
<QueryContext.Provider value={{ authQuery }}>
30+
<TokenContext.Provider value={{ token }}>
31+
<UsecaseContext.Provider value={{ authUsecase }}>
32+
<RouterProvider />
33+
</UsecaseContext.Provider>
34+
</TokenContext.Provider>
35+
</QueryContext.Provider>
36+
);
37+
};
1938

39+
export const App = () => {
2040
return (
2141
<QueryClientProvider client={queryClient}>
22-
<UsecaseContext.Provider value={{ authUsecase }}>
23-
<RouterProvider />
24-
</UsecaseContext.Provider>
42+
<AppContent />
2543
</QueryClientProvider>
2644
);
2745
};

0 commit comments

Comments
 (0)