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. 다시시작
    완료
  2. 고스트프리
    네임스페이스 신기하네요... 감사합니다.
  3. kimjs9105
    include는 다른 언어에도 사용해 보아서 익숙했는데 네임스페이스는 신기한 개념이네요! 링크따라서 한번 더 공부해봐야겠어요~ 감사합니다~^^
  4. spiritord
    감사합니다
  5. 잘 봤어요^^
  6. 심화평
    2017.07..17 감사합니다
  7. ttt2rrxx
    include 강의 8분 38초에서 설명하시는 데로 하면 include 중복오류가 나는거 아닌가요 ....?
  8. treehouse
    호우
  9. HGERRARD
    egoing님 강의는 이해가 잘 됩니다 !!
  10. 김세창
    잘보고갑니다~^^ ㅎ
  11. Scott Kim
    PHP Version 5.3부터 네임스페이스가 지원될 것입니다.
    apmsetup은 PHP Version 5.2일거에요
    대화보기
    • php가첫취업?
      프로그램 사용하는게 뭐냐에 따라 구동이 잘되고 안되고의 차이가 있네요;;;
      전 참고로apmsetup으로 구동하고 있는데;;;네임스페이스 구동이 잘 안되네요 ㅠㅠ
    • 고맙습니다~
    • Fatal error: Call to undefined function language\en\language\kr\welcome() in C:\
      오류메세지인데요.
      language\en\language\kr\welcome()
      이걸보시면 지금 네임스페이스가 language\en\language\kr 이렇게 설정되있는 걸 보실수 있죠.
      네임스페이스를 language로 바꾸어주시고
      echo language\kr\welcome();
      echo language\en\welcome();

      이부분을

      echo kr\welcome();
      echo en\welcome();

      이렇게 바꾸어 주시면 되어요.

      <?php

      namespace language\kr;
      function welcome() {
      return '안녕 세계';
      }
      namespace language\en;
      function welcome() {
      return 'Hello world';
      }

      namespace language;

      echo kr\welcome();
      echo en\welcome();
      ?>
      대화보기
      • 하나의 파일 아래에 여러가지 네임스페이스를 만드려면 namespace를 선언한 바로 밑줄에 함수를 선언해야
        하는 것이겠네요 잘봤습니다
      • NamJin Kim
        감사합니다
      • 신입1
        첫번째 영상에서 welcome 함수에 echo가 없어서 출력은 안되지 않나요?
        호출할때마다 hello world가 출력된다고 설명하셔서 글남겨용
      • enqn1992
        글에 첨부된 링크 중 한글버전 링크를 보니 이런글이 있네요
        '... 함수를 호출할 때에는 네임스페이스 맨 앞에 \ 를 붙여야 합니다.'
        글 내용을 보니 네임스페이스를 지정할 땐 맨 앞에 \가 없지만, 함수를 호출할 때는 \를 최상위 디렉터리로 생각하여 네임스페이스 경로 맨 앞에 꼭 붙여야 한다고 하네요

        덕분에 공부하고 갑니다~

        +방금 해보니 저는 함수 호출 시 경로 맨 앞에 \가 없어도 잘 되네요 음?
        대화보기
        • Sajuk
          아래와 같은 내용이 한 파일 안에서 다 실행하면 "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하지 않는다로 생각하는데 맞을거 같습니다.
          • LILIS
            네임스페이스가 이런거였군요..!
            잘 배워갑니다~
          • 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
                            현재 버전
                            선택 버전
                            graphittie 자세히 보기