[PHP] require과 include 그리고 「@」사용법


Study/PHP  2019. 9. 18. 09:00

안녕하세요. 명월입니다.


이 글은 php에서 require과 include에 대한 소개입니다.


프로그램을 관리하기 위해서는 파일 구조를 만드는 것도 중요합니다.

예를 들면, 자바의 경우는 패키지이름이 디렉토리 구조로 들어가고 클래스 이름과 파일명을 일치시키게 만들어서 클래스를 찾을 때 좀 더 빠르게 찾을 수 있도록 구조를 만듭니다.

C#의 경우도 namespace가 디렉토리 구조이고 클래스 이름이 파일명과 일치됩니다.

위 규약은 반드시는 아니지만 가능하면 지키도록 합니다.


PHP의 경우는 .php가 웹페이지의 단위이기 때문에 클래스 이름과 파일명을 일치시키기는 조금 곤란한 부분도 있지만 맞추는게 좋습니다.

그리고 최근 프로젝트에서는 .php로 전개하는 것이 아니고 .htaacess를 이용해 MVC모델로 구성해서 만들기 때문에 .php안에 HTML를 넣지 않습니다.

그렇기 때문에 php도 class명 단위, namespace 단위로 분할해서 만듭니다.


먼저 두개의 페이지를 하나로 합쳐서 보겠습니다.

<?php
  require 'extension.php';
  $obj = new Extension();
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  <?=$obj->getData()?>
</body>
</html>
<?php
  class Extension
  {
    private $data;
    public function __construct()
    {
      $this->data = "hello world";
    }
    public function getData(){
      return $this->data;
    }
  }
?>

위 index.php 파일과 extension.php를 만들었습니다. index.php 파일에서는 require를 통해서 extension.php 파일을 읽어옵니다.

extension.php 파일에서는 class만 넣었기 때문에 실제 localhost/extension.php를 치면 빈 페이지가 호출될 것입니다.

그러나 index.php에서는 class를 선언하고 getData함수를 통해 데이터를 가져오기 때문에 localhost/index.php에서는 hello world 데이터가 나왔습니다.


여기서 require과 include는 사용방법이 비슷합니다. 위 소스에서 require 대신에 include를 넣어도 똑같은 처리가 실행됩니다.

그럼 require과 include의 차이점은 실제 파일이 있고 없고에서 차이가 납니다.

<?php
  require 'extension1.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  GO!!
</body>
</html>

여기서 제가 require로 extension1.php를 참조했습니다.

실제로는 없는 파일입니다. 이럴 경우 require의 경우는 Fatal error를 발생합니다.

위처럼 에러가 발생해서 웹페이지의 GO!!메시지도 표시가 되지 않네요.

그러나 include의 경우는 페이지가 없어도 warning을 발생하고 페이지를 진행합니다.

<?php
  include 'extension1.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  GO!!
</body>
</html>

위 이미지를 보면 확실히 Warning 메시지가 나오고 GO!!라는 메시지가 나왔습니다.

이 전에 에러 메시지 설정 방법에 대해 설명한 적이 있는데 거기서 Warning 메시지를 보이지 않게 해버리면 include로 페이지가 없어도 문제없이 처리가 되겠네요.

링크 - [PHP] Fatal 및 Notice, Warnig 에러 메시지 처리하는 방법

<?php
  error_reporting(E_ALL&~E_WARNING);
  include 'extension1.php';
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  GO!!
</body>
</html>

사실 에러는 반드시 처리해야 하는 항목이므로 위처럼 처리하는건 에러가 났을 경우, 찾지를 못하는 경우가 발생할 수도 있습니다. 매우 좋지 않네요.

그럼 전부다 require를 사용하면 좋지 않겠나 싶겠지만, include는 사용하는 목적이 있습니다.


보통 선언은 require가 맞습니다만, 동적인 로딩을 할 때는 include를 사용해야 합니다.

<?php
  $pagename = 'extension'.$_GET["page"].'.php';
  if(@include $pagename){
    echo "It was loaded";
  } else {
    echo "It was not loaded";
  }
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
</body>
</html>

include로 포함시키는 파일은 string으로 받기 때문에 위처럼 만들 수 있습니다. 파라미터로 page의 값에 따라 불려지는 페이지가 달라지겠네요.

require의 경우는 에러가 발생해 버리기 때문에 페이지가 멈춰서 위와 같은 식을 작성할 수 없습니다.


여기서 include 앞에 「@」마크를 사용했습니다.

「@」의 마크는 페이지 내에 Warning이 발생할 경우 앞에 @를 붙이므로써 true또는 false값을 받을 수 있습니다.

즉, Warning이 발생하지 않으면 true, 발생하면 false값으로 리턴되는 문법입니다.


「@」마크는 PHP내에서 따로 변수를 선언하지 않기 때문에 선언되지 않는 변수를 계산하거나 0으로 나누거나 IO에서 파일이 없거나 등에서 Warning이 발생하는데 그럴 때 사용하면 매우 유용한 키워드입니다.


include와 require는 각각 include_once가 있고 require_once가 있습니다.

이는 어디선가 include가 되었다면 다시 불리지 않는 함수입니다.

<?php
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  <?php 
     require_once 'extension.php';
  ?>
  <br />
  <?php 
     require_once 'extension.php';
  ?>
  <br />
  <?php 
     include_once 'extension.php';
  ?>
  <br />
  <?php 
     include 'extension.php';
  ?>
</body>
</html>
<?php
  echo "hello world";
?>

위 예제를 보시면 첫번째 require_once는 extension.php가 호출된 적이 없기 때문에 표시가 되었습니다. 그러나 두번째 세번째는 한번 호출이 되었기 때문에 호출하지 않습니다.

마지막은 _once가 붙어있지 않기 때문에 이전의 호출 여부와는 관계없이 불리게 됩니다.


참조 - https://andy-carter.com/blog/difference-between-include-and-require-statements-in-php


여기까지 php에서 require과 include에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.