Skip to content

Commit 9a4be89

Browse files
committed
feat: 로그인 안한 상태로 페이지 접근 시 제한
1 parent 8a9c599 commit 9a4be89

4 files changed

Lines changed: 56 additions & 4 deletions

File tree

app/(with-sidebar)/layout.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
'use client';
2+
13
import Sidebar from '@/components/common/Sidebar';
4+
import { useAuthGuard } from '@/hooks/useAuthGuard';
25

36
import '@uiw/react-md-editor/markdown-editor.css';
47
import '@uiw/react-markdown-preview/markdown.css';
@@ -8,6 +11,14 @@ export default function SidebarLayout({
811
}: {
912
children: React.ReactNode;
1013
}) {
14+
const { loading, isAuthed } = useAuthGuard({ redirectTo: '/login' });
15+
16+
if (loading) return <div>로딩중...</div>;
17+
if (!isAuthed) {
18+
alert('로그인이 필요합니다.');
19+
return null;
20+
}
21+
1122
return (
1223
<div className="flex">
1324
<Sidebar />

components/common/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ const Sidebar = () => {
2626
const handleLogout = async (): Promise<void> => {
2727
try {
2828
await signOut(auth);
29+
alert('로그아웃 되었습니다.');
2930
router.replace('/landing');
30-
router.refresh(); // 서버 컴포넌트/세션 UI 갱신
3131
} catch (err) {
3232
console.error('로그아웃 실패:', err);
3333
alert('로그아웃에 실패했습니다.');

components/write/PostDetail.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const Markdown = dynamic(
1515
const PostDetail = ({ tilId }: { tilId: string }) => {
1616
const router = useRouter();
1717
const [data, setData] = useState<Til | null>(null);
18-
const [loading, setLoading] = useState(true);
1918

2019
useEffect(() => {
2120
const unsub = auth.onAuthStateChanged(async (user) => {
@@ -26,13 +25,11 @@ const PostDetail = ({ tilId }: { tilId: string }) => {
2625

2726
const post = await fetchMyTil(user.uid, tilId);
2827
setData(post);
29-
setLoading(false);
3028
});
3129

3230
return () => unsub();
3331
}, [tilId, router]);
3432

35-
if (loading) return <div className="min-h-screen p-6">로딩중...</div>;
3633
if (!data) return <div className="min-h-screen p-6">글이 없습니다.</div>;
3734

3835
return (

hooks/useAuthGuard.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { onAuthStateChanged, type User } from 'firebase/auth';
5+
import { useRouter } from 'next/navigation';
6+
import { auth } from '@/lib/firebase';
7+
8+
type UseAuthGuardOptions = {
9+
/** 로그인 안 됐을 때 보낼 경로 */
10+
redirectTo?: string;
11+
};
12+
13+
type UseAuthGuardResult = {
14+
user: User | null;
15+
loading: boolean;
16+
isAuthed: boolean;
17+
};
18+
19+
export function useAuthGuard(
20+
options: UseAuthGuardOptions = {}
21+
): UseAuthGuardResult {
22+
const { redirectTo = '/login' } = options;
23+
24+
const router = useRouter();
25+
const [user, setUser] = useState<User | null>(null);
26+
const [loading, setLoading] = useState(true);
27+
28+
useEffect(() => {
29+
const unsub = onAuthStateChanged(auth, (u) => {
30+
if (!u) {
31+
setUser(null);
32+
setLoading(true);
33+
router.replace(redirectTo);
34+
return;
35+
}
36+
setUser(u);
37+
setLoading(false);
38+
});
39+
40+
return () => unsub();
41+
}, [router, redirectTo]);
42+
43+
return { user, loading, isAuthed: !!user };
44+
}

0 commit comments

Comments
 (0)