예외 처리
PageNotFoundException, 커스텀 예외 클래스, try/catch 패턴, 글로벌 예외 핸들러 설정을 학습합니다.
예외 시나리오 실행
PageNotFoundException 시나리오는 CI4의 실제 404 에러 페이지로 이동합니다.
브라우저 뒤로가기로 돌아오세요.
PageNotFoundException — 404 처리
CI4는 PageNotFoundException을 던지면 자동으로 404 응답을 반환합니다. 컨트롤러에서 리소스를 찾지 못할 때 사용합니다.
use CodeIgniter\Exceptions\PageNotFoundException;
public function show(int $id): string
{
$post = $this->model->find($id);
if (! $post) {
// 자동으로 404 응답 + app/Views/errors/html/error_404.php 렌더링
throw PageNotFoundException::forPageNotFound();
}
return view('post/show', ['post' => $post]);
}
커스텀 404 뷰 — app/Views/errors/html/error_404.php
<!-- 이 파일을 만들면 CI4 기본 404 페이지 대신 사용됨 -->
<?php $message ??= '페이지를 찾을 수 없습니다.'; ?>
<h1>404 Not Found</h1>
<p><?= esc($message) ?></p>
커스텀 예외 클래스 + try/catch
// app/Exceptions/InsufficientBalanceException.php
namespace App\Exceptions;
class InsufficientBalanceException extends \RuntimeException
{
public function __construct(int $required, int $available)
{
parent::__construct(
"잔액 부족: 필요={$required}, 보유={$available}",
402
);
}
}
서비스에서 던지고 컨트롤러에서 잡기
// Service
public function transfer(int $from, int $to, int $amount): void
{
$account = $this->model->find($from);
if ($account->balance < $amount) {
throw new InsufficientBalanceException($amount, $account->balance);
}
// ... 이체 처리
}
// Controller
try {
$this->transferService->transfer($fromId, $toId, $amount);
return redirect()->back()->with('success', '이체 완료');
} catch (InsufficientBalanceException $e) {
// 도메인 오류 → 사용자에게 안내
return redirect()->back()->with('error', $e->getMessage());
} catch (\Exception $e) {
// 예상치 못한 오류 → 로그 + 일반 메시지
log_message('error', $e->getMessage());
return redirect()->back()->with('error', '처리 중 오류가 발생했습니다.');
}
글로벌 예외 핸들러 — app/Config/Exceptions.php
잡히지 않은 예외를 전역에서 처리하려면 app/Config/Exceptions.php에서 handler()를 오버라이드합니다.
// app/Config/Exceptions.php
namespace Config;
use CodeIgniter\Config\Exceptions as BaseExceptions;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Throwable;
class Exceptions extends BaseExceptions
{
public function handler(int $statusCode, Throwable $exception,
RequestInterface $request,
ResponseInterface $response): ResponseInterface
{
// 404: 커스텀 응답
if ($exception instanceof PageNotFoundException) {
return $response->setStatusCode(404)
->setBody(view('errors/custom_404'));
}
// 운영 환경: 상세 오류 숨기고 로그만
if (ENVIRONMENT === 'production') {
log_message('critical', $exception->getMessage());
return $response->setStatusCode(500)
->setBody(view('errors/custom_500'));
}
// 개발 환경: 기본 처리 위임
return parent::handler($statusCode, $exception, $request, $response);
}
}
운영/개발 환경 분리 팁
ENVIRONMENT === 'production' 조건으로 운영에서는 스택 트레이스를 감추고,
개발에서는 상세 오류를 표시하도록 분기하세요.