이 문서는 G7에서 Custom Exception 클래스의 다국어 처리 방법을 설명합니다.
1. 예외 메시지 하드코딩 금지 → __() 함수 필수
2. 메시지 위치: lang/ko/exceptions.php, lang/en/exceptions.php
3. 파라미터 치환: __('exceptions.key', ['param' => $value])
4. 코어 예외: exceptions.template_engine.* 형식
5. 모듈 예외: vendor-module::exceptions.* 형식
필수: __() 함수 사용 (예외 메시지 하드코딩 금지)
필수: __() 함수를 사용한 다국어 처리
- 모든 예외 메시지는 다국어 파일에 정의:
/lang/ko/exceptions.php,/lang/en/exceptions.php - Exception 생성자에서 __() 함수 사용: 하드코딩된 문자열 사용 금지
- 파라미터 치환 지원:
:trace,:max,:id등의 동적 값 지원 - 일관성 유지: 모든 커스텀 예외가 동일한 패턴 사용
/lang/ko/exceptions.php # 한국어 예외 메시지
/lang/en/exceptions.php # 영어 예외 메시지
// /lang/ko/exceptions.php
return [
'circular_reference' => '레이아웃 순환 참조 감지: :trace',
'max_depth_exceeded' => '레이아웃 중첩 깊이가 최대 허용 깊이(:max)를 초과했습니다.',
'resource_not_found' => ':resource를 찾을 수 없습니다.',
];
// /lang/en/exceptions.php
return [
'circular_reference' => 'Layout circular reference detected: :trace',
'max_depth_exceeded' => 'Layout nesting depth exceeds maximum allowed depth (:max).',
'resource_not_found' => ':resource not found.',
];// /lang/ko/exceptions.php
return [
'template' => [
'circular_reference' => '레이아웃 순환 참조 감지: :trace',
'max_depth_exceeded' => '레이아웃 중첩 깊이(:current)가 최대 허용 깊이(:max)를 초과했습니다.',
'template_not_found' => '템플릿을 찾을 수 없습니다: :identifier',
'layout_not_found' => '레이아웃을 찾을 수 없습니다: :layout_name',
'component_not_found' => '컴포넌트를 찾을 수 없습니다: :component_name',
'invalid_layout_structure' => '유효하지 않은 레이아웃 구조입니다.',
],
];
// /lang/en/exceptions.php
return [
'template' => [
'circular_reference' => 'Layout circular reference detected: :trace',
'max_depth_exceeded' => 'Layout nesting depth (:current) exceeds maximum allowed depth (:max).',
'template_not_found' => 'Template not found: :identifier',
'layout_not_found' => 'Layout not found: :layout_name',
'component_not_found' => 'Component not found: :component_name',
'invalid_layout_structure' => 'Invalid layout structure.',
],
];// ❌ 하드코딩된 예외 메시지 - 금지
class CircularReferenceException extends Exception
{
public function __construct(array $stack, string $currentLayout)
{
$stackTrace = implode(' → ', $stack) . " → {$currentLayout}";
$message = "레이아웃 순환 참조 감지: {$stackTrace}"; // 한국어만 지원, 다국어 불가
parent::__construct($message);
}
}// ✅ 다국어 함수 사용 (파라미터 치환)
class CircularReferenceException extends Exception
{
private array $stack;
public function __construct(array $stack, string $currentLayout)
{
$this->stack = $stack;
// ✅ 다국어 함수 사용 (파라미터 치환)
$stackTrace = implode(' → ', $stack) . " → {$currentLayout}";
$message = __('exceptions.circular_reference', ['trace' => $stackTrace]);
parent::__construct($message);
}
public function getStack(): array
{
return $this->stack;
}
}class MaxDepthExceededException extends Exception
{
public function __construct(int $currentDepth, int $maxDepth)
{
// ✅ 다국어 함수 사용 (다중 파라미터)
$message = __('exceptions.max_depth_exceeded', [
'current' => $currentDepth,
'max' => $maxDepth
]);
parent::__construct($message);
}
}템플릿 레이아웃 상속 시 순환 참조가 발생하면 이 예외를 발생시킵니다.
<?php
namespace App\Exceptions\Template;
use Exception;
/**
* 레이아웃 순환 참조 예외
*/
class CircularReferenceException extends Exception
{
private array $stack;
public function __construct(array $stack, string $currentLayout)
{
$this->stack = $stack;
// ✅ 다국어 함수 사용
$stackTrace = implode(' → ', $stack) . " → {$currentLayout}";
$message = __('exceptions.template.circular_reference', ['trace' => $stackTrace]);
parent::__construct($message);
}
/**
* 순환 참조 스택 반환
*/
public function getStack(): array
{
return $this->stack;
}
}레이아웃 상속 깊이가 최대 허용 깊이(10)를 초과하면 이 예외를 발생시킵니다.
<?php
namespace App\Exceptions\Template;
use Exception;
/**
* 레이아웃 최대 깊이 초과 예외
*/
class MaxDepthExceededException extends Exception
{
private int $currentDepth;
private int $maxDepth;
public function __construct(int $currentDepth, int $maxDepth = 10)
{
$this->currentDepth = $currentDepth;
$this->maxDepth = $maxDepth;
// ✅ 다국어 함수 사용 (다중 파라미터)
$message = __('exceptions.template.max_depth_exceeded', [
'current' => $currentDepth,
'max' => $maxDepth
]);
parent::__construct($message);
}
/**
* 현재 깊이 반환
*/
public function getCurrentDepth(): int
{
return $this->currentDepth;
}
/**
* 최대 허용 깊이 반환
*/
public function getMaxDepth(): int
{
return $this->maxDepth;
}
}<?php
namespace App\Services\Template;
use App\Exceptions\Template\CircularReferenceException;
use App\Exceptions\Template\MaxDepthExceededException;
class LayoutService
{
private const MAX_DEPTH = 10;
/**
* 레이아웃 병합 (상속 체인 처리)
*
* @throws CircularReferenceException 순환 참조 발생 시
* @throws MaxDepthExceededException 깊이 초과 시
*/
public function mergeLayouts(string $layoutName, array $stack = [], int $depth = 0): array
{
// 순환 참조 검사
if (in_array($layoutName, $stack)) {
throw new CircularReferenceException($stack, $layoutName);
}
// 깊이 검사
if ($depth > self::MAX_DEPTH) {
throw new MaxDepthExceededException($depth, self::MAX_DEPTH);
}
// 재귀적으로 레이아웃 병합
// ...
}
}새로운 Custom Exception을 개발할 때 다음 항목을 확인하세요:
-
/lang/ko/exceptions.php에 한국어 메시지 추가 -
/lang/en/exceptions.php에 영어 메시지 추가 - Exception 생성자에서 모든 메시지는
__()함수 사용 - 동적 값은 파라미터 배열로 전달 (예:
['trace' => $stackTrace]) - 두 언어 모두에서 테스트 수행
- 예외 메시지가 사용자에게 노출될 경우 보안 정보 포함 금지
- 다국어 키 정의: 적절한 네임스페이스로 그룹화
- Exception 클래스 생성:
__()함수로 메시지 생성 - 필요한 속성 저장: 디버깅이나 로깅에 필요한 값 보관
- getter 메서드 제공: 저장된 속성에 접근할 수 있도록 제공
- 테스트 작성: 두 언어 환경에서 메시지 확인
- validation.md - Custom Rule 다국어 처리
- index.md - 백엔드 가이드 인덱스