CODEONWORT

액션스크립트 문법에 1순위로 추가해야 하는 것: 변경 불가능한 참조 본문

Season 1/플래시

액션스크립트 문법에 1순위로 추가해야 하는 것: 변경 불가능한 참조

codeonwort 2012. 3. 6. 01:06
Stage3D도 나온 마당에 CPU에서 수행 능력을 최대한 뽑아내야 하는데 액션스크립트 3.0에는 치명적인 문법이 하나 없다. 바로 변경 불가능한 참조(immutable reference)인데 특정 경로를 통해 참조한 객체의 내부 상태를 수정하지 못하도록 하는 문법이다.

예를 들어 flash.geom.Vector3D 클래스에는 X_AXIS라는 Vector3D형 static 상수가 있는데 이걸 접근할 때마다 새로운 객체를 반환하기 때문에 반복문 안에서 쓰면 수행 능력이 극악으로 떨어진다. 액션스크립트로 써보면 대충 이런 식이다.

// Vector3D 클래스에서
public static function get X_AXIS():Vector3D { return new Vector3D(1, 0, 0) }

직접 확인해보자면 trace(Vector3D.X_AXIS == Vector3D.X_AXIS) 를 실행하면 false를 출력한다. 이것은 만약 코드 어딘가에서 Vector3D.X_AXIS.x = 0 을 실행하면 그 프로그램 전체가 박살이 나기 때문에 타당한 구현이다. Matrix3D#rawData나 DisplayObject#transform등 여러 getter 메서드가 같은 이유로 호출될 때마다 새 객체를 반환한다. (레퍼런스를 보면 이런 클래스들에는 모두 clone() 메서드가 있다)

다음 문법만 추가되면 위와 같은 수행능력 낭비는 모두 사라진다.
private static const xAxis:Vector3D = new Vector3D(1, 0, 0)
immutable public static function get X_AXIS():Vector3D {
  return xAxis
}

immutable의 뜻은 이 메서드가 반환하는 객체의 멤버 변수의 값을 바꾸려는 모든 시도를 컴파일 오류로 처리하겠다는 것이다. Vector3D.X_AXIS.x = 0 은 x 좌표를 저장하는 멤버 변수의 값을 바꾸려는 시도이기 때문에 컴파일 오류로 처리된다. 따라서 멤버 변수의 값에 접근하는 것만 가능하게 되어 안전하고 수행 능력도 좋은 프로그램을 작성할 수 있다.

여기서 헷갈릴 수 있는 점이 하나 있는데 만약 immutable이 붙은 함수와 붙지 않은 함수가 동일한 객체를 반환한다면

var vec:Vector3D = new Vector3D
immutable function a():Vector3D {
   return vec
}
function b():Vector3D {
   return vec
}

a().x = 1 // 이것은 불가능하지만
b().x = 1 // 이것은 가능하다

immutable은 컴파일 때 코드를 살펴봐서 오류를 내는 것이고 런타임에는 아무 작용도 하지 않는다. 컴파일 시간에 코드를 분석할 때 immutable이 붙은 함수를 추적해서 이 함수가 반환한 객체를 이용하는 모든 구문을 검사해서 규칙을 위반하면 컴파일 오류를 내는 것이다. 이렇게 하지 않으면 런타임에 보안 샌드박스 검사하는 것 마냥 실시간으로 감시해야 하는데 수행 능력도 떨어지고 위의 상황처럼 경우에 따라 객체를 변경 불가능이나 가능한 상태로 반환하는 유연함이 필요하다고 본다.
3 Comments
댓글쓰기 폼