The Execution Context : 실행문맥 제대로 이해하기

원문 출처 : http://www.jibbering.com/faq/faq_notes/closures.html

평소에 일반적인 C,C++,Java,C# 이딴 언어를 주로 사용하다 자바스크립트와 같은 스크립트 언어를 조금만 하다보면, 금방 궁금증이 늘어난다.

과연.. 요놈들은 왜? 이렇게 작동하는걸까? 라는 좀 원초적인 질문이다.

어제 오늘 클로저라는 놈을 제대로 이해하기위해, 각종 아티클들을 찾아보다가..
괜찮은 아티클을 발견하고, 지금 번역은 아니고.. 그냥 해석해서 이해하는 중이다.
사실 클로저라는 놈을 이해하기위해선, 자바스크립트 내부적으로 작동하는 매커니즘을 이해할 필요가 있다..

이름하야, Indentifier Resolution, Execution Contexts, Scope Chains, Property Chain 같은 용어와 내부 매커니즘을 이해해야 한다는 얘기다.

오늘은 그중에서 실행문맥(Execution Contexts)에 대해서 정리해보자.

위에 원문을 A4로 출력하면, 대략 4페이지에 나오는 내용이다.

실행문맥은 ECMAScript 스펙에서 정의 된대로 추상적인 개념이고, 요 스팩을 구현하기 위해서 요구되는 지침정도라고 생각해보면 되겠다. 하지만 스펙에는 어떻게 구현하라는 이야기는 없으므로, 대충 개념만이라도 이해하자.

모든 자바스크립트 코드의 실행은 실행문맥안에서 이루어 진다. 전역 코드가 실행될때는 전역실행문맥이라고 불리는 곳에서 실행된다. 그리고 그 전역실행 문맥 안에 존재하는 각각의 function 들은 그 펑션마다 고유의 실행 문맥이 만들어지고 그 안에서 실행이 된다. eval 펑션은 예외다.

자바스크립트 펑션이 호출되면, 실행문맥안으로 들어가고 그안에서 새로운 펑션이 호출되면, 새로운 실행문맥을 만들고, 그 실행문맥 안으로 들어간다. 그리고 값이 리턴되면, 본래 호출되었던 펑션으로 복귀를 하게 되고, 이값도 리턴이 되면, 실행문맥은 사라진다.
결국 실행문맥이라는 것은 우리가 흔히 메모리 구조를 그릴때 그리는 스택구조와 비슷하다고 보면 되겠다.

일반 실행 문맥
실행문맥이 생성될때, 많은 일들이 순차적으로 일어난다.

1. Activation 객체 생성
먼저, 펑션의 실행문맥안에서 특별한 매커니즘을 갖는 Activation  이라는 객체를 만든다. 이 Activation 객체는 결과적으로 이름이 있는 프로퍼티에 접근할수 있으므로, 일반적인 객체라고 봐도 무방하다. 하지만, 일반 객체들이 모두 가지고 있는 프로토타입(prototype)을 가지고 있지 않고, 자바스크립트 코드에 의해서 직접적으로 참조되지 않는다.

2. arguments 객체 생성
다음으로 배열과 비슷하게 index를 가지는 Arguments 객체를 생성한다. 이 객체는 length(호출자가 넘겨주는 인자의 갯수)와 callee(실행중인 함수 객체-재귀를 위해 필요하다) 프로퍼티도 갖는다.
그리고 앞서 만든 Activation 객체에 “arguments”라는 이름의 프로퍼티가 만들어지고, 이 arguments객체를 참조할수 있도록 할당(assign)된다.

3. scope 할당
다음으로, 실행문맥은 Scope를 할당(assign)한다. 스코프는 객체들의 리스트로 구성된다. 흔히들 스코프 체인이라고 이야기한다. 한편 각 펑션 객체는 내부적인 [[scope]] 프로퍼티를 갖고 있는데, 그 [[scope]] 프로퍼티 역시 객체들의 리스트로 구성된다.
실행문맥에 할당된 스코프는 맨 앞에 Actiovation객체를 넣고, 호출된 본 함수 객체의  [[scope]] 프로퍼티가 참조하는 리스트들을 함께 구성한다.

4. 변수 인스턴스화 과정수행
다음으로, ECMA 262에서 “Variable” 객체로 언급한  객체들을 사용해서 변수의 인스턴스화(“variable instantiation”) 과정이 일어난다. Activation 객체 또한  Variable 객체로써 사용된다. (결국 Activation 객체와 Variable 객체는 사실상 같은 객체다. 아주 중요하니 체크하기 바람!!)

함수 표현식에서 선언된 공식적인 파라메타들을 식별자로 Activation 객체의 프로퍼티로 생성하고, 호출자로 부터 넘어온 인자값은 그 프로퍼티들의 값으로 한다. 인자가 넘어오지 않은 프로퍼티는 그 값으로는 undefined 할당이 된다.

함수 선언에서 사용된 함수 이름은 그 이름으로 함수 객체를 만들고 Variable 객체(이름은 다르게 표현하지만 결국 Activation 객체를 말한다)의 프로퍼티로 생성한다.변수 인스턴스화의 마지막 과정은 함수 안에서 지역변수로 선언된 모든 변수들을 Variable 객체의 프로퍼티로 생성하면서 마무리 짓는다.

변수 인스턴스화 과정에서 지역 변수로 생성된 프로퍼티들은 모두 undefined 값으로 초기화된다. 실질적인 값 초기화 과정은 함수 내부 코드가 실행될때 비로서 값이 정해진다는것을 잊지말자!

 arguments 프로퍼티를 가지는 Activation 객체와 지역 변수로 쓰이는 정해진 이름의 프로퍼티들을 가지는 Valiable 객체는 결국 서로 같은 객체다. 그리고 식별자 arguments 가 마치 지역변수로써 쓰일수 있도록 허가되어진다.

5. this 키워드 값 할당
마지막으로 this 키워드 값이 할당된다. 만일 this가 어떤 객체를 참조하도록 할당이 되면, 프로퍼티 접근 연산자를 통해서 그 this 키워드가 가르키는 객체의 프로퍼티들을 참조 한다.
즉, this.(프로퍼티 이름) 이딴 식으로 참조할수 있게 되고, this 에 null 값이 할당되면, 이 this 키워드는 전역 객체(window)를 참조하게 될것이다.

전역 실행 문맥

전역 실행 문맥은 arguments 가 없기 때문에 정의된 Activation 객체를 가질필요가 없다는 것이 약간 다르다. 하지만 스코프는 필요로 한다. 전역 실행 문맥의 스코프 체인은 오직 전역 객체 하나만을 가르킨다.

역주) 코드에서 선언된 전역변수는 모두 이 전역객체의 프로퍼티로 들어가기 때문에 사실상 전역객체 하나만 가지고 있는 꼴이 된다.

일반적인 최상위 레벨의 함수 선언들은 전역 실행 문맥의 내부 함수 들로써, 변수 인스턴화 과정을 거친다. 즉, 이 변수 인스턴화 과정을 거치게 되므로, 결론적으로 이 함수들은 전역 객체의 프로퍼티로써 존재하게 된다.  그리고 마지막으로 전역객체는 this 객체를 통해서 참조 될수 있다.

휴..-_- 그냥 원문 읽는거랑 번역해서 쓰는거랑 차이가 심하군..2시간이나 걸렸넹..ㅜㅜ..

microtime 의 비밀, microtime을 로컬타임으로 변환하기.

오늘은 Microtime 에 대해서 이야기 해봐야겠당. 사실 나도 정확히 요놈에 대해 알지 못한다. 그런데 오늘 이놈 때문에 삽질을 한게 있어서 적고 넘어간다. 사실 내가 하고 싶었던건, zeroboard에서 reg_date로 들어가 있는 날짜를 jsp에서 불러와 출력하고 싶었다. 내가 검색 능력이 딸려서 못찾은건지, php에서는 기본 함수로 있는데.. jsp에서는 microtime을 현재 시간으로 변환해주는 메소드를 찾지 못했다.

여기저기 Q/A를 뒤져봤지만.. 못찾았다.. 그래서 그냥 나몰라라 접어두고 있었는데.. 오늘 마침 TDD(테스트 주도개발) 연습을 하면서 날짜를 컨트롤하는 예제를 뚝딱뚝딱 하고 있었다. 그래서 이왕 하는 김에 DateTime  클래스를 java로 구현해봤다. 이놈의 역할은 간단하다. microtime 을 인자로 받아서 현재시간으로 출력해주기위한 클래스다. 이것을 구현하기 위해 microtime을 다시 찾아봤다.

검색 결과에 의하면, microtime은 100/1 초까지 유닉스시간형태로 반환을 해준다고 한다. 기준은 1970년 1월 1일 0시 ㅇ분 00초를 부터 시작이다. 중요한건 1970년 1월 1일 0시 00분 00초가 기준이라는것이다. 아마도 1970년도가 유닉스 탄생해가 아닌가하는 추측해본다. 물론 찾아보지 않았다..귀찮아서..( 누군가 유닉스 탄생시기를 알려주겠지?~ ㅎㅎ)

다시 본론으로 돌아와서 zeroboard 의 reg_date는 mysql에 int(13)으로 잡혀있다. 실제로 값을 불러오면, 10자리 숫자가 나온다. 추측해보건데,.. 이 10자리 숫자를 환산하면, 0000년 00월 00일 00시 00분 00초로 나올것이다. 마침 32비트 컴퓨터의 int형 범위도 대략 10자리수가 나온다. 여기서 재밌는 사실을 알아냈다. microtime의 유효범위가 2037년쯤 된다고 한다. 만약에 2037년이 지나면, 이상해 진다고 하던데.. 아마도 그 이유는 int 범위에 굉장히 밀접한 관계가 있지 싶다.

시간을 계산해 보면,
1분은 60초,
1시간은 3600초,
하루는 86400초,
한달은 날짜마다 계산이 다르다.
단, 1년은 365일이고, 윤년일 경우 1년은 366일..
즉, 1년은 31536000초이고, 윤년인 해일 경우엔, 31622400초가 된다.

int의 최대범위는 2147483647 이고, 이것을 평년으로 나누면,..대략 68년이 나온다. 그러므로 1970년을 기준으로하면 2038년이 딱떨어진다. ㅋㅋㅋ 이것으로, 마이크로타임은 32비트 컴에서 내부적으로 int형 4바이트로 구현되어 있음을 짐작 할수있다. 이미 microtime을 로컬타임으로 변환하기 위한, 모든 아이디어는 앞에 서술한거 같다.

다시한번 짚어보면,
윤년을 계산해 내야하고,
날짜를 계산해 내기 위해, 달별로 일수를 짚어내야한다.
물론 윤년이 낀 해의 2월은 29일이다.
요 날짜만 구해낸다면, 시간은 식은죽먹기~!
시간구할때 한가지 더 생각해봐야할껀 로컬타임..
우리나라의 경우 +9 시간을 해야한다.

그밖에

TDD 연습을 위한 페이지

AJax 토글형 댓글 링크 버튼 만들기

제목을 어떻게 해야할찌 몰라서.. 일단 [Ajax 토글형 댓글 링크 버튼] 이라고 적고 시작한다.
이게 어떤거냐면,.. Me2day에 있는 댓글(0) 버튼이라고 생각하면 된다.
미투데이에 요 버튼이 좀 재밌는데.. 버튼이라고 하면, 보통 input 태그를 이용한 버튼을 이용하지만..
요건 링크와 자바스크립트 그리고 CSS 스타일을 적절히 이용한다.

먼저 링크,
링크는 보통 아래처럼 이용한다.
<a href=”이동할 주소”>이동링크이름</a>
<a href=”./comment”>댓글</a>

여기에 자바 스크립트를 적용해서 이벤트를 걸면,..
<a onclick=”이벤트함수이름();” href=”이동할 주소”>이동 링크 이름</a>
<a onclick=”comment_list_toggle();” href=”./comment”>댓글</a>

위에 처럼 쓰는게 보통인데.. 위에 경우엔 보통 링크를 클릭하면 해당 링크로 점프를 띤다.
그러면 당근 버튼 효과를 내지 못한다.. 그래서 아래처럼..

<a onclick=”이벤트함수이름(); return false;” href=”이동할 주소”>이동 링크 이름</a>
<a onclick=”comment_lists_toggle(); return false;” href=”./comment”>댓글</a>

자바스크립트에 false를 리턴하게 되면, 클라이언트에서 서버로 전송을 하지않고, 클라이언트에서 함수만 실행하고 종료를 하게 된다. 보통 취소 버튼을 구현할때 요걸 많이 쓴다.

그러면 바로 요 이벤트 함수를 통해서 comment 라고 지정해둔 id 태그의 스타일을 변화시키면 된다.
<script type=”text/javascript”>
//<![CDATA[
        function comment_lists_toggle() {
            if(document.getElementById(“comment”).style.display==”none”)
            {
                document.getElementById(“comment”).style.display=””;
            }   
            else
                document.getElementById(“comment”).style.display=”none”;          
        }
//]]>
</script>


기본은 머 저렇게 하면되는데… 기본적으로 Ajax 콜백에 대한 이해가 있으면,..
어렵지 않게 구현할수 있을것이다..

사실 내가 젤 어려웠떤건,..-_- 따옴표 처리문제..ㅜㅜ..
아무대로 에디터를 한번 따로 만들어봐야겠다..

————— updated 2012.07 —————–
간혹 리피러를 확인해보는데, 이 포스트가 검색에 걸려 읽으시는 분들에게…
이글은 2008년 2월에 작성한 글로써, 매우 전문적인지 않은 글이니… 그냥 그려려니 참고만하세요. 🙂

윗 글에서 몇가지 정정한다면,
1. 엘리먼트의 return false;
 

 <a onclick=”이벤트함수이름(); return false;” href=”이동할 주소”>이동 링크 이름</a>

여기서 클릭 이벤트에 return false;를 하는 이유는 본래 a태그가 하는 기본 기능을 수행하지 않겠다는 의미입니다.  a 태그의 기본 기능은 바로 href로 지정된 url로 이동하는 기능을 말합니다.
따라서 위와 같이 걸면, a 태그의 기본기능을 수행하지 않게 되는 거죠!
이거 a 태그뿐만 아니라 기본 기능이 걸려있는 모든 엘리먼트에 해당하는 내용입니다.
 href=’#’ 으로 해시 값을 지정했을때는 새로 고침하지 않고, URL 뒤에 # 해시가 붙게 되는데,..
이런 해시값이 지저분하다고 느낄때도 return false를 넣어서 처리하곤 합니다.

2. 인라인 이벤트는 가급적 피하세요!
인라인 이벤트라 함은 앞에서 처럼 HTML 마크업에 바로 onclick=’어쩌고 저쩌고’ 하고 이벤트 핸들러를 할당하는 경우죠. 이거보다는 addEventListener 함수를 이용해 이벤트를 따로 등록하는 것이 좋습니다.
왜 이게 좋냐면,..
1. 마크업이 깨끗해집니다.
2. 같은 이벤트에 여러 핸들러를 중복해서 추가 할수있습니다. (인라인은 덮어버리죠!)
3. 인라인 핸들러가 정의되지 않는 시점(마크업이 그려지고 있는 시점)에 클릭하면 에러가 날수있습니다.

따라서 되도록이면 모든 마크업이 다 그려지고 나서 자바스크립트를 한번에 로드하고 처리하세요!