PHP Notice/Warning 무시하지 않기

프리터코더·2025년 5월 29일
0

php 문제 해결

목록 보기
44/79

Notice와 Warning을 단순히 숨기는 것보다 근본적으로 해결하는 방법을 알아보겠습니다. 안전하고 효율적인 에러 처리 방법들을 제시합니다.

1. 배열 키 존재 확인으로 Notice 해결

문제: Undefined index Notice 발생

해결책: 안전한 배열 접근 방법 사용

// 잘못된 방법 (Notice 발생)
// $name = $_POST['name']; // Notice: Undefined index

// 올바른 해결 방법들
class SafeArrayAccess {
    // 방법 1: isset() 사용
    public static function getValue($array, $key, $default = null) {
        return isset($array[$key]) ? $array[$key] : $default;
    }
    
    // 방법 2: array_key_exists() 사용 (null 값도 구분)
    public static function getValueStrict($array, $key, $default = null) {
        return array_key_exists($key, $array) ? $array[$key] : $default;
    }
    
    // 방법 3: PHP 7+ null coalescing operator
    public static function getValueModern($array, $key, $default = null) {
        return $array[$key] ?? $default;
    }
    
    // 중첩 배열 안전 접근
    public static function getNestedValue($array, $keys, $default = null) {
        foreach ($keys as $key) {
            if (!is_array($array) || !array_key_exists($key, $array)) {
                return $default;
            }
            $array = $array[$key];
        }
        return $array;
    }
}

// 사용 예시
$name = SafeArrayAccess::getValue($_POST, 'name', '익명');
$email = $_POST['email'] ?? 'no-email@example.com';
$nested = SafeArrayAccess::getNestedValue($_POST, ['user', 'profile', 'age'], 0);

2. 변수 초기화로 Warning 방지

문제: Undefined variable Warning 발생

해결책: 적절한 변수 초기화 및 검증

class VariableHelper {
    // 변수 안전 초기화
    public static function initializeVars(&...$vars) {
        foreach ($vars as &$var) {
            if (!isset($var)) {
                $var = null;
            }
        }
    }
    
    // 타입별 기본값 설정
    public static function setDefaults($config = []) {
        $defaults = [
            'string_var' => '',
            'int_var' => 0,
            'array_var' => [],
            'bool_var' => false,
            'object_var' => null
        ];
        
        return array_merge($defaults, $config);
    }
    
    // 함수 매개변수 검증
    public static function validateParams($params, $required = []) {
        $missing = [];
        
        foreach ($required as $param) {
            if (!isset($params[$param])) {
                $missing[] = $param;
            }
        }
        
        if (!empty($missing)) {
            throw new InvalidArgumentException(
                '필수 매개변수가 누락되었습니다: ' . implode(', ', $missing)
            );
        }
        
        return true;
    }
}

// 사용 예시
function processUser($data) {
    // 필수 매개변수 검증
    VariableHelper::validateParams($data, ['name', 'email']);
    
    // 기본값 설정
    $config = VariableHelper::setDefaults([
        'name' => $data['name'],
        'email' => $data['email'],
        'age' => $data['age'] ?? 0
    ]);
    
    return $config;
}

3. 파일/함수 존재 확인

문제: 존재하지 않는 파일이나 함수 호출로 인한 Warning

해결책: 사전 검증 및 안전한 호출

class SafeOperations {
    // 안전한 파일 포함
    public static function safeInclude($filepath, $required = false) {
        if (!file_exists($filepath)) {
            $message = "파일을 찾을 수 없습니다: $filepath";
            
            if ($required) {
                throw new Exception($message);
            } else {
                error_log($message);
                return false;
            }
        }
        
        if ($required) {
            require $filepath;
        } else {
            include $filepath;
        }
        
        return true;
    }
    
    // 안전한 함수 호출
    public static function safeCall($function, $args = [], $default = null) {
        if (!function_exists($function)) {
            error_log("함수가 존재하지 않습니다: $function");
            return $default;
        }
        
        try {
            return call_user_func_array($function, $args);
        } catch (Exception $e) {
            error_log("함수 호출 오류 ($function): " . $e->getMessage());
            return $default;
        }
    }
    
    // 안전한 메서드 호출
    public static function safeMethodCall($object, $method, $args = [], $default = null) {
        if (!is_object($object)) {
            error_log("객체가 아닙니다");
            return $default;
        }
        
        if (!method_exists($object, $method)) {
            error_log("메서드가 존재하지 않습니다: " . get_class($object) . "::$method");
            return $default;
        }
        
        try {
            return call_user_func_array([$object, $method], $args);
        } catch (Exception $e) {
            error_log("메서드 호출 오류: " . $e->getMessage());
            return $default;
        }
    }
}

// 사용 예시
SafeOperations::safeInclude('config.php', true);
$result = SafeOperations::safeCall('custom_function', ['param1', 'param2'], 'default');

4. 적절한 에러 레벨 설정

문제: 개발/운영 환경별 에러 처리 필요

해결책: 환경별 에러 레벨 및 로깅 설정

class ErrorManager {
    public static function setupEnvironment($env = 'production') {
        switch ($env) {
            case 'development':
                // 개발 환경: 모든 에러 표시
                error_reporting(E_ALL);
                ini_set('display_errors', 1);
                ini_set('log_errors', 1);
                break;
                
            case 'testing':
                // 테스트 환경: 에러 로깅만
                error_reporting(E_ALL);
                ini_set('display_errors', 0);
                ini_set('log_errors', 1);
                break;
                
            case 'production':
                // 운영 환경: 치명적 에러만 로깅
                error_reporting(E_ERROR | E_WARNING | E_PARSE);
                ini_set('display_errors', 0);
                ini_set('log_errors', 1);
                break;
        }
        
        // 커스텀 에러 핸들러 설정
        set_error_handler([self::class, 'customErrorHandler']);
    }
    
    public static function customErrorHandler($severity, $message, $file, $line) {
        // Notice는 로깅만 하고 계속 실행
        if ($severity === E_NOTICE) {
            error_log("Notice: $message in $file on line $line");
            return true; // 기본 핸들러 실행 안함
        }
        
        // Warning은 로깅하고 예외로 변환
        if ($severity === E_WARNING) {
            error_log("Warning: $message in $file on line $line");
            
            // 개발 환경에서만 예외로 변환
            if (defined('ENVIRONMENT') && ENVIRONMENT === 'development') {
                throw new ErrorException($message, 0, $severity, $file, $line);
            }
            
            return true;
        }
        
        // 기타 에러는 기본 처리
        return false;
    }
    
    // 선택적 에러 억제 (최후의 수단)
    public static function suppressSpecificErrors($callback, $suppressLevels = E_NOTICE) {
        $oldLevel = error_reporting();
        error_reporting($oldLevel & ~$suppressLevels);
        
        try {
            $result = $callback();
        } finally {
            error_reporting($oldLevel);
        }
        
        return $result;
    }
}

// 사용 예시
ErrorManager::setupEnvironment('development');

// 특정 코드 블록에서만 Notice 억제
$result = ErrorManager::suppressSpecificErrors(function() {
    return $_POST['maybe_undefined_key']; // Notice 발생하지 않음
}, E_NOTICE);

5. 구조화된 에러 처리 클래스

문제: 일관성 없는 에러 처리로 인한 혼란

해결책: 통합 에러 처리 시스템 구축

class StructuredErrorHandler {
    private static $errorCounts = [];
    private static $logFile = 'errors.log';
    
    public static function handleNotice($callback, $context = '') {
        try {
            return $callback();
        } catch (Exception $e) {
            self::logError('NOTICE', $e->getMessage(), $context);
            return null;
        }
    }
    
    public static function handleWarning($callback, $fallback = null, $context = '') {
        try {
            return $callback();
        } catch (Exception $e) {
            self::logError('WARNING', $e->getMessage(), $context);
            return $fallback;
        }
    }
    
    private static function logError($level, $message, $context) {
        $timestamp = date('Y-m-d H:i:s');
        $logEntry = "[$timestamp] $level: $message";
        
        if ($context) {
            $logEntry .= " (Context: $context)";
        }
        
        error_log($logEntry . PHP_EOL, 3, self::$logFile);
        
        // 에러 카운트 증가
        if (!isset(self::$errorCounts[$level])) {
            self::$errorCounts[$level] = 0;
        }
        self::$errorCounts[$level]++;
    }
    
    public static function getErrorStats() {
        return self::$errorCounts;
    }
    
    // 안전한 배열 접근 래퍼
    public static function safeGet($array, $key, $default = null) {
        return self::handleNotice(
            function() use ($array, $key) {
                return $array[$key];
            }
        ) ?? $default;
    }
}

// 사용 예시
$name = StructuredErrorHandler::safeGet($_POST, 'name', '익명');
$config = StructuredErrorHandler::handleWarning(
    function() { return parse_ini_file('config.ini'); },
    ['default' => 'config'],
    'Config file loading'
);
profile
일용직 개발자. freetercoder@gmail.com

0개의 댓글