2007년 11월 25일 일요일

프랑크푸르트 콘티넨탈 호텔(싱글 룸)

스페인 여행 갔을 때 묶었던 프랑크푸르트의 콘티넨탈 호텔 사진입니다.
  • 싱글룸이였구요.
  • 비용은 정확히 기억이 나지 않는데 매우 저렴하였습니다. (다른 호텔에 비해서)
  • 프랑크푸르트 역 부근에 있어서 찾아가기 매우 쉽습니다.
  • 시설 수준은 보통이구요.
  • 갔을 때(9/27/2007)는 외부 공사중이여서 전망은 별로 였습니다.
  • TV는 있으나 시청 시 요금이 부과됩니다.
  • 조식 제공이었는데 새벽에 도착해서 먹어보지는 못했습니다.(식사류 평가는 높더군요)
사용자 삽입 이미지

보이기에는 허접이라도 나름 푹신한 침대입니다.


바깥 외벽 공사하느라 비계 등이 설치되어 있어서 많이 어둡더군요.
사용자 삽입 이미지

왼쪽 편 사진의 오른쪽 벽에 걸려 있는 청소기처럼 생긴게 헤어 드라이기더군요.
사용자 삽입 이미지사용자 삽입 이미지

샤워시설과 화장실은 깔끔히 잘 갖추어져 있습니다. 욕조가 없는게 매우 아쉬웠지만요.
가격대 성능비를 생각하시면 추천할만합니다. (프랑크푸르트 역주위만 보고 다른 곳으로의 이동을 생각하신다면 또 추천 ^^)
사용자 삽입 이미지

구글에서 검색한 화면입니다.

관련 링크:

2007년 11월 21일 수요일

포탈지향적 사고방식?

포탈지향적인 사고방식이 어떤게 있을까요?
  • 남들이 하는 (잘될 것 같은) 서비스는 우리도 제공해야한다. (이미 늦었다.)
  • 그 서비스는 우리가 개발해야한다. (인력 비용은?)
  • 문제는 기술력으로 극복해야한다. (뭐.. 기술력으로 극복해야할 수도 있다. 그러나, 기획 또는 디자인에서 반대로 생각하면 쉽게갈 수 있는 문제라고 생각할수도 있지 않을까?)
  • 이 사이트에서만 되는 기능 저 사이트에서만 되는 기능을 가져다가 우리는 다 구현해야한다고 주장한다. (저기요... 균형이란게 있지 않을까요?)
이런 걸 반대하는 개발자는 잘못된 것일까?

작은조직, 가벼우면서도 빠른 개발, 성과를 내는 조직.... 쉽지 않은 것 같다. 집중이라는 의미는 공부뿐만 아니라 서비스에도 마찬가지인것 같다.

투덜투덜투덜....

JavaScript의 파라미터를 어떻게 처리할 것인가?

Wait till I come!Sending Objects as parameters - good or bad?라는 글에서 JavaScript의 파라미터들을 어떻게 처리할 것인가에 대해서 다루었는데요.

JavaScript의 코드들을 살펴보면 파라미터가 여럿 사용된 코드들을 쉽게 찾아볼 수 있습니다.
function doLayerFloat(id, start, end, direction, speed, fade, whatelse, Iforgot) {
}
이러한 코드의 가장 큰 문제점은 이 함수를 호출할 때 파라미터의 개수와 순서를 항상 기억해야하는 문제점을 지니고 있습니다. 게다가 첫 파라미터를 제외와 마지막 파라미터만 값을 넘겨야 하는 경우 null 또는 ''의 값을 넘겨야 하는 문제점도 있죠.
doLayerFloat('myDIV', null, null, null, null, null, null, 'default') {
}
이러한 복잡함은 인자를 항상 받아야할 파라미터를 제외하고 나머지를 배열로 받음으로써 쉽게 해결할 수 있습니다. (배열을 사용하는 비용은 들겠지만요.)
function doLayerFloat(id, props) {
   var elm = typeof id !== 'string'? id: document.getElementById(id);
   for (var i in props) {
   }
   // 또는 || 연산을 사용하여 디폴트 값을 채워줄 수도 있구요.
   props = props || {};
   props.start = props.start || 100;
   ....
}
※ prototype.js를 사용하신다면 다음과 같은 방법도 사용할 수 있습니다.
function doLayerFloat(id, props) {
   var elm = $(id);
   props = Object.extend({
      start: 100,
      ...
   }, props || {});
}
※※ 파라미터가 함께 여러곳에 쓰인다면 Hash가 아닌 의미있는 클래스로 만들어버리는게 바꿔주는게 가장 적당하겠네요. -_-a

출처: Wait till I come!Sending Objects as parameters - good or bad?

2007년 11월 19일 월요일

Prototype 1.6.0의 addMethods()에대한 고찰

요즘에 회사에서 JavaScript OOP 주제로 스터디를 하고 있는데요. 최근에 정식버전이 나온 prototype 1.6.0의 상속기능에 대한 주제로 K과장님(실명을 밝혀도 되려나? ^^;;;)께서 발표를 하셨는데 그 때 잘이해가 안되던 Class.addMethods()에 대해서 다시 정리해보게 되었습니다.
사용자 삽입 이미지

※ 본 포스트에 사용된 Animal클래스는 http://prototypejs.org/api/class/addMethods에 나와있는 클래스입니다.

1. firebug를 실행시켜보면 addMethods의 파라미터(source)는 클래스가 넘어오고 properties는 클래스가 가지고 있는 프로퍼티인 클래스 메소드, Function의 메소드와 prototype 등의 배열이 됩니다.

Object.keys(Animal) 을 출력했을 때 다음의 결과를 얻었습니다.

addMethods, superclass, subclasses, prototype, argumentNames, bind,
 bindAsEventListener, curry, delay, wrap, methodize, defer

2.
ancestor: ancestor는 this.superclass && this.superclass.prototype이 되게 됩니다. 이 때 && 연산의 결과를 알아보기 위해서 http://prototypejs.org/api/class/addMethods의 Animal 클래스로 테스트를 해봤습니다.

Animal을 출력했을 때는

function klass() {this.initialize.apply(this, arguments);}

Animal.prototype을 출력했을 때는
({initialize:(function (name, sound) {this.name = name;this.sound = sound;}),
 speak:(function () {alert(this.name + " says: " + this.sound + "!");})})

의 값을 얻었습니다.

그리고, Animal && Animal.prototype의 결과로는 Animal.prototype의 결과 값을 얻었습니다.

({initialize:(function (name, sound) {this.name = name;this.sound = sound;}),
 speak:(function () {alert(this.name + " says: " + this.sound + "!");})})


(궁금증, 개인적으로는 연산 결과로 logical 연산 값인 true나 false가 나올 줄 알았습니다. 왜그런지 아시는 분 있으신가요?)


3. for문과 if문의 부분은 $super가 첫 번째 argument로 정의되어 있는 Function을 찾는 경우를 의미합니다. (부모 클래스로부터 자식이 function을 상속받아서 $super로 부모의 메소드를 호출할 수 있는 경우가 되겠죠)

4. 이제 가장 궁금했던 value 부분을 살펴볼 것인데요. 가장 바깥의 Object.extend를 호출하는 부분은 value에 toString과 valueOf 메소드를 추가해주는 코드입니다. Object.extend의 첫 번째 파라미터로 넘겨지는 부분만 따로 때어내면 다음과 같습니다.
            (
                function(m) {
                      return function() {
                          return ancestor[m].apply(this, arguments)
                      };
                }
            )(property).wrap(method),

(이 코드가 어떻게 호출되면 과연 부모의 코드를 호출하게 되는 것일까 많은 고민을 했었습니다. -_-;;)

5. 먼저, 가장 처음 실행되는 부분만 따로 때서 생각해보면 (function(m){...})(property) 부분은 인터프리터에서 코드가 읽히면서 실행이 되게 되는데요. 인자로 받은 property의 값은 function(m)의 파라미터인 m으로 넘어가게 됩니다.
Animal.prototype.speak = function () { alert(this.name + " says: " + this.sound + "!"); }
이 코드가 for 루프로 들어가게 되면 m의 값이 'speak'로 넘어오게 되고 ancestor[m]은 function () { alert(this.name + " says: " + this.sound + "!"); }이 되게 됩니다. 즉, 실행된 코드는 실행시점에서 받은 파라미터를 넘겨서 Animal의  speak를 호출하게됩니다. (이 값이 나중에 Animal을 상속받는 자식의 메소드로 저장됩니다.)

            (
               function(m) {
                     return function() {
                         return ancestor[m].apply(this, arguments)
                     };
               }
           )(property)

여기까지 실행된 값은
function () { return ancestor[m].apply(this, arguments); } 됩니다.

6. 이제 마지막으로 wrap메소드를 살펴보면 다음과 같은 메소드로 구성됩니다. 위의 코드의 wrap()이 호출될 때 인자로 넘겨지는 wrapper는 Animal 클래스의 speak 메소드(function () { alert(this.name + " says: " + this.sound + "!"); })가 됩니다.

    wrap: function(wrapper) {
        // 그리고, __method는 5에서 넘겨지는
        // function() {return ancestor[m].apply(this, arguments);}
        // 가 되게 됩니다.
        var __method = this;
        return function() {
            // 그리고, 이 부모의 메소드가 첫 번째 인자로 넘어가게 됩니다. $super의 파라미터 위치에
            // 부모 메소드가 넘겨지게 됩니다.
            return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
        }
    },

7. 그리고, 이 결과 값이 자식의 prototype[property]로 추가되게 됩니다.


P.S. 좀 정신사납게 적은 글입니다만, 참고용으로만 봐주세요. 전체 코드를 다 본게 아니라서.. 쿨헉~
(''  ;;; 언제 다 본 적 있냐고 물으시면 난감합니다.~~)

테스트 출력에 사용한 샘플 파일입니다. (허접이긴 하지만 참고용으로 올립니다. )

※  3에서 던진 질문의 답을 알아냈습니다. JavaScript에서는 Short-Circuit Evalation 연산을 사용하게 되는데요. (expression1) && (expression2)의 연산에서 앞의 expression1이 false면 뒤의 expression2의 연산을 실행하지 않는 것을 Short-Circuit Evaluation이라 합니다. (시험에도 나왔었던 기억이.. -_-;;;)

Animal && Animal.prototype의 경우에는 Animal이 reference 값이 있으므로 true의 값이 떨어지게 되는데요. 이 때 연산의 결과는 expression1의 값과 상관없이 expression2의 연산의 결과에만 의존하게 되므로 expression2의 연산을 boolean으로 값으로 evaluation하지 않습니다.
사용자 삽입 이미지
※ Wikipedia의 내용을 더 살펴보니 Short-Circuit Evaluation을 실행하는 경우 앞의 expression1이 true인 경우 뒤의 연산을 하지 않는, 즉 마지막 값을 그대로 넘겨주는 언어가 여럿 있군요 ^^

2007년 11월 16일 금요일

MoniWiki를 사용하다보니...

입력 창 우측 사이드바에 다음의 문구가 눈에 팍~ 뛰었다.
사용자 삽입 이미지

이런 의민가?
 오우~ 댁같이 MoniWiki 쓰는 사람은 일년이내에 장가갈거야~
--;;;; 과연?????? 아직도.. ㅅㄹ구나.. ㅠㅠ

2007년 11월 14일 수요일

Apache의 Default Host

403 Forbidden You don't have permission to access
Apache 설치 후 http.conf 파일에 VirtualHost를 설정하여서 사용하고 있었는데 *.domain.com 주소가 동작을 하지 않더군요. 이것저것 다 설정해보고 동료 분의 http.conf와 비교도 해봤는데 원인을 찾지 못했었는데 방금 '올빼미'님의 도움으로 해결했습니다. 해결방법은...(Virtual Host에서 주소를 찾지 못할 때도 403이 발생하더군요)

'http.conf의 VirtualHost들이 정의되어 있는 리스트에서 디폴트 동작을하는 VirtualHost 정의는 맨 처음에 위치해야 한다'입니다. (As a consequence, the first listed virtual host is the default virtual host.)

   NameVirtualHost *

<VirtualHost *>
ServerName *.domain.tld
DocumentRoot /www/domain
</VirtualHost>

<VirtualHost *>
ServerName www.otherdomain.tld
DocumentRoot /www/otherdomain
</VirtualHost>
관련 링크 : Named-based Virtual Host Support

2007년 11월 5일 월요일

Apache/PHP 재설치할 때 발생한 문제들

여러가지 이유로 인하여 Apache와 PHP를 재설치하게 되었습니다. 이 과정에서 몇 가지 문제가 발생하였는데요.

1. Apache를 설치했을 때 이전과 달리 서비스에 등록이 되지 않더군요. '올빼미'님의 도움으로 확인해보니 서비스가 설치되지 않아서 발생한 문제라고 하더군요. 서비스 설치는 다음의 -k install을 사용하여 command 상에서 설치가 가능합니다.
Apache.exe -k install
2. 우여곡절 끝에 설치한 Apache에 PHP를 설치하다가 삽질을 또 하였습니다. php.net에서 Windows 버전의 인스톨러를 받아서 설치하는 경우 extension 설치 메시지가 나오는데요. 메시지에서 설치할 목록을 선택한 후 설치를 하였슴에도 불구하고 설치가 되지 않더군요. 그래서 5.0 버전대의 ext 버전을 사용했는데 버전이 달라서 에러가 나더군요.
사용자 삽입 이미지

버전 확인은 dll파일을 선택한 후 마우스 오른쪽 버튼을 눌러서 버전을 확인 할 수 있습니다.

3. 그리고, dll을 로딩하지 못한다는 메시지가 나온다면 php.ini의 include_path와 extension의 이름도 확인하는 것도 좋은 방법일 것 같습니다. (2에서 안되길래 모두 삭제한 후 5.0대 버전을 설치하였는데 php.ini를 5.2.4를 사용하니까 에러가 발생하더군요. 5.2.4에서는 php_http.dll이 php_http_5_2_3.dll로 이름이 바뀌어서 발생한 문제였습니다. -_-)

P.S. 정보공유 차원에서 올렸습니다. ^^;;;