728x90
반응형

1. 예상 오류 처리 (Error Handling)

// 기본적인 try-catch를 사용한 오류 처리
async function getData() {
  try {
    const res = await fetch('https://api.example.com/data')
    if (!res.ok) {
      throw new Error('Failed to fetch data')
    }
    return res.json()
  } catch (error) {
    console.error('Error:', error)
    return null // 또는 기본값 반환
  }
}

2. 서버 작업에서의 오류 처리 (Server Actions Error Handling)

// app/actions.ts
'use server'

async function serverAction(data: FormData) {
  try {
    // 서버 작업 수행
    const result = await database.save(data)
    return { success: true, data: result }
  } catch (e) {
    // 구체적인 오류 타입 처리
    if (e instanceof DatabaseError) {
      return { success: false, error: '데이터베이스 오류' }
    }
    return { success: false, error: '알 수 없는 오류' }
  }
}


3. 서버 구성 요소의 오류 처리 (Server Component Error Handling)

// app/ServerComponent.tsx
async function ServerComponent() {
  const data = await getData()
  
  if (!data) {
    // 오류 상태를 명시적으로 처리
    return <div>데이터를 불러오는데 실패했습니다</div>
  }

  return <div>{data.map(item => <Item key={item.id} {...item} />)}</div>
}


4. 오류 경계 사용 (Error Boundaries)
이 부분이 특히 중요한데, Next.js 13 이상에서는 error.tsx 파일을 사용하여 오류 경계를 구현합니다:


// app/error.tsx
'use client' // 클라이언트 컴포넌트여야 함

interface ErrorBoundaryProps {
  error: Error
  reset: () => void
}

export default function ErrorBoundary({
  error,
  reset,
}: ErrorBoundaryProps) {
  return (
    <div className="error-container">
      <h2>문제가 발생했습니다!</h2>
      <p>{error.message}</p>
      <button onClick={reset}>다시 시도</button>
    </div>
  )
}


5. 중첩된 경로에서 오류 처리 (Nested Routes Error Handling)

app/
├── error.tsx      // 전역 오류 처리
├── layout.tsx
├── page.tsx
└── blog/
    ├── error.tsx  // 블로그 섹션 오류 처리
    └── page.tsx


6. 전역 오류 처리 (Global Error Handling)

// app/global-error.tsx
'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <html>
      <body>
        <h1>심각한 오류가 발생했습니다</h1>
        <p>{error.message}</p>
        <button onClick={reset}>다시 시도</button>
      </body>
    </html>
  )
}


주요 포인트
1. 계층적 오류 처리
- error.tsx는 가장 가까운 상위 경로에서 오류를 포착
- 더 구체적인 오류 처리가 필요한 경우 하위 경로에 error.tsx 배치

2. 오류 복구 전략

// app/posts/error.tsx
'use client'

export default function ErrorBoundary({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  useEffect(() => {
    // 오류 로깅
    console.error(error)
  }, [error])

  return (
    <div>
      <h2>포스트를 불러오는데 실패했습니다</h2>
      <button 
        onClick={() => reset()}
        className="retry-button"
      >
        다시 시도
      </button>
    </div>
  )
}


3. 오류 UI 구성
- 사용자 친화적인 메시지 제공
- 복구 옵션 제시 (reset 함수 활용)
- 필요한 경우 대체 콘텐츠 표시

4. 오류 타입별 처리

try {
  await someOperation()
} catch (error) {
  if (error instanceof NotFoundError) {
    // 404 처리
    notFound()
  }
  if (error instanceof AuthError) {
    // 인증 오류 처리
    redirect('/login')
  }
  // 기타 오류는 error.tsx에서 처리되도록 전파
  throw error
}

 

오류 핸들링을 통해
- 예측 가능한 오류 상황을 우아하게 처리
- 사용자 경험 개선
- 디버깅 및 유지보수 용이성 향상
- 애플리케이션의 안정성 확보

728x90
반응형

'코딩공부 > Next.js' 카테고리의 다른 글

Next.js의 Layout과 Template  (1) 2024.10.31
728x90
반응형

1. 레이아웃(Layout)
- 상태와 상호작용이 유지됩니다
- 여러 페이지에서 공유되는 UI를 위해 사용됩니다
- 렌더링 시 레이아웃은 자식 컴포넌트 간에 상태를 보존합니다
- 주로 사용되는 경우

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <nav>공통 네비게이션</nav>
        {children}
        <footer>공통 푸터</footer>
      </body>
    </html>
  )
}



2. 템플릿(Template)
- 각 자식 페이지나 레이아웃이 새로 마운트될 때마다 새 인스턴스가 생성됩니다
- 상태가 유지되지 않고 DOM 요소가 재생성됩니다
- 페이지 전환 시마다 다시 마운트되어야 하는 기능에 적합합니다
- 주로 사용되는 경우

// app/template.tsx
export default function Template({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div>
      {/* 애니메이션 효과나 로깅 등이 필요한 경우 */}
      {children}
    </div>
  )
}


사용 사례 비교:

레이아웃 사용이 적합한 경우:
- 헤더, 푸터, 사이드바와 같은 지속적인 UI 요소
- 전역 상태나 컨텍스트를 공유해야 하는 경우
- 페이지 간 이동시에도 상태를 유지해야 하는 경우

템플릿 사용이 적합한 경우:
- 페이지 전환 애니메이션
- 페이지 접속시마다 초기화되어야 하는 카운터나 타이머
- useEffect 훅이 페이지마다 다시 실행되어야 하는 경우
- 페이지별 피드백이나 분석 기능

실제 사용 예시

// app/layout.tsx (레이아웃)
export default function Layout({ children }) {
  const [user] = useState(getUser()) // 상태 유지됨
  
  return (
    <UserContext.Provider value={user}>
      <nav>
        <Logo />
        <UserProfile />
      </nav>
      {children}
    </UserContext.Provider>
  )
}

// app/template.tsx (템플릿)
export default function Template({ children }) {
  useEffect(() => {
    // 페이지 방문마다 실행됨
    logPageView()
  }, [])

  return (
    <div className="page-transition">
      {children}
    </div>
  )
}



핵심 차이점을 정리하면
1. 상태 유지: 레이아웃은 유지, 템플릿은 초기화
2. 마운팅: 레이아웃은 한 번, 템플릿은 매 페이지 전환마다
3. 용도: 레이아웃은 공통 UI, 템플릿은 페이지별 기능
4. 성능: 레이아웃이 더 효율적 (재렌더링이 적음)

728x90
반응형

'코딩공부 > Next.js' 카테고리의 다른 글

Next.js의 오류처리  (4) 2024.10.31

+ Recent posts