클래스를 사용해야 하나 – 5.이름공간(namespace)

이름공간은 현재 동작하는 프로그램에 정의되어 있는 변수명, 함수명, 클래스명 등과 같은 이름을 기록하기 위한 공간에 관련된 매카니즘을 총칭합니다. PHP에는 아래와 같이 크게 3가지 이름공간이 존재하는 것으로 보입니다.

  • 전역 이름공간 – 함수(또는 클래스) 바깥쪽에서 정의된 이름
  • 지역 이름공간 – 함수(또는 메소드) 안에서 정의된 이름 또는 클래스 안에서 정의된 이름
  • 내장 이름공간 – PHP 자체에 정의된 이름(연산자들과 같은 각종 키워드),
    함수명과 같이 프로그램 어느 곳에서나 제한없이 접근할 수 있는 이름

이와 같이 이름공간이 독립적으로 분리되어 있으므로 동일한 이름이 서로 다른 지역에 존재할 수 있도록 허용하고 있습니다.

위의 소스와 같이 같은 함수 내에서 지역변수와 전역변수가 동시에 나타난다면 먼저 전역 이름공간을 참조하게 될 것입니다. 따라서 이 소스를 실행하면 아래와 같이 나타날 것입니다. 위의 소스와 같이 함수 내에서 사용되는 변수명은 지역 이름공간에서 찾게 됩니다. 전역 이름공간의 이름을 사용하려면 global 키워드로 먼저 선언해주어야 합니다.

  • 지역 이름공간의 변수
  • 전역 이름공간의 변수

함수마다 별도의 이름공간을 제공해 주기때문에 앞에서 설명한 모듈화가 가능하게 되지요.

만약 이름공간 안에 없는 이름을 참조한다면 어떻게 될까요? 물론 어떻게 처리하는가에 대한 매카니즘은 그 대상이 변수냐 함수냐 등에 의해 다르게 처리되겠지요. 변수인 경우라면 참조한 위치가 전역 위치면 전역 이름공간을 살펴보고 없으면 전역 이름공간에 새로운 이름을 생성합니다. 그리고 참조한 위치가 함수 내와 같은 지역 위치면 해당 함수의 지역 이름공간을 살펴보고 없으면 이 공간에 새로운 이름을 생성합니다.

함수라면 좀더 복잡할 것입니다. 함수를 정의하면서 함수명을 이름공간에 생성하려고 할 때 이미 해당 이름공간에 함수명이 있다면 중복된 함수 정의라는 에러메시지를 보여줄 것입니다. 반면에 함수를 실행하려고 이름공간을 참조하였을 때 이 이름공간에 해당 함수명이 없다면 정의된 함수가 없다고 에러메시지를 보여줄 것입니다.

여러 해동안 웹프로그래밍을 하다보면 나도 모르는 사이에 많은 함수들이 하드디스크에 쌓여가는 것을 볼 수 있습니다. 이 양은 적지 않은 분량으로 이러한 함수를 이용하여 파일 입출력을 다루고, 문자열을 편리하게 처리하도록 도움받게 됩니다.

그런데 이러한 함수의 분량이 쌓여가다보면 개발자는 동일하거나 비슷한 기능의 함수를 다시 작성하는 경우도 빈번하고 더 나아가 동일한 함수명을 사용하는 경우도 발생합니다.

PHP 는 이와 같이 동일한 함수명을 중복하여 정의하여 사용할 경우 에러를 발생시켜 줍니다. 이와 같이 프로그램에서 중복된 이름을 사용할 때 이를 방지하기 위한 매카니즘이 동작하여 이에 의해 중복된 이름을 사용하였을 때 강제적으로 에러를 발생시키도록 하는 것입니다. 이와 같이 해당 이름공간 안에 있는 모든 함수는 자신만의 이름을 가지게 됩니다.

PHP 에서는 대부분 함수를 이용하여 라이브러리를 구축할 때 파일 단위로 묶어 놓게 됩니다. 그런데 파일 단위로 묶여 있는 라이브러리마다 라이브러리 내에서 발생하는 사용자 정의 에러를 처리하기 위하여 에러를 처리하는 함수를 정의하여 사용하게 되지요. 예를 들면 아래와 같이 warning() 함수를 정의하게 됩니다.

이러한 에러 처리 함수는 각 라이브러리마다 조금씩 다르게 정의할 수도 있고 때에 따라서는 동일하게 정의할 수도 있겠지요. 그런데 만약 a라는 라이브러리와 b라는 라이브러리에 모두 이와 같은 에러 처리 함수 warning() 함수가 있고 우연히 동일한 웹페이지에서 a와 b 라이브러리를 모두 불러들였다고 하지요. 웹페이지를 실행하면 PHP는 당연히 이름공간 매카니즘에 의해 중복된 함수를 정의하였다는 에러를 신속히 보여줄 것입니다.

여러분은 이러한 에러를 방지하기 위해 나름대로 대책을 세우셨을 것입니다. 에러 처리 함수를 별도의 파일로 구성하여 놓을 수도 있겠지요. 그리고 a와 b 라이브러리에서 에러 처리 함수가 포함된 파일을 포함(include)하겠지요.

아니면 a라는 라이브러리의 에러 처리 함수명을 warning() 대신에 a_warning()로 변경하고, b라는 라이브러리의 에러 처리 함수명을 b_warning()로 변경할 수도 있겠지요.

결국 어떠한 대책이 되었든지간에 함수를 이용하는 한은 불편하기도 하고 실수할 가능성도 상당히 높습니다. 그래서 PHP는 함수라는 도구보다 더욱 강력한 도구인 클래스라는 것을 우리에게 선물로 주었습니다. 위의 예에서 발생한 이름공간 문제를 클래스를 이용하여 해결하여 보지요.

여기서 클래스 a와 b가 동일한 파일에 있어도 좋고 다른 파일에 있어도 관계없겠지요. 일단 위와 같이 클래스 a, b 내에 동일한 이름의 에러 처리 함수(메소드) warning()를 정의하여 놓더라도 이름공간 문제가 발생하지 않습니다. 왜냐하면 클래스 a와 b는 서로 다른 이름공간을 가지게 되니까요.

그런데 에러 처리 함수를 클래스의 멤버로 정의하지 않고 일반 함수로 정의하게 되면 이 함수명은 전역 이름공간(global name space)에 있게 됩니다. 동일한 이름공간 내에서는 중복된 이름을 가질 수 없기 때문에 결국 일반 함수로 정의하면 문제가 발생하는 것이지요.

반면 클래스는 각 클래스마다 독립적인 이름공간을 가지기 때문에 함수명이 중복되어도 에러가 발생하지 않습니다. 아울러 클래스에서는 오버로딩, 오버라이딩과 같은 특성을 제공하기 때문에 이름공간의 융통성(?)이 막강하지요.

[주의] PHP에서는 오버로딩을 지원하지 않습니다. 오버라이딩도 너무 포괄적(?)으로 지원합니다.

함수를 통해 모듈화를 하더라도 여러 개의 함수가 모이다보면 함수명의 중복으로 인하여 문제가 발생하는 것입니다. 일반 함수명은 모두 동일한 전역 이름공간에 생성되며 따라서 함수가 많을 때는 중복될 가능성이 많아지게 됩니다. 중복되지 않도록 개발자가 직접 관리해야 하는데 사람이라는 것이 워낙 실수도 많고 기억에도 한계가 있다보니 자연히 한계에 부딪치게 되지요.

결국 여러 개의 함수로 구성된 라이브러리와 같은 경우에서는 라이브러리 전체를 하나의 모듈로 묶어줄 수 있는 강력한 모듈화 도구인 클래스로 감싸줌으로써 함수명의 중복에 따른 문제를 쉽게 해결할 수가 있는 것이지요.

답글 남기기