PHP

include와 namespace

프로그램은 작고 단순한 것에서 크고 복잡한 것으로 진화한다. 그 과정에서 코드의 재활용성을 높이고, 유지보수를 쉽게 할 수 있는 다양한 기법들이 사용된다. 그 중의 하나가 코드를 여러개의 파일로 분리하는 것이다. 이를 통해서 얻을 수 있는 효과는 아래와 같다.

  • 자주 사용되는 코드를 별도의 파일로 만들어서 필요할 때마다 재활용할 수 있다.
  • 코드를 개선하면 이를 사용하고 있는 모든 애플리케이션의 동작이 개선된다.
  • 코드 수정 시에 필요한 로직을 빠르게 찾을 수 있다.
  • 필요한 로직만을 로드해서 메모리의 낭비를 줄일 수 있다.

include란?

PHP에서는 필요에 따라서 다른 PHP 파일을 코드 안으로 불러와서 사용할 수 있다. 그 방법에 대해서 알아보자.

include가 없다면

우선 include가 없는 애플리케이션을 하나 만들어보자. 이 코드의 파일명은 1.php 다.

<?php
function welcome(){
    return 'Hello world';
}
echo welcome();
?>

위의 코드는 아무런 문제가 없다. 하지만 welcome 함수가 자주 사용되는 것이라고 가정해보자. 이런 경우 이것이 필요할 때마다 이 함수를 정의해서 사용하는 것은 유지보수도 어렵고 낭비가 될 것이다. 이럴 때 include가 필요하다. 함수 welcome을 include해보자.

include의 사용

새로운 파일을 만든다. 이름은 greeting.php다.

greeting.php

<?php
function welcome(){
    return 'Hello world';
}
?>

새로운 파일을 만들고 아래와 같이 greeting.php를 인클루드한다.

2.php

<?php
include 'greeting.php';
echo welcome();
?>

이전 예제와 비교했을 때 결과는 같다. 하지만 함수 welcome을 외부 파일로 분리했다. 다음은 위의 코드에 대한 분석이다.

include 'greeting.php';

include는 외부의 php 파일을 로드할 때 사용하는 명령이다.

PHP는 외부의 php 파일을 로드하는 방법으로 4가지 형식을 제공한다. 형식의 종류는 아래와 같다.

  • include
  • include_once
  • require
  • require_once

include와 require의 차이점은 존재하지 않는 파일의 로드를 시도했을 때 include가 warning를 일으킨다면 require는 fatal error를 일으킨다는 점이다. fatal error는 warning 보다 심각한 에러이기 때문에 require가 include 보다 엄격한 로드 방법이라고 할 수 있다.

_once라는 접미사가 붙은 것은 파일을 로드 할 때 단 한번만 로드하면 된다는 의미다.

네임스페이스

네임스페이스가 무엇인가를 정의하기에 앞서서 파일을 생각해보자. 파일은 데이터를 보관하고 있는 일종의 컨테이너다. 그리고 이 컨테이너는 파일명으로 식별이 된다. 파일의 수가 많아지면서 파일을 관리하는 것이 점점 어려워진다. 그래서 고안된 것이 바로 디렉토리다. 디렉토리를 이용하면 같은 이름의 파일이 하나의 컴퓨터에 존재할 수 있다. 파일명의 충돌을 회피 할 수 있게 된 것이다. 네임스페이스란 간단하게 디렉토리와 같은 것이라고 생각하자. 하나의 에플리케이션에는 다양한 모듈을 사용하게 된다. 그런데 모듈이 서로 다른 개발자에 의해서 만들어지기 때문에 같은 이름을 쓰는 경우가 생길 수 있다. 이런 경우 먼저 로드된 모듈은 나중에 로드된 모듈에 의해서 덮어쓰기 되기 때문에 이에 대한 대책이 필요하다. 네임스페이스가 필요해지게 되는 것이다. 

만약 환영인사를 언어별로 다르게 하고 싶다면 어떻게 해야 할까? 3개의 파일을 만든다.

greeting_en.php

<?php
function welcome(){
    return 'Hello world';
}
 위의 코드에는 PHP 구문의 종료를 의미하는 닫히는 기호가 없다. 닫히는 기호는 생략이 가능하다.

greeting_ko.php

<?php
function welcome(){
    return '안녕세계';
}

5.php

<?php
require_once 'greeting_ko.php';
require_once 'greeting_en.php';
echo welcome();
echo welcome();
?>

위의 코드는 아래와 같은 에러를 발생시킨다.

Fatal error: Cannot redeclare welcome() (previously declared in D:\BitNami\wampstack-5.4.12-0\apache2\htdocs\include\greeting_ko.php:3) in D:\BitNami\wampstack-5.4.12-0\apache2\htdocs\include\greeting_en.php on line 4

로드한 두개의 파일 모두 welcome라는 함수를 선언했기 때문이다. PHP에서는 함수의 중복 선언을 허용하지 않는다. 이런 경우 네임스페이스를 사용할 수 있다. 아래와 같이 로드되는 파일의 내용을 수정해보자.

greeting_en_ns.php

<?php
namespace language\en;
function welcome(){
    return 'Hello world';
}

greeting_ko_ns.php

<?php
namespace language\ko;
function welcome(){
    return '안녕하세요';
}

6.php

<?php
require_once 'greeting_ko_ns.php';
require_once 'greeting_en_ns.php';
echo language\ko\welcome();
echo language\en\welcome();
?>

로드되는 파일의 초입에 키워드 namespace를 이용해서 네임스페이스를 만들었다. 그리고 네임스페이스를 사용할 때는 함수 앞에 네임스페이스의 이름을 붙여서 사용하면 된다. 이로서 동일한 이름의 함수를 하나의 php 에플리케이션 안에서 사용할 수 있게 되었다.

하나의 파일에는 복수의 네임스페이스가 존재 할 수도 있다.

greeting_lang.php

<?php
namespace language\en;
function welcome(){
    return 'Hello world';
}
namespace language\ko;
function welcome(){
	return '안녕세계';
}
<?php
require_once 'greeting_lang.php';
echo language\ko\welcome();
echo language\en\welcome();
?>

네임스페이스는 함수 뿐만 아니라 클래스와 상수에 대해서도 사용할 수 있다. 네임스페이스에 대한 자세한 내용은 아래의 자료들을 참고하자.

댓글

댓글 본문
작성자
비밀번호
  1. NamJin Kim
    감사합니다
  2. 신입1
    첫번째 영상에서 welcome 함수에 echo가 없어서 출력은 안되지 않나요?
    호출할때마다 hello world가 출력된다고 설명하셔서 글남겨용
  3. enqn1992
    글에 첨부된 링크 중 한글버전 링크를 보니 이런글이 있네요
    '... 함수를 호출할 때에는 네임스페이스 맨 앞에 \ 를 붙여야 합니다.'
    글 내용을 보니 네임스페이스를 지정할 땐 맨 앞에 \가 없지만, 함수를 호출할 때는 \를 최상위 디렉터리로 생각하여 네임스페이스 경로 맨 앞에 꼭 붙여야 한다고 하네요

    덕분에 공부하고 갑니다~

    +방금 해보니 저는 함수 호출 시 경로 맨 앞에 \가 없어도 잘 되네요 음?
    대화보기
    • 아래와 같은 내용이 한 파일 안에서 다 실행하면 "Call to undefined function" 이라는 Fatal 에러가 뜹니다.
      이유가 무엇일까요??
      <?php

      namespace language\kr;
      function welcome() {
      return '안녕 세계';
      }
      namespace language\en;
      function welcome() {
      return 'Hello world';
      }
      echo language\kr\welcome();
      echo language\en\welcome();
      ?>
    • pakellie
      마지막 강의에서 소스 실행시키는데 잘 안됩니다..
      해결하신분 잇으신가요?
    • 오덕소희
      echo language\ko\welcome();
      echo language\en\welcome();
      이렇게 입력하면 함수를 못찾네요!!

      echo \language\en\welcome()
      echo \language\ko\welcome();

      이렇게했더니 됬습니다.
      대화보기
      • JustStudy
        고맙습니다
      • SK Kim
        x 내용으로 echo "test"; 라고 하면
        include x; #1
        include_once x; #2
        include x; #3
        include x; #4
        의 경우 x를 3번(1 3 4) 불러드리네요.
        include_once는 동일한게 이미 include된 상태이면 include하지 않는다로 생각하는데 맞을거 같습니다.
      • 네임스페이스가 이런거였군요..!
        잘 배워갑니다~
      • iam777
        감사합니다. 정말 잘 이해가 되고 있습니다.
      • silverwing
        php 5.3버전 이후에서만 사용가능한것 같습니다.
        대화보기
        • ㅁㅅㅈ
          <?php
          require_once 'test1.php';
          require_once 'test2.php';
          echo language\ko\welcome();
          echo language\en\welcome();
          ?>
          강의에 나온대로 이렇게 코딩하면
          Warning: Unexpected character in input: '\' (ASCII=92) state=1 in C:\APM_Setup\htdocs\test\test3.php on line 4
          Parse error: syntax error, unexpected T_STRING, expecting ',' or ';' in C:\APM_Setup\htdocs\test\test3.php on line 4
          이렇게 나오는데 아무래도 echo 뒤에 \가 들어있는 스트링이 오면 안되는 듯하네요....
          에코 뒤에 있는 부분을 따옴표 안에 넣으면
          Parse error: syntax error, unexpected T_STRING in C:\APM_Setup\htdocs\test\test1.php on line 2
          이렇게 상속된 그 전의 파일에서 namespace를 정의하는 부분의 스트링이 걸리는군요...

          그냥 제가 사용하는 버전이 지원을 안하는건가요?
        • omaly
          namespace 지정전에 다른 코드를 삽입하면 에러가 발생합니다. 문서포팻이나 개발환경, 웹서버환경에 따라 차이가 있긴 하지만 php구문 이전에 공백을 허용하지 않는 경우도 있습니다(UTF-8 인코딩에서의 Bytes Order Mark문제). 다음과 같은 경우 에러가 일어납니다.

          (1) error
          <?php
          header("Content-Type:text/html; charset=utf-8");
          namespace language\ko;
          function sayHello() {
          return "내가 고자라니...";
          }
          ?>

          (2) error
          <html>
          <body>
          <?php
          namespace language\ko;
          function sayHello() {
          }
          ?>
          </body>
          </html>

          (3) error
          -----공백-------
          <?php
          namespace language\ko;
          function sayHello() {
          }
          ?>



          # php구문안에 주석이나 공백은 허용됩니다.

          (4) not error
          <?php
          공백
          namespace language\ko;
          ?>

          (5) not error
          <?php
          # comment
          namespace language\ko;



          # 한글을 출력코자 한다면 호스트 파일에 적용하면 됩니다.

          main.php
          <?
          header("Content-Type:text/html; charset=utf-8");

          include_once "language_ko.php";
          print language\ko\sayHello();
          ?>
          대화보기
          • 2015-11-16
            저녁 6시가 넘어가면 버퍼링때문에 동영상 강좌를 보기가 힘드네요....
          • 코딩!
            만에 하나 중복된 함수의 이름이 있을경우엔 namespace를 써서 에러를 방지하는군요!
          • 천국나무
            php5.x 이상부터 되는것으로 알고있습니다.
            낮은 버전 에서는 지원 안될겁니다.^^
            대화보기
            • 이용주
              일부 php 버전에서는 안되는거 같아요 제가 웹 호스팅을 3개쓰는데 그중에 1곳만 되네요. php 버전차이가 있나 봅니다,. ^^;;
            • 어떤 프로그램을 어떻게 업그래이드 하셨는지 궁금합니다.
              대화보기
              • 나은성
                네임스페이스의 개념을 설명해주셨는데 보충이 필요할거 같습니다.


                저도 막 배우는 단계지만
                네임스페이스를 실제로 이런식으로 쓰이는 경우는 거의 없고 대부분 Use 키워드를 사용하는데
                그부분의 언급이 없는것은 아쉬운 부분입니다.
              • o그림자o
                궁금해서 그러는데요... namespace 뒤에 language\en; 디렉토리처럼 쓴다고 했는데..
                language\en의 디렉토리 명은 임의로 정하는 건가요?
              • egoing
                고맙습니다!
                대화보기
                • 오정민
                  사소한 오타 보고 드립니다.^^;;

                  네임스페이스 동영상 아래 2번째 라인의
                  "그리고 이 컨텐이너는 파일명으로 식별이 된다."
                  : "컨텐이너는" => "컨테이너는"


                  좋은 강의 잘 보고 있습니다. 항상 감사 드립니다^^
                • 비기너
                  <meta charset="utf-8" />

                  이 구문은 한글이 깨지는 것을 잡아주는 구문입니다.
                  해당 에러 메시지와는 상관없는 구문이죠.
                  대화보기
                  • 강윤호
                    <meta charset="utf-8" />
                    <?php

                    ?>

                    저걸 추가해도
                    Fatal error: Namespace declaration statement has to be the very first statement in the script in C
                    이러한 에러가 또 뜨는데 이런경우엔 어떻게 해야하나요??
                    php버전도 확인해보았지만 5.4였습니다..
                  • rustypassion
                    아고.. 감기 조심하셔요.
                    아프신것 같은데도 강의를 제작해주셨네요.
                    감사합니다.

                    더 열심히 공부해야 하겠습니다.
                  • 요섭아빠
                    감사합니다. 좋은 강의 잘 듣고있습니다.
                  • Allen Cho
                    <meta charset="utf-8" />
                    <?php

                    ?>

                    형식으로 작성해 보세요.
                    대화보기
                    • zyavermi
                      깨지는 건 인코딩 때문이 아닐까요?
                      대화보기
                      • Sozzi
                        namespace language\ko 에서 리턴해주는 값은 꺠지는데 어떻게 된거죠?
                      • 샤핀
                        항상 좋은 강의 감사합니다. ^^.
                      • 샤핀
                        include 강좌 코드 설명에서 include_once 설명하실 때 좀 이상해서 질문드릴께요.
                        include 강좌 (07:43부분)

                        greeting.php의
                        <?php
                        function welcome(){
                        return 'Hello world';
                        }

                        welcome();
                        ?>
                        와 같은 상황 일 때, welcome 함수 정의 부에 echo 'hello world'라고 정의 되어 있지 않기 때문에... 그러니까 return 'hello world'라고만 되어 있기 때문에... welcome();와 같이 되어 있더라도 출력은 되지 않는다고 해야 하지 않을까요..

                        만약에 설명하시려던 것처럼 출력을 하게 하려면,
                        welcome(); 가 아니라
                        echo welcome(); 로 설명을 하셔야 할 거 같습니다. 헷갈려서요 ^^;;
                      • JPARK
                        namespace 사용할때에 범위가 궁금하여 한번 실험해봤는데 한번 선언한 namespace는 다른 namespace가 선언되기 전까지 영향을 주는것 같습니다.
                        한파일에만 유일하게 존재하는 함수를 선언할때도 namespace를 붙여서 선언하는 것처럼 선언하는 불편함이 있네요..
                        혹시 다른 돌파구를 찾으신 분들 알려주세요!!
                      • JPARK
                        include 하는 파일이 서로 다른 폴더에 있으면 어떻게 선언해야되나요??
                      • wonjun
                        인클루드한 파일의 경로가 틀리거나 파일 이름이 틀린거 같은데요????
                        대화보기
                        • 장성규
                          include(./lib/top_login1.php) [function.include]: failed to open stream: No such file or directory in C:\APM_Setup\htdocs\index.php on line 11
                          위에 있는 저건 무슨 뜻인가요?ㅜㅜ
                          include() [function.include]: Failed opening './lib/top_login1.php' for inclusion (include_path='.') in C:\APM_Setup\htdocs\index.php on line 11
                          이건 또 무슨 뜻인지 모르겟네요ㅜㅜ 책에 있는거랑 비교를 했는데도 틀린게 없다고 생각하는데..
                        • 히시기
                          강의 감사합니다!
                        • egoing
                          어이쿠 고맙습니다!
                          대화보기
                          • openkwang
                            "새로운 파일을 만든다. 이름은 greeting.py다."
                            =>
                            "새로운 파일을 만든다. 이름은 greeting.php다."

                            오타 발견하여 보고 드립니다.
                          • public^^
                            네임스페이스는 php5.2 에서는 안되나 보네요.
                            검색해서 업글하니 잘 작동하네요.
                          • egoing
                            어떤 PHP 파일을 한번만 로드해야 하는 경우 include_once, 여러번 로드해야 하는 경우 include를 쓴다고 보시면 될 것 같습니다.
                            대화보기
                            • Finisher
                              저도 조금 헷갈리는 개념이라 찾아보다가 나름 정리가 된 것 같은데요

                              작업하는 php파일에서 여러개의 php파일을 가져와야 할 경우 include를 쓰고,
                              하나의 php파일을 로드할 경우 include_once를 쓰는 것으로 이해하면 되나요?
                            • egoing
                              프로그램이 커지면 의도하지 않게 include가 여러번 사용될 수 있습니다. 특히 프로그래밍은 여러 모듈들을 사용하는 경우가 많기 때문에 그런 경우가 생길 수가 있지요.
                              대화보기
                              • 김동진
                                저 궁금한게 있습니다....
                                _once 는 한번만 로드하면 된다고 설명해주셨는데요.

                                그렇다면 php파일이 한번만 로드 되지 않을때도 있단 말씀이신가요 ??
                                그런 경우에 대해서 설명이 없어서 이해가 잘 되지 않습니다...

                                위의 예제에서는 include 로 welcome() 함수를 로드하는 예제를 보았는데.
                                welcome() 함수가 여러번 로드될 필요가 있을까요...
                                그럼 모든 include나 require에서는 _once 를 붙이는게 좋다고 보는데

                                여러번 호출하고 로드될 필요가 있는경우가 과연 무엇인지...
                                너무너무 궁금합니다 이고잉선생님!!
                              • boldn
                                voldn//

                                안녕세계 인데요.. 난독증
                              • voldn
                                안녕하세요 라고 적으시려고 했던 것 같은데,
                                안녕세요 라고 적으셨네요~
                              버전 관리
                              egoing
                              현재 버전
                              선택 버전
                              graphittie 자세히 보기