PHP 코드를 작성하다 보면 갑자기 화면이 하얀색으로 변하거나 '<br /><b>Parse error</b>: syntax error, unexpected' 같은 메시지가 떠본 경험이 있을까? 대부분의 개발자들은 이런 파스 에러가 뜨면 코드 전체를 뒤지느라 시간을 낭비한다. 다만 원인은 의외로 간단한 경우가 많다. 이번에는 PHP 파스 에러의 정확한 원인이 뭔지, 왜 발생하는지, 어떻게 찾아서 해결하는지 실무에서 바로 쓸 수 있는 방법을 정리해서 소개하겠다.

 

1단계: PHP 파스 에러 기초 이해하기
PHP 파스 에러(Parse Error)는 PHP 인터프리터가 코드를 읽으면서 문법이 맞지 않다고 판단할 때 발생한다. 즉, 코드가 실행되기 전 단계에서 이미 문제가 있다는 뜻이다. 자바스크립트의 SyntaxError와 비슷하지만, PHP는 서버 에러이므로 브라우저에서 보이지 않고 로그에만 남는 경우도 있다.

파스 에러가 떠도 에러 메시지가 정확한 라인 번호를 가리킴에도 불구하고, 실제 문제는 그 줄보다 위에 있는 경우가 많다. 이게 초보 개발자들을 헷갈리게 하는 가장 큰 이유다.

 

가장 흔한 파스 에러 5가지
에러 유형 원인 예시
unexpected '{' 중괄호 개수 맞지 않음 if ($x == 1) { 뒤에 } 빠짐
unexpected 'echo' (T_ECHO) 세미콜론 누락 $x = 10 echo $x;
unexpected '$변수' 인용부호 닫지 않음 echo "hello $x;
unexpected 'if' (T_IF) 연산자나 쉼표 빠짐 $arr = [1, 2 if ($x) {}
unexpected '==' 비교 연산자를 할당에 사용 if $x == 1 (괄호 빠짐)

 

2단계: 실전 디버깅 방법
PHP 파스 에러를 찾으려면 몇 가지 체계적인 방법을 따르는 게 좋다.

방법 A: 에러 로그 확인하기
아파치나 Nginx의 로그 파일을 보면 정확한 라인 번호가 나온다.

# Apache 에러 로그
tail -f /var/log/apache2/error.log

# Nginx 에러 로그
tail -f /var/log/nginx/error.log

# 또는 PHP 내부 에러 로그
tail -f /var/log/php-errors.log

방법 B: PHP 문법 검사 명령어
파일을 직접 실행하지 말고 문법만 검사할 수도 있다.

# 단일 파일 검사
php -l /path/to/file.php

# 디렉토리 전체 검사
for file in *.php; do php -l "$file"; done

이 명령어는 파스 에러가 있으면 정확한 라인 번호와 함께 에러를 출력한다. 예를 들어 10줄에 중괄호가 빠졌으면 'Parse error: syntax error, unexpected 'EOF' in /path/to/file.php on line 10'이라고 나온다.

방법 C: 에디터의 린터(Linter) 활용
VSCode나 PhpStorm 같은 에디터를 쓰면 실시간으로 파스 에러를 알려준다. PHP Intelephense 플러그인을 설치하면 더 빠르게 문제를 찾을 수 있다.

 

3단계: 실제 코드 예제로 배우기

예제 1: 세미콜론 누락

✗ 잘못된 코드 (세미콜론 빠짐)
<?php
$x = 10
echo $x;  // Parse error: syntax error, unexpected 'echo'
?>

PHP는 한 줄의 코드가 끝났음을 세미콜론으로 인식한다. 위 코드에서 인터프리터는 '$x = 10'이 아직 끝나지 않았다고 생각하고 다음 줄 'echo'를 예상하지 못했다고 말한다. 에러 메시지는 10번 줄에 문제가 있다고 하지만, 실제로는 9번 줄에 세미콜론을 붙여야 한다.

✓ 올바른 코드
<?php
$x = 10;
echo $x;  // 10
?>

예제 2: 중괄호 개수 맞지 않음

✗ 잘못된 코드 (닫는 괄호 빠짐)
<?php
if ($age >= 18) {
    echo "성인입니다.";
// 여기서 } 빠짐

echo "다음 코드";  // Parse error: syntax error, unexpected 'echo'
?>

이 경우 if 블록이 닫혀있지 않아서 인터프리터는 계속 if 블록 내부라고 생각한다. 따라서 다음 echo 문이 이상하게 보인다.

✓ 올바른 코드
<?php
if ($age >= 18) {
    echo "성인입니다.";
}  // 괄호 추가

echo "다음 코드";  // 정상 출력
?>

예제 3: 인용부호를 닫지 않음

✗ 잘못된 코드 (큰따옴표 안 닫음)
<?php
$text = "안녕하세요
$name = "홍길동";  // Parse error: syntax error, unexpected '"'
?>

첫 번째 문자열이 닫혀있지 않으면 PHP는 계속 문자열이라고 생각한다. 다음 줄의 $name은 따옴표 안쪽 문자의 일부로 해석된다.

✓ 올바른 코드
<?php
$text = "안녕하세요";
$name = "홍길동";
echo $text . $name;  // 안녕하세요홍길동
?>

예제 4: if문에 괄호 빠짐

✗ 잘못된 코드 (if 뒤의 괄호 빠짐)
<?php
$score = 95;
if $score >= 90 {  // Parse error: syntax error, unexpected '=='
    echo "A학점";
}
?>
if 문법은 반드시 'if (조건) { }'이어야 한다. 괄호를 빼면 PHP가 문법을 인식하지 못한다.

✓ 올바른 코드
<?php
$score = 95;
if ($score >= 90) {  // 괄호 추가
    echo "A학점";
}
?>

예제 5: 배열 문법 오류

✗ 잘못된 코드 (쉼표 빠짐)
<?php
$arr = [
    'name' => '홍길동'
    'age' => 30,  // Parse error: syntax error, unexpected '=>'
];
?>
배열 요소 사이에는 쉼표가 필요하다. 위 코드는 name 뒤에 쉼표가 없어서 PHP가 다음 줄의 'age' => 30을 이상하게 해석한다.

✓ 올바른 코드
<?php
$arr = [
    'name' => '홍길동',  // 쉼표 추가
    'age' => 30,
];
echo $arr['name'];  // 홍길동
?>

 

4단계: 주의사항과 흔한 실수

✗ 잘못된 습관: 에러 메시지의 라인 번호를 맹신하기
PHP 파스 에러의 라인 번호는 문제가 '발견된' 위치이지, 문제가 '있는' 위치가 아니다. 에러가 15번 줄이라고 해도 실제 원인은 14번 줄일 수 있다. 따라서 에러 메시지의 몇 줄 위를 먼저 확인하는 습관이 필요하다.

✓ 올바른 습관: 에러 메시지의 라인 주변을 넓게 확인하기
에러 메시지에 나온 라인뿐만 아니라 그 이전 5~10줄도 함께 검토하자. 특히 세미콜론, 괄호, 따옴표 같은 작은 것들을 놓치기 쉽다.

✗ 잘못된 습관: 에러 로그 확인 안 하기
많은 초보 개발자들은 에러가 날 때 브라우저 화면만 본다. 하지만 PHP 파스 에러는 로그에만 남고 화면에는 아무것도 안 나온다.

✓ 올바른 습관: 항상 에러 로그를 먼저 확인하기
개발 중에는 'tail -f' 명령어로 실시간 로그를 열어두고 작업하자. 이렇게 하면 에러가 나는 즉시 원인을 알 수 있다.

✗ 잘못된 습관: php.ini에서 에러 표시 안 켜두기
프로덕션 서버에서는 에러를 화면에 띄우지 않는 게 맞지만, 개발 환경에서는 반드시 켜두어야 한다.

✓ php.ini 설정 (개발 환경)
error_reporting = E_ALL
display_errors = On
error_log = /var/log/php-errors.log

 

5단계: 핵심 정리 및 다음 행동

PHP Parse Error는 매우 흔한 문제지만, 원인을 체계적으로 찾는 방법을 알면 금방 해결할 수 있다. 세미콜론, 괄호, 따옴표 같은 문법 요소를 놓치지 않는 것이 핵심이다. 작은 실수 하나가 전체 코드 실행을 멈추기 때문이다.

이 글에서 소개한 'php -l' 명령어와 에러 로그 확인 습관이 모여서 디버깅 시간을 대폭 줄일 수 있을 것이다. 지금 바로 개발 환경의 error_reporting과 display_errors를 설정하고, 에디터에 PHP 린터를 설치한 뒤, 파스 에러가 날 때마다 로그를 먼저 확인하는 습관을 들이면, 앞으로 같은 문제로 헤매지 않을 수 있을 것이다.