[JavaScript] 클래스 정의 API ㅡ 2/3

총 5개의 클래스가 존재하는데 먼저 가장 간단한 Coordinate 클래스를 정의하면 다음과 같습니다.

var Coordinate = Class({
    name: "Coordinate",
    construct: function(x, y) {
        this._x = x;
        this._y = y;
    },
    methods: {
        getX: function() {
            return this._x;
        },
        getY: function() {
            return this._y;
        },
        toString: function() {
            return "(" + this._x + ", " + this._y + ")";
        }
    }
});

앞서 언급했듯이 자바스크립트에서 클래스의 정의는 개발자 스스로에 대한 약속이 필요하다고 하였습니다. 그 약속에 해당하는 부분이 바로 4,5번 코드에 있는 _x, _y 변수입니다. 변수명 앞에 밑줄(_)을 하였음으로 해서 이 변수는 private 변수라는 약속을 정한 것입니다. 개발자 스스로의 약속이므로 이 약속을 깼다고 하여도 자바스크립트는 어떤한 오류를 제공하지 않습니다. 물론 이러한 약속에 대해서 경고를 제공하도록 할 수 있으나 그렇게 되면 클래스 정의 API가 더욱 복잡해지게 될 것입니다. 그리고 7번의 methods 객체에 필요한 매서드를 추가하였습니다.

이제 다음은 추상 클래스인 Shape 클래스에 대한 코드입니다.

var aShape = Class({
    name: "aShape",
    methods: { 
        draw: function() { throw "abstract method"; }
    }
});

코드를 살펴보면, 4번에 draw라는 추상 매서드를 제공하였습니다. draw 매서드 역시 추상 매서드다라는 약속이지 자바스크립트 언어 차원에서 추상 매서드로 강제하지 않습니다. 대신 이 매서드를 호출하게 되면 예외를 발생하도록 하였습니다.

다음으로 위의 추상클래스인 Shape를 구현하는 Rectangle와 Circle 클래스에 대한 코드를 살펴보겠습니다.

var Rectangle = Class({
    name: "Rectangle",
    construct: function(w, h) {
        this._width = w;
        this._height = h;
    },
    methods: {  
        draw: function() { 
            alert("draw Rectangle");
        },
        getWidth: function() {
            return this._width;
        },  
        getHeight: function() {
            return this._height;
        }
    },
    requires: [aShape]
});

var Circle = Class({
    name: "Circle",
    construct: function(x, y, r) {
        this._x = x;
        this._y = y;
        this._r = r;
    },
    methods: {
        draw: function() {
            alert("draw Circle");
        },
        getCenter: function() {
            return new Coordinate(this._x, this._y);
        },
        getRadius: function() {
            return this._r;
        }
    },
    requires: [aShape] 
});

동시에 Rectangle와 Circle 클래스에 대한 코드를 보이는 이유는 이 두개가 서로 동일한 구조를 갖고 있음을 강조하기 위함입니다. 이 두 클래스는 Shape의 추상 매서드인 draw를 분명히 구현하고 있으며 각기 자신에게 맞는 매서드를 추가적으로 정의하고 있습니다. 여기서 추상매서드를 구현하고 있는지에 대한 검사는 18번과 39번의 코드에서처럼 requires 속성을 통해 검사를 해주게 됩니다. 만약 이 requires 속성을 통해 추상 매서드를 구현하지 않았을 경우 예외를 친절하게 예외를 발생해 주도록 클래스 정의 API를 구현하였습니다.

[JavaScript] 클래스 정의 API ㅡ 1/3

자바스크립트는 C++이나 C#/Java 등에서와 같이 클래스(Class)를 직접적으로 정의할 수 있는 API를 제공해 주지 않습니다. 그러나 자바스크립트에서는 프로토타입(Prototype)을 이용하여 클래스의 특성을 제공할 수 있습니다. 그러나 이러한 프로토타입 기반의 클래스 정의에 대한 API는 개발자가 직접 만들어 사용해야 합니다. 게다가 비록 프로토타입을 이용해 클래스 개념을 자바스크립에서 사용할 수 있다고는 하여도 C++이나 C#/Java와 같은 완전한 클래스를 정의하지는 못합니다. 대신 개발자는 스스로 엄격한 약속을 통해 이러한 부족함으로 매꿔야만 합니다.
아래의 코드는 자바스크립트에서 클래스를 정의하기 위한 API의 한가지 예입니다. 자바스크립트를 이용해 클래스를 정의하는 API는 매우 다양하고 많습니다. 그중 제가 필요에 의해 아래의 제시한 클래스 정의 API는 데이비드 플래너건의 자바스크립트 완벽가이드라는 책을 많은 부분 참고했으며 불필요한 부분을 제거한 예입니다.

function Class(x) {
    var classname = x.name;
    var superclass = x.extend || Object;
    var constructor = x.construct || function() {};
    var methods = x.methods || {};
    var statics = x.statics || {};
    var requires = x.requires || [];
    var proto = new superclass();

    for(var p in proto) if(proto.hasOwnProperty(p)) delete proto[p];
 
    proto.constructor = constructor;
    proto.superclass = superclass;
    proto.classname = classname; 
    constructor.prototype = proto;
 
    for(var p in methods) proto[p] = methods[p];
    for(var p in statics) constructor[p] = statics[p];

    for(var i=0; i        var c = requires[i];
        for(var p in c.prototype) {
            if(typeof c.prototype[p] != "function" || 
                p == "constructor" || p == "superclass") continue;
   
            if(p in proto && typeof proto[p] == "function" && 
                proto[p].length == c.prototype[p].length) continue;
    
            throw new Error(classname + " class requires " + p + " method.");
        }
    } 

    return constructor;
}

위의 클래스 정의 API는 다음과 같이 클래스의 4가지 본연의 기능에 충실할 것을 전제로 하였습니다.

  • 클래스를 정의하는 방법 제공할 것
  • 클래스 상속을 지원할 것
  • 추상 클래스을 구현할때 해당 추상 클래스의 모든 매서드를 구현하고 있는지 검사할 것
  • 객체가 어떤 클래스의 타입인지 검사할 수 있도록 할 것

위의 전제 조건들에 대해서 실제 위의 클래스 정의 API를 대한 사용예를 통해 살펴보겠습니다. 위의 클래스 정의 API를 통해 다음과 같은 클래스 계층을 구성하고자 합니다.


사용자 삽입 이미지Shape는 draw라는 매서드를 갖는 추상 클래스입니다. 그리고 이 Shape를 구현하는 클래스로 Rectangle과 Circle 클래스가 있습니다. 여기에 PositionedRectangle라는 클래스는 Rectangle를 상속받습니다. 또한 Coordinate라는 클래스가 존재하며 이 클래스는 PositionedRectangle와 Circle 클래스 사용합니다.

[G1X] 손 길..


사무실이 강변역 바로 옆이다. 그리고 집은 강변역에서 버스를 타고 간다. 늦은 시간까지 외부에서 다른 일을 보다 집에 갈때 버스를 타기 위해 강변역을 들려야 한다.. 하지만 지금처럼 다소 늦은 시간이면 집 대신 사무실로 발길을 돌린다..

저작권 침해에 따른 형사처벌 증가

한미 FTA 협정에 관련하여 오픈소스에 대한 라이선스 소송에 대한 글입니다.

전체 기사 내용은 http://www.oss.kr/82739 를 참고하시고, 기사의 내용의 앞 부분에 대한 내용은 다음과 같습니다.

한-미 FTA 협정 이행에 따른 저작권법 개정에 따르면, 저작권자가 저작권 이슈를 문제 삼지 않더라도(고소하지 않더라도), 그 침해가 영리를 목적으로 하거나 상습적이기만 하면, 형사처벌이 가능하게 되었다. 따라서 공개 SW를 도입하여 영리 또는 상습적으로 사용하는 기업 또는 개인 개발자들이 해당 라이선스 준수 의무를 지키지 아니하면, 공개 소프트웨어 커뮤니티에서 문제 삼고 있지 아니하더라도, 검찰 직권 또는 제3자 고발에 의하여 공소를 제기당할 수 있는 것이다. (이하 생략 …)

이 기사는 자작권 침해에 대한 고발이 비친고죄의 형태로 변경됨으로써 우려와 기대를 동시에 다룬내용입니다. 소스가 오픈되었다고 하여 라이선스의 본래 의미와 상관없이 마음대로 사용할 수 있다는 논리가 얼마나 잘못되었고 위험한지를 깨달았으면 좋겠습니다. 세계적으로.. 그리고 국내에서만 해도 무형의 가치를 생산해 내는 소프트웨어 개발자들의 수는 이미 유형의 산출물을 생산해 내는 생산자 수만큼이나 많습니다. 유형의 자산에 대해서는 그 가치를 인정하면서 무형의 가치에 대해서는 아직까지도 인정하지 못하는 몰지각함에 대한 자각이 있었으면 합니다.

말라 죽어버린 잎을 모두 잘라내다..

작년말.. 그러니까 12월에 회사를 옮길때.. 한겨울 너무 추운 날이라 그랬는지 행운목의 잎이 동상을 입어 말라 죽어갔습니다..


다행히 모든 잎이 말라 죽지 않고 몇개가 말랐고.. 마른 잎이 자연스럽게 떨어 지기를 기다릴 요량으로 건들지 않고 가만히 기다렸습니다.. 그러다가 오늘 말라 죽어가는 잎만을 골라 모두 다 잘라내었습니다..

죽은 잎을 잘라내고 행운목을 다시 보니.. 마치.. 머리를 덮수룩하게 기르다가 이제 방금 이발을 한 것처럼 말끔하고 더욱 생기있어 보입니다.. 진작에 잘라내 버릴 것을 그랬습니다… 올해에 들어 가장 잘한 일 같다는 생각마저 듭니다..

문득 지금까지 살아오며 내 생각들 중에.. 행운목의 말라 죽어버린.. 거추장스러운 잎처럼 나를 복잡하게 만드는 것은 무엇일까 하는 생각이 듭니다…. 말라 죽어버린 잎처럼 잘못된 생각들.. 또 내게는 맞지 않는 생각들이 있다면 과감히 잘라내야겠습니다..