네임스페이스를 사용하면 사용자가 만든 속성 및 메서드의 가시성을 제어할 수 있습니다. public, private, protected 및 internal 액세스 제어 지정자를 내장 네임스페이스로 간주할 수 있습니다. 이러한 미리 정의된 액세스 제어 지정자가 사용자 요구에 적합하지 않은 경우 직접 네임스페이스를 만들 수 있습니다.
ActionScript 구현의 구문 및 세부 사항이 XML의 구문 및 세부 사항과 약간 다르지만 XML 네임스페이스에 익숙한 사용자에게는 이 설명서의 내용이 낯설게 느껴지지 않을 것입니다. 네임스페이스의 개념은 매우 간단하지만 이전에 네임스페이스를 사용하여 작업한 경험이 없는 경우 이를 구현하려면 특정 용어를 익혀야 합니다.
네임스페이스의 작동을 이해하려면 속성 또는 메서드 이름에 식별자 및 네임스페이스가 항상 포함된다는 점을 이해하는 것이 좋습니다. 식별자는 일반적으로 이름으로 간주되는 것을 말합니다. 예를 들어 다음 클래스 정의에서 식별자는 sampleGreeting과 sampleFunction()입니다.
class SampleCode
{
var sampleGreeting:String;
function sampleFunction () {
trace(sampleGreeting + " from sampleFunction()");
}
}
클래스 등을 정의할 때 네임스페이스 특성을 먼저 지정하지 않으면 해당 정의에 사용된 이름이 기본 internal 네임스페이스로 정규화되므로 동일한 패키지에 있는 호출자만 해당 이름을 참조할 수 있습니다. 컴파일러가 엄격 모드로 설정되어 있는 경우 네임스페이스 특성이 없는 모든 식별자에 internal 네임스페이스가 적용된다는 경고가 표시됩니다. 식별자를 모든 범위에서 사용할 수 있도록 하려면 식별자 이름 앞에 public 특성을 명시해야 합니다. 이전 예제 코드에서 sampleGreeting 및 sampleFunction()에는 모두 internal 네임스페이스 값이 적용됩니다.
네임스페이스를 사용할 때 수행해야 할 세 가지 기본 단계는 다음과 같습니다. 첫 번째, namespace 키워드를 사용하여 네임스페이스를 정의해야 합니다. 예를 들어 다음 코드는 version1 네임스페이스를 정의합니다.
namespace version1;
두 번째, 속성 또는 메서드 선언에서 액세스 제어 지정자 대신 네임스페이스를 사용하여 네임스페이스를 적용합니다. 다음 예제에서는 myFunction() 함수를 version1 네임스페이스에 배치합니다.
version1 function myFunction() {}
세 번째, 네임스페이스가 적용되면 use 지시문을 사용하거나 식별자 이름을 네임스페이스로 정규화하여 참조할 수 있습니다. 다음 예제에서는 use 지시문을 통해 myFunction() 함수를 참조합니다.
use namespace version1;
myFunction();
다음 예제에서 볼 수 있는 것과 같이 정규화된 이름을 사용하여 myFunction() 함수를 참조할 수도 있습니다.
version1::myFunction();
네임스페이스 정의
네임스페이스에는 URI(Uniform Resource Identifier)라는 하나의 값이 포함되며, 이를 네임스페이스 이름이라고도 합니다. URI를 사용하여 네임스페이스 정의를 고유하게 만들 수 있습니다.
두 가지 방법 중 하나로 네임스페이스 정의를 선언하여 네임스페이스를 만듭니다. XML 네임스페이스를 정의하듯이 명시적 URI가 있는 네임스페이스를 정의할 수 있으나 URI를 생략하는 것도 가능합니다. 다음 예제에서는 URI를 사용하여 네임스페이스를 정의하는 방법을 보여 줍니다.
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
URI는 해당 네임스페이스에 대한 고유한 식별 문자열 역할을 합니다. URI를 생략하면 다음 예제에서와 같이 컴파일러에서 URI 대신 고유한 내부 식별 문자열을 만듭니다. 사용자는 이 내부 식별 문자열에 액세스하지 못합니다.
namespace flash_proxy;
URI 사용 여부와 관계없이 한 번 정의한 네임스페이스는 동일한 범위에서 다시 정의할 수 없습니다. 이전에 정의한 네임스페이스를 동일한 범위에서 정의하려고 하면 컴파일러 오류가 발생합니다.
패키지 또는 클래스 내에 네임스페이스가 정의된 경우 적절한 액세스 제어 지정자를 사용하지 않으면 해당 패키지 또는 클래스 외부의 코드에서 네임스페이스를 참조할 수 없습니다. 예를 들어 다음 코드에서는 flash.utils 패키지 내에 정의된 flash_proxy 네임스페이스를 보여 줍니다. 다음 예제에서는 액세스 제어 지정자가 없으므로 flash.utils 패키지 내의 코드에서만 flash_proxy 네임스페이스를 참조할 수 있고 패키지 외부의 모든 코드에서는 참조할 수 없습니다.
package flash.utils
{
namespace flash_proxy;
}
다음 코드에서는 패키지 외부의 코드에서 flash_proxy 네임스페이스를 참조할 수 있도록 public 특성을 사용합니다.
package flash.utils
{
public namespace flash_proxy;
}
네임스페이스 적용
네임스페이스를 적용한다는 것은 정의를 네임스페이스에 배치하는 것을 의미합니다. 네임스페이스에 배치할 수 있는 정의에는 함수, 변수 및 상수가 있으며 사용자 정의 네임스페이스에 클래스를 배치할 수는 없습니다.
예를 들어 public 액세스 제어 네임스페이스를 사용하여 선언된 함수를 살펴보십시오. 함수 정의에서 public 특성을 사용하여 함수를 공용 네임스페이스에 배치하면 모든 코드에서 해당 함수를 사용할 수 있습니다. 네임스페이스를 정의하면 public 특성을 사용할 때와 동일한 방법으로 정의된 네임스페이스를 사용할 수 있으며, 사용자 정의 네임스페이스를 참조할 수 있는 코드에서 해당 정의를 사용할 수 있습니다. 예를 들어 example1 네임스페이스를 정의하면 다음 예제에서 볼 수 있는 것과 같이 example1을 특성으로 사용하여 myFunction() 메서드를 추가할 수 있습니다.
namespace example1;
class someClass
{
example1 myFunction() {}
}
example1 네임스페이스를 특성으로 사용하여 myFunction() 메서드를 선언하면 이 메서드가 example1 네임스페이스에 속하게 됩니다.
네임스페이스를 적용할 때에는 다음 사항에 주의해야 합니다.
각 선언에는 네임스페이스를 하나만 적용할 수 있습니다.
한 번에 둘 이상의 정의에 네임스페이스 특성을 적용할 수 없습니다. 즉, 서로 다른 10개의 함수에 네임스페이스를 적용하려면 10개의 각 함수 정의에 네임스페이스를 특성으로 추가해야 합니다.
또한 네임스페이스와 액세스 제어 지정자는 상호 배타적이므로 네임스페이스를 적용하는 경우 액세스 제어 지정자를 지정할 수 없습니다. 즉, 네임스페이스를 적용한 함수 또는 속성을 public, private, protected 또는 internal로 선언할 수 없습니다.
네임스페이스 참조
public, private, protected, internal 등의 액세스 제어 네임스페이스 중 하나로 선언된 메서드 또는 속성을 사용할 때 네임스페이스를 명시적으로 참조할 필요는 없습니다. 이러한 특수 네임스페이스에 대한 액세스는 컨텍스트에 의해 제어되기 때문입니다. 예를 들어 정의를 private 네임스페이스에 배치하면 자동으로 동일한 클래스 내의 코드에서 사용할 수 있게 됩니다. 그러나 사용자가 정의한 네임스페이스에는 이와 같은 컨텍스트 민감도가 없습니다. 사용자 정의 네임스페이스에 배치한 메서드 또는 속성을 사용하려면 네임스페이스를 참조해야 합니다.
use namespace 지시문을 사용하여 네임스페이스를 참조하거나, 이름 한정 기호(::)를 사용하여 네임스페이스로 이름을 정규화할 수 있습니다. use namespace 지시문을 사용하여 네임스페이스를 참조하면 네임스페이스가 "열려" 정규화되지 않은 모든 식별자에 해당 네임스페이스를 적용할 수 있습니다. 예를 들어 example1 네임스페이스를 정의한 경우 use namespace example1을 사용하여 해당 네임스페이스에 있는 이름에 액세스할 수 있습니다.
use namespace example1;
myFunction();
한 번에 둘 이상의 네임스페이스를 열 수 있습니다. use namespace를 사용하여 네임스페이스를 열면 네임스페이스가 열린 코드 블록 전체에서 열린 상태로 남아 있게 됩니다. 열린 네임스페이스를 명시적으로 닫을 수는 없습니다.
그러나 둘 이상의 네임스페이스가 열려 있으면 이름이 충돌할 가능성이 커집니다. 네임스페이스를 열지 않으려면 use namespace 지시문을 사용하는 대신 네임스페이스 및 이름 한정 기호로 메서드 또는 속성 이름을 정규화하면 됩니다. 예를 들어 다음 코드에서는 example1 네임스페이스를 사용하여 myFunction()이라는 이름을 정규화하는 방법을 보여 줍니다.
example1::myFunction();
네임스페이스 사용
ActionScript 3.0의 일부인 flash.utils.Proxy 클래스에서 이름 충돌을 방지하는 데 사용되는 네임스페이스에 대한 실제 예를 찾아볼 수 있습니다. ActionScript 2.0의 Object.__resolve 속성을 대체하는 Proxy 클래스를 사용하면 정의되지 않은 속성 또는 메서드에 대한 참조를 차단하여 오류가 발생하는 것을 막을 수 있습니다. 이름이 충돌하지 않도록 하려면 Proxy 클래스의 메서드를 모두 flash_proxy 네임스페이스에 배치합니다.
flash_proxy 네임스페이스가 사용되는 방법을 보다 잘 이해하려면 Proxy 클래스를 사용하는 방법을 알아야 합니다. Proxy 클래스의 기능은 이 클래스에서 상속된 클래스에서만 사용할 수 있습니다. 즉, 객체에 Proxy 클래스의 메서드를 사용하려면 객체의 클래스 정의에서 Proxy 클래스를 확장해야 합니다. 예를 들어 정의되지 않은 메서드 호출을 차단하려면 Proxy 클래스를 확장한 다음 Proxy 클래스의 callProperty() 메서드를 재정의합니다.
네임스페이스 구현 과정은 일반적으로 네임스페이스 정의, 적용 및 참조의 3단계로 구성된다는 것을 기억하고 있을 것입니다. 그러나 Proxy 클래스의 어떤 메서드도 명시적으로 호출되지 않기 때문에 flash_proxy 네임스페이스는 정의 및 적용되기는 하지만 참조되지는 않습니다. ActionScript 3.0이 flash_proxy 네임스페이스를 정의하고 이를 Proxy 클래스에 적용합니다. 사용자가 작성하는 코드에서는 Proxy 클래스를 확장하는 클래스에 flash_proxy 네임스페이스를 적용하기만 하면 됩니다.
다음과 유사한 방식으로 flash_proxy 네임스페이스가 flash.utils 패키지에 정의되어 있습니다.
package flash.utils
{
public namespace flash_proxy;
}
이 네임스페이스는 Proxy 클래스에서 발췌한 다음 예제에서 볼 수 있는 것과 같이 Proxy 클래스의 메서드에 적용됩니다.
public class Proxy
{
flash_proxy function callProperty(name:*, ... rest):*
flash_proxy function deleteProperty(name:*):Boolean
...
}
다음 코드에서 볼 수 있는 것과 같이 먼저 Proxy 클래스와 flash_proxy 네임스페이스를 모두 가져와야 합니다. 그런 다음 Proxy 클래스를 확장하도록 클래스를 선언해야 하며, 엄격 모드에서 컴파일하는 경우에는 dynamic 특성도 추가해야 합니다. callProperty() 메서드를 재정의하는 경우 flash_proxy 네임스페이스를 사용해야 합니다.
package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic class MyProxy extends Proxy
{
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
}
MyProxy 클래스의 인스턴스를 만들고 다음 예제에서 호출된 testing() 메서드처럼 정의되지 않은 메서드를 호출하는 경우, Proxy 객체에서 메서드 호출을 차단하고 재정의된 callProperty() 메서드 내의 명령문(이 경우 간단한 trace() 문)을 실행합니다.
var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing
flash_proxy 네임스페이스 내에 Proxy 클래스의 메서드를 배치하면 두 가지 장점이 있습니다. 첫 번째, 별도의 네임스페이스를 사용하면 Proxy 클래스를 확장하는 모든 클래스의 공용 인터페이스가 단순화됩니다. Proxy 클래스에서 재정의할 수 있는 메서드는 약 12개이며 모두 직접 호출되도록 설계되지 않았습니다. 공용 네임스페이스에 메서드를 모두 배치하면 혼동될 수 있습니다. 두 번째, Proxy의 하위 클래스에 Proxy 클래스의 메서드와 이름이 일치하는 인스턴스 메서드가 포함되어 있는 경우 flash_proxy 네임스페이스를 사용하면 이름 충돌이 방지됩니다. 예를 들어 사용자가 정의한 메서드 중 하나에 callProperty()라는 이름을 지정할 수 있습니다. 다음 코드에서는 사용자가 정의한 callProperty() 메서드가 다른 네임스페이스에 있으므로 오류가 발생하지 않습니다.
dynamic class MyProxy extends Proxy
{
public function callProperty() {}
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
네임스페이스는 public, private, internal 및 protected와 같은 네 가지 액세스 제어 지정자로는 불가능한 방식으로 메서드 또는 속성에 대한 액세스를 제공하려는 경우에도 유용합니다. 예를 들어 몇 가지 유틸리티 메서드가 여러 패키지에 분산되어 있는 경우가 있을 수 있습니다. 이러한 메서드를 모든 패키지에서 사용할 수 있도록 하되 공용으로 지정하지 않으려고 합니다. 이렇게 하려면 네임스페이스를 만들어 사용자 고유의 특수 액세스 제어 지정자로 사용하면 됩니다.
다음 예제에서는 사용자 정의 네임스페이스를 사용하여 다른 패키지에 있는 두 개의 함수를 그룹화합니다. 동일한 네임스페이스로 함수를 그룹화하면 클래스 또는 패키지에서 use namespace 문을 한 번만 사용하여 두 함수를 참조하도록 할 수 있습니다.
이 예제에서는 네 개의 파일을 사용하여 이러한 기법을 설명합니다. 네 개의 파일 모두 클래스 경로에 있어야 합니다. 첫 번째 파일인 myInternal.as는 myInternal 네임스페이스를 정의하는 데 사용됩니다. 파일이 example 패키지에 있으므로 해당 파일을 example 폴더에 배치해야 합니다. 네임스페이스가 public으로 표시되어 있으므로 다른 패키지로 가져올 수 있습니다.
// myInternal.as in folder example
package example
{
public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples";
}
두 번째와 세 번째 파일인 Utility.as 및 Helper.as에서는 다른 패키지에서도 사용할 수 있어야 하는 메서드가 포함된 클래스를 정의합니다. Utility 클래스가 example.alpha 패키지에 있으므로 example 폴더의 하위 폴더인 alpha 폴더에 파일을 배치해야 합니다. Helper 클래스가 example.beta 패키지에 있으므로 example 폴더의 하위 폴더인 beta 폴더에 파일을 배치해야 합니다. 이러한 example.alpha 및 example.beta 패키지를 사용하려면 네임스페이스를 가져와야 합니다.
// Utility.as in the example/alpha folder
package example.alpha
{
import example.myInternal;
public class Utility
{
private static var _taskCounter:int = 0;
public static function someTask()
{
_taskCounter++;
}
myInternal static function get taskCounter():int
{
return _taskCounter;
}
}
}
// Helper.as in the example/beta folder
package example.beta
{
import example.myInternal;
public class Helper
{
private static var _timeStamp:Date;
public static function someTask()
{
_timeStamp = new Date();
}
myInternal static function get lastCalled():Date
{
return _timeStamp;
}
}
}
네 번째 파일인 NamespaceUseCase.as에는 기본 응용 프로그램 클래스가 정의되어 있으며 example 폴더와 상위 폴더가 같은 폴더에 있어야 합니다. Flash Professional에서 이 클래스는 FLA의 문서 클래스로 사용됩니다. NamespaceUseCase 클래스는 myInternal 네임스페이스를 가져와서 이를 사용하여 다른 패키지에 있는 두 개의 정적 메서드를 호출하기도 합니다. 예제에서는 코드를 단순화하기 위해서만 정적 메서드를 사용합니다. 정적 메서드와 인스턴스 메서드를 모두 myInternal 네임스페이스에 배치할 수 있습니다.
// NamespaceUseCase.as
package
{
import flash.display.MovieClip;
import example.myInternal; // import namespace
import example.alpha.Utility;// import Utility class
import example.beta.Helper;// import Helper class
public class NamespaceUseCase extends MovieClip
{
public function NamespaceUseCase()
{
use namespace myInternal;
Utility.someTask();
Utility.someTask();
trace(Utility.taskCounter); // 2
Helper.someTask();
trace(Helper.lastCalled); // [time someTask() was last called]
}
}
}