서버 세팅 시 PHP 쪽에서 자주 참고하게 된 항목만 정리한 내용이다. exec로 jar 실행 시 Java 설치, php-zip 설치 오류, Access Denied 발생 시 SELinux 대처, CORS 헤더 설정 방법을 포함한다.
1. PHP에서 외부 실행(exec)·jar 실행 시 — Java 설치
PHP에서 exec()나 shell_exec()로 jar 파일을 실행할 때는 서버에 Java가 설치되어 있어야 한다. 아래처럼 설치한다.
yum install java-1.8.0-openjdk-devel.x86_64
경로가 잡혀 있지 않으면 which java로 확인하고, 필요 시 JAVA_HOME을 설정한다.
2. php-zip 설치 오류 (extension zip 없을 때)
PHP에서 ZipArchive를 쓰려면 zip 확장이 필요한데, yum으로만 설치하면 포함되지 않거나 버전이 맞지 않는 경우가 있다. 이때는 devel·libzip·pecl로 직접 빌드해 넣는 방법을 사용한다. (예시는 PHP 8.1 기준, AWS Linux 2022 등에서 참고한 흐름이다.)
sudo yum install php8.1-devel php-pear libzip libzip-devel
sudo pecl install zip
echo "extension=zip.so" | sudo tee /etc/php.d/20-zip.ini
pecl install이 끝난 뒤 extension=zip.so를 php.d 디렉터리에 넣어야 PHP가 로드한다. 경로는 환경마다 다를 수 있으므로 php -i | grep "Scan this dir"로 추가 설정 디렉터리를 확인한다. 웹 서버(또는 php-fpm) 재시작 후 php -m | grep zip으로 zip이 나오면 정상이다.
AWS Linux 2022에서 php-zip 이슈가 있을 때는 repost.aws 답변도 참고할 수 있다.
3. PHP·아파치에서 Access Denied 나올 때
웹에서 특정 디렉터리나 파일 접근 시 403·Access Denied가 나오면 SELinux 때문인 경우가 많다. SELinux를 끄거나, 필요한 불리언만 켜는 두 가지 방식이 있다.
방법 A — SELinux 비활성화 (재부팅 후에도 유지)
보안 정책을 완전히 끄고 싶을 때 사용한다. 재부팅해도 disabled로 유지된다.
sudo vi /etc/selinux/config
파일 안에서 SELINUX=disabled로 바꾼 뒤 저장하고 재부팅한다. (enforcing → disabled)
방법 B — httpd가 유저 콘텐츠 읽기 허용 (권장)
SELinux는 켜 둔 채로, 아파치에만 "유저 홈 디렉터리 등 콘텐츠 읽기"를 허용하는 방식이다.
sudo setsebool -P httpd_read_user_content 1
-P는 재부팅 후에도 유지되는 옵션이다. 적용 후 웹 서버를 재시작한다.
sudo systemctl restart httpd
방법 C — 임시로 SELinux 완화 (테스트용)
원인 확인만 할 때 사용하며, 재부팅하면 다시 Enforcing으로 돌아간다.
sudo setenforce 0
이렇게 했을 때 접근이 되면 SELinux가 원인인 것이므로, 이후에는 방법 B처럼 불리언으로 필요한 것만 켜는 것이 좋다. setenforce 0으로 테스트해 접근이 되면, httpd_read_user_content 1을 설정한 뒤 setenforce 1로 다시 켜면 된다.
SELINUX=disabled"] G["setsebool -P
httpd_read_user_content 1"] H["ausearch 등으로
로그 확인 후 정책 조정"] I["재부팅 후 적용"] J["httpd 재시작"] end A --> B B --> C C -->|Yes| D C -->|No| K["다른 원인 확인"] D --> E E --> F E --> G E --> H F --> I G --> J H --> J
4. PHP에서 CORS 허용
다른 도메인(프론트 또는 다른 서비스)에서 이 PHP API를 호출할 때 CORS 에러가 나면, 응답 헤더에 허용 출처·메서드를 넣어 준다. 보통 API 진입 스크립트 맨 위, 출력 전에 한 번만 보내면 된다.
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
*는 모든 출처 허용이므로, 운영 환경에서는 필요한 도메인만 지정하는 것이 좋다. 예: Access-Control-Allow-Origin: https://example.com. OPTIONS는 브라우저가 preflight 요청을 보낼 때 사용하므로, GET·POST를 쓰면 OPTIONS도 함께 넣어 둔다. 프론트에서 API 호출 시 CORS 에러가 나면 위 헤더를 출력하면 해결할 수 있다.
5. 자주 발생하는 문제와 대처
exec로 jar 실행 시 "java: command not found"
Java가 설치되지 않았거나 PATH에 없을 때 발생한다. 위처럼 yum으로 Java를 설치한 뒤, 아파치·php-fpm이 사용하는 환경에 PATH가 잡혀 있는지 확인한다. 웹에서 exec를 할 때는 아파치 유저 환경이 사용되므로, 아파치용 스크립트에서 JAVA_HOME을 설정하면 해결된다.
pecl install zip 시 configure 에러
libzip·libzip-devel이 없으면 pecl 설치가 실패한다. libzip 개발 패키지를 설치한 뒤 다시 pecl install zip을 실행하면 된다.
CORS 헤더를 넣었는데 여전히 차단될 때
OPTIONS 요청에 200과 CORS 헤더를 반환해야 브라우저가 본 요청을 보낸다. OPTIONS를 따로 처리하지 않으면 preflight에서 막힐 수 있다. OPTIONS 요청이 오면 헤더만 보내고 200을 반환하는 분기를 넣으면 해결된다.
한 줄 요약
jar 실행용 Java(yum install java-1.8.0-openjdk-devel). php-zip 없으면 php-devel·libzip·pecl install zip 후 extension=zip.so를 php.d에 추가. Access Denied는 SELinux — httpd_read_user_content 1 또는 setenforce 0으로 확인 후 불리언 조정, 필요 시 config에서 disabled. CORS는 header로 Access-Control-Allow-Origin·Allow-Methods(OPTIONS 포함) 출력.
댓글 0