Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions app/lib/dbConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ async function dbConnect(uri?: string, retries = 3): Promise<Mongoose> {
const opts = {
bufferCommands: false,
maxPoolSize: 10,
minPoolSize: 2,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
minPoolSize: 1,
serverSelectionTimeoutMS: 10000,
socketTimeoutMS: 20000,
connectTimeoutMS: 10000,
maxIdleTimeMS: 30000,
waitQueueTimeoutMS: 5000,
};

cached.promise = mongoose
Expand Down
50 changes: 50 additions & 0 deletions app/posts/[slug]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use client';

import Link from 'next/link';
import { useEffect } from 'react';

export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error('Post detail error:', error);
}, [error]);

return (
<div className="flex flex-col items-center justify-center min-h-[60vh] px-4">
<div className="max-w-md w-full text-center space-y-6">
<h2 className="text-3xl font-bold text-gray-900 dark:text-gray-100">
글을 불러오는데 실패했습니다
</h2>
<p className="text-gray-600 dark:text-gray-400">
{error.message === 'Post not found'
? '요청하신 글을 찾을 수 없습니다.'
: '일시적인 오류가 발생했습니다. 잠시 후 다시 시도해주세요.'}
</p>
<div className="flex gap-4 justify-center">
<button
onClick={reset}
className="px-6 py-2 bg-primary-mountain text-white rounded-lg hover:bg-primary-mountain-dark transition-colors"
>
다시 시도
</button>
<Link
href="/posts"
className="px-6 py-2 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
>
목록으로
</Link>
</div>
{error.digest && (
<p className="text-xs text-gray-500 dark:text-gray-600">
오류 ID: {error.digest}
</p>
)}
</div>
</div>
);
}
12 changes: 12 additions & 0 deletions app/posts/[slug]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import SVGLoadingSpinner from '@/app/entities/common/Loading/SVGLoadingSpinner';

export default function Loading() {
return (
<div className="flex flex-col items-center justify-center min-h-[60vh]">
<SVGLoadingSpinner />
<p className="mt-4 text-gray-600 dark:text-gray-400">
글을 불러오는 중...
</p>
</div>
);
}
4 changes: 2 additions & 2 deletions app/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function generateStaticParams() {
}

// ISR 활성화하기
export const revalidate = 60; // 60초마다 재검증
export const revalidate = 300; // 300초(5분)마다 재검증

async function getPostDetail(slug: string) {
await dbConnect();
Expand Down Expand Up @@ -60,7 +60,7 @@ export const generateMetadata = async ({
authors: [post.author],
},
other: {
'application-name': 'Shipfriend Tech Blog',
'application-name': 'ShipFriend TechBlog',
author: post.author,
publish_date: new Date(post.date).toISOString(),
'og:type': 'article',
Expand Down
4 changes: 2 additions & 2 deletions app/posts/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Suspense } from 'react';
import SVGLoadingSpinner from '@/app/entities/common/Loading/SVGLoadingSpinner';
import Loading from './[slug]/loading';

interface LayoutProps {
children: React.ReactNode;
}
const Layout = ({ children }: LayoutProps) => {
return <Suspense fallback={<SVGLoadingSpinner />}>{children}</Suspense>;
return <Suspense fallback={<Loading />}>{children}</Suspense>;
};

export default Layout;