PHP에서 환경변수 미적용 문제 해결하기

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

php 문제 해결

목록 보기
64/79

PHP 애플리케이션에서 환경변수가 제대로 로드되지 않거나 적용되지 않는 문제는 매우 흔합니다. 다양한 원인과 해결책을 알아보겠습니다.

1. 기본 환경변수 로더 구현

가장 기본적인 .env 파일 로더를 직접 구현합니다.

<?php
class EnvLoader {
    public static function load($path = null) {
        $envFile = $path ?: __DIR__ . '/../.env';
        
        if (!file_exists($envFile)) {
            throw new Exception(".env file not found at: $envFile");
        }
        
        $lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        
        foreach ($lines as $line) {
            if (strpos($line, '#') === 0 || strpos($line, '=') === false) {
                continue;
            }
            
            list($key, $value) = explode('=', $line, 2);
            $key = trim($key);
            $value = trim($value, '"\'');
            
            // 이미 설정된 환경변수는 덮어쓰지 않음
            if (!isset($_ENV[$key])) {
                $_ENV[$key] = $value;
                putenv("$key=$value");
            }
        }
    }
}

// 사용법
EnvLoader::load();

2. 환경별 .env 파일 로딩

개발, 스테이징, 프로덕션 환경별로 다른 .env 파일을 로드합니다.

<?php
class Environment {
    public static function load() {
        $env = $_SERVER['APP_ENV'] ?? 'development';
        $basePath = __DIR__ . '/../';
        
        $envFiles = [
            $basePath . '.env',
            $basePath . ".env.$env",
            $basePath . '.env.local'
        ];
        
        foreach ($envFiles as $file) {
            if (file_exists($file)) {
                self::loadEnvFile($file);
            }
        }
    }
    
    private static function loadEnvFile($file) {
        $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        
        foreach ($lines as $line) {
            if (self::isComment($line) || !self::hasEquals($line)) {
                continue;
            }
            
            self::setEnvironmentVariable($line);
        }
    }
    
    private static function setEnvironmentVariable($line) {
        list($key, $value) = explode('=', $line, 2);
        $key = trim($key);
        $value = self::parseValue(trim($value));
        
        $_ENV[$key] = $value;
        $_SERVER[$key] = $value;
        putenv("$key=$value");
    }
    
    private static function parseValue($value) {
        // 따옴표 제거
        if (preg_match('/^"(.*)"$/', $value, $matches)) {
            return $matches[1];
        }
        
        // 불린 값 처리
        if (in_array(strtolower($value), ['true', 'false'])) {
            return strtolower($value) === 'true';
        }
        
        return $value;
    }
}

3. PHP-FPM 환경변수 설정

PHP-FPM에서 환경변수가 전달되지 않는 문제를 해결합니다.

; 환경변수 전달 설정
clear_env = no

; 또는 특정 환경변수만 전달
clear_env = yes
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

; 애플리케이션 환경변수
env[APP_ENV] = production
env[DB_HOST] = localhost
env[DB_NAME] = myapp

4. 환경변수 헬퍼 함수

편리한 환경변수 접근을 위한 헬퍼 함수를 만듭니다.

<?php
class EnvHelper {
    public static function get($key, $default = null) {
        $value = $_ENV[$key] ?? $_SERVER[$key] ?? getenv($key);
        
        if ($value === false) {
            return $default;
        }
        
        return self::castValue($value);
    }
    
    public static function required($key) {
        $value = self::get($key);
        
        if ($value === null) {
            throw new Exception("Required environment variable '$key' is not set");
        }
        
        return $value;
    }
    
    public static function bool($key, $default = false) {
        $value = self::get($key, $default);
        
        if (is_bool($value)) {
            return $value;
        }
        
        return in_array(strtolower($value), ['true', '1', 'yes', 'on']);
    }
    
    public static function int($key, $default = 0) {
        return (int) self::get($key, $default);
    }
    
    private static function castValue($value) {
        // 불린 값 변환
        if (in_array(strtolower($value), ['true', 'false'])) {
            return strtolower($value) === 'true';
        }
        
        // 숫자 값 변환
        if (is_numeric($value)) {
            return strpos($value, '.') !== false ? (float) $value : (int) $value;
        }
        
        return $value;
    }
}

5. 환경변수 검증 시스템

필수 환경변수가 설정되었는지 검증합니다.

<?php
class EnvValidator {
    private static $requiredVars = [
        'DB_HOST',
        'DB_NAME', 
        'DB_USER',
        'DB_PASSWORD',
        'APP_KEY'
    ];
    
    public static function validate() {
        $missing = [];
        
        foreach (self::$requiredVars as $var) {
            if (empty(EnvHelper::get($var))) {
                $missing[] = $var;
            }
        }
        
        if (!empty($missing)) {
            throw new Exception('Missing required environment variables: ' . implode(', ', $missing));
        }
        
        return true;
    }
    
    public static function validateTypes() {
        $validations = [
            'DB_PORT' => 'integer',
            'APP_DEBUG' => 'boolean',
            'CACHE_TTL' => 'integer'
        ];
        
        foreach ($validations as $var => $type) {
            $value = EnvHelper::get($var);
            if ($value !== null && !self::validateType($value, $type)) {
                throw new Exception("Environment variable '$var' must be of type $type");
            }
        }
    }
    
    private static function validateType($value, $type) {
        switch ($type) {
            case 'integer':
                return is_numeric($value);
            case 'boolean':
                return in_array(strtolower($value), ['true', 'false', '1', '0']);
            default:
                return true;
        }
    }
}

6. Docker 환경에서의 환경변수 처리

Docker 컨테이너에서 환경변수를 올바르게 처리합니다.

<?php
class DockerEnvLoader {
    public static function load() {
        // Docker secrets 처리
        self::loadDockerSecrets();
        
        // 환경변수 파일 처리
        self::loadEnvFiles();
    }
    
    private static function loadDockerSecrets() {
        $secretsDir = '/run/secrets';
        
        if (!is_dir($secretsDir)) {
            return;
        }
        
        $secrets = scandir($secretsDir);
        
        foreach ($secrets as $secret) {
            if ($secret === '.' || $secret === '..') {
                continue;
            }
            
            $secretPath = $secretsDir . '/' . $secret;
            $secretValue = trim(file_get_contents($secretPath));
            
            $envKey = strtoupper($secret);
            $_ENV[$envKey] = $secretValue;
            putenv("$envKey=$secretValue");
        }
    }
    
    private static function loadEnvFiles() {
        $envFile = '/app/.env';
        
        if (file_exists($envFile)) {
            EnvLoader::load($envFile);
        }
    }
}

7. 환경변수 캐싱

성능 향상을 위한 환경변수 캐싱 시스템입니다.

<?php
class EnvCache {
    private static $cache = [];
    private static $loaded = false;
    
    public static function get($key, $default = null) {
        if (!self::$loaded) {
            self::loadAll();
        }
        
        return self::$cache[$key] ?? $default;
    }
    
    private static function loadAll() {
        // 시스템 환경변수 로드
        foreach ($_ENV as $key => $value) {
            self::$cache[$key] = $value;
        }
        
        // .env 파일 로드
        if (file_exists('.env')) {
            $lines = file('.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
            
            foreach ($lines as $line) {
                if (strpos($line, '=') !== false && strpos($line, '#') !== 0) {
                    list($key, $value) = explode('=', $line, 2);
                    self::$cache[trim($key)] = trim($value, '"\'');
                }
            }
        }
        
        self::$loaded = true;
    }
}

8. 환경변수 디버깅 도구

환경변수 문제를 진단하는 도구입니다.

<?php
function debugEnvironment() {
    echo "=== Environment Variables Debug ===\n\n";
    
    echo "1. PHP SAPI: " . php_sapi_name() . "\n";
    echo "2. Current working directory: " . getcwd() . "\n";
    echo "3. Script location: " . __DIR__ . "\n\n";
    
    echo "4. .env file status:\n";
    $envFiles = ['.env', '.env.local', '.env.production'];
    foreach ($envFiles as $file) {
        $path = __DIR__ . '/../' . $file;
        echo "   $file: " . (file_exists($path) ? 'EXISTS' : 'NOT FOUND') . "\n";
    }
    
    echo "\n5. Environment variables:\n";
    $envVars = ['APP_ENV', 'DB_HOST', 'DB_NAME', 'DB_USER'];
    foreach ($envVars as $var) {
        $value = $_ENV[$var] ?? $_SERVER[$var] ?? getenv($var) ?: 'NOT SET';
        echo "   $var: $value\n";
    }
    
    echo "\n6. All $_ENV variables:\n";
    foreach ($_ENV as $key => $value) {
        echo "   $key: $value\n";
    }
}

debugEnvironment();

9. 자동 환경변수 로딩

애플리케이션 부트스트랩에서 자동으로 환경변수를 로드합니다.

<?php
// 환경변수 자동 로딩
spl_autoload_register(function($class) {
    if ($class === 'EnvLoader') {
        require_once __DIR__ . '/../src/EnvLoader.php';
    }
});

// 애플리케이션 시작 시 환경변수 로드
try {
    EnvLoader::load();
    EnvValidator::validate();
} catch (Exception $e) {
    error_log("Environment loading failed: " . $e->getMessage());
    
    if (EnvHelper::get('APP_ENV') !== 'production') {
        die("Environment configuration error: " . $e->getMessage());
    }
}

이러한 해결책들을 조합하여 사용하면 환경변수 미적용 문제를 효과적으로 해결할 수 있습니다. 특히 환경변수 검증과 디버깅 도구를 함께 사용하면 문제를 빠르게 진단하고 해결할 수 있습니다.

profile
일용직 개발자. freetercoder@gmail.com

0개의 댓글