한동안 포스팅이 좀 뜸했었죠? 회사 솔루션에 대한 라이센스 정책을 만들고, 그에 대한 구현을 하느라, 그리고 외산 솔루션 하나 분석하느라 정신이 없네요. 가끔은 정말 제 자신이 둘 정도 있었으면 하는 바람입니다. ... 


그래서 말인데 오늘은 JDK7.0부터 새롭게 제안된 Fork/Join 방식에 대해 소개할까 합니다. 소개라기보다는 그냥 링크인데요, 그리 길지 않아 번역을 할까 하다가 갑작스레 귀차니즘이 발동하여.... 그렇게 됐습니다. 나중에 시간적 정신적 여유가 생기면 따로 번역해 보기로 하죠. 


Fork와 Join 태스크들간의 협력 관계랍니다.


구글에서 Fork Join Java로 검색을 하면 몇 가지 읽을만한 아티클들을 찾아볼 수 있습니다. 그 중 제가 봤을때 가장 내용이 충실했던 것은 바로, http://www.oracle.com/technetwork/articles/java/fork-join-422606.html 입니다. Fork/Join이 없던 시절의 프로그래밍 기법과 비교도 해 주고, 실제 소스 코드도 제공해주니 도움이 될 것입니다. 더욱 더 좋은 점은, 피보나치 수열과 같은 너무나도 간단해서 그닥 쓸모 없는 예제가 아니라 그럭저럭 실제로도 쓸만한 예제를 다루고 있다는 점이랄까요.


아 근데 제 Java Concurrent Programming 책은 어디 간 걸까요...


신고
Posted by Layered 트랙백 0 : 댓글 0

댓글을 달아 주세요

이번 포스트에서는 초보 프로그래머들이 다서 어려워하는 개념인 클로저(Closure)에 대한 내용을 다루도록 하겠습니다. 

사실 '자바스크립트 클로저'라고 검색을 하면 수많은 Q&A와 포스트들을 찾을 수 있는데요, 그 많은 글들을 읽어보아도 완벽하게 손에 쥘 듯 이해되지는 않는 듯 합니다. 저도 마찬가지였구요. 그 이유는 크게 두 가지인 것으로 생각됩니다. 하나는, 클로저와 객체의 스코프(영역, Scope)를 통합하여 이해하지 못하기 때문이고, 다른 하나는 클로저라는 것이 왜 클로저라고 불리는지 이해하지 못하기 때문입니다. 실제로 클로저를 능숙하게 사용한다는 자바스크립트 프로그래머들에게 클로저가 왜 클로저라고 불리느냐 물어보면 제대로 대답하지 못하는 경우가 많더군요. 

어쨌든, 이 글을 통해 클로저와 스코프에 대해 명확히 이해할 수 있기를 기대하며 시작해보도록 하겠습니다. 이 글의 원문 주소는  http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/ 입니다.



이 글에서는 많은 사람들이 어려워하는 개념에 대해 다룰까 합니다. 바로 자바스크립트의 유효 범위(scope)와 클로저(closure)에 대한 내용입니다.

 

1. 배경 (Background)

이미 매우 많은 기사나 블로그에서 자바스크립트의 유효범위와 클로저에 대해 다루었지만, 필자가 생각하기에 그들 대부분 명백하고 확실했던 것 같지는 않았습니다. 게다가 그 글들 중 상당수는 사람들이 적어도 15개 정도의 다른 프로그래밍 언어를 경험한 것으로 간주하는 것 같았습니다. 하지만 제 경험상 자바스크립트를 개발하는 대부분의 사람들은 CJava 같은 언어가 아니라 HTMLCSS를 먼저 접하고 개발을 시작했었습니다.

하여, 제 최종 목표는 유효범위와 클로저가 무엇인지, 어떻게 동작하는지, 그리고 어떤 점이 좋은지에 대해 모든 사람들이 명확하게 이해할 수 있도록 돕는 것입니다. 물론, 이 글을 읽기 전에 변수(variables)나 함수(functions)의 개념에 대한 기본적인 이해는 필요할 것입니다.

 

2. 유효범위 (Scope)

유효범위라 함은, 변수나 함수가 접근 가능한 영역, 혹은 어떤 맥락(context)이 실행되는 곳을 의미합니다.  기본적으로 변수나 함수는 전역(global scope)이나 지역(local scope)적으로 선언될 수 있습니다. 변수들은 소위 함수영역(function scope)라고 불리는 유효범위를 갖고 있고, 함수들도 변수로서 동일한 유효범위를 갖고 있습니다.


- 전역 범위(Global Scope)

 무엇이든 전역적이다 라고 말한다면, 그것이 코드의 어느 곳에서든 접근 가능하다는 것을 의미합니다. 다음 예제를 확인해 보시기 바랍니다.


var monkey = "Gorilla";

function greetVisitor () {
	return alert("Hello dear blog reader!");
}

 

이 코드가 브라우저 내에서 실행된다면, 이 함수의 유효범위는 window 객체가 될 것입니다. 그러므로 해당 브라우저에서 실행되는 모든 코드에서 접근 가능할 것입니다.


- 지역 범위(Local Scope)

 전역 범위와는 다르게 지역 범위라고 하면, 함수와 같이 코드의 어떤 부분에서만 접근이 가능하게 정의되었다는 것을 의미합니다. 예를 들어 봅시다;


function talkDirty () {
	var saying = "Oh, you little VB lover, you";
	return alert(saying);
}
alert(saying); // Throws an error


위 코드에서, saying이라는 변수는 talkDirty라는 함수 내에서만 접근할 수 있습니다. 이 함수의 외부에서는 정의된 적이 없죠. 주의할 점은, 위의 2 라인에서 sayingvar 지시자 없이 선언하면 이 변수는 자동적으로 전역변수가 된다는 것입니다.

이것이 의미하는 바는, 함수 내에 중첩된 함수가 자신을 포함하고 있는 함수의 변수와 함수에 접근할 수도 있다는 것입니다:


function saveName (firstName) {
	function capitalizeName () {
		return firstName.toUpperCase();
	}
	var capitalized = capitalizeName();
	return capitalized; 
}
alert(saveName("Robert")); // Returns "ROBERT"


위 코드에서 볼 수 있듯, capitalizeName 함수에는 어떠한 입력 파라미터도 없습니다만, 그를 포함하고 있는 함수인 saveName의 파라미터-firstName에 접근할 수 있습니다. 좀 더 명확히 알기 위해 예제를 하나 더 보기로 하겠습니다.


function siblings () {
	var siblings = ["John", "Liza", "Peter"];
	function siblingCount () {
		var siblingsLength = siblings.length;
		return siblingsLength;
	}
	function joinSiblingNames () {
		return "I have " + siblingCount() + " siblings:\n\n" + siblings.join("\n");
	}
	return joinSiblingNames(); 
}
alert(siblings()); // Outputs "I have 3 siblings: John Liza Peter"


여기서 알 수 있듯이, 두 개의 내부 함수 모두 siblings라는 지역 변수에 접근할 수 있고, 또 각각의 내부 함수들은 서로 접근할 수 있습니다.(여기서는 joinSiblingNames 함수가 siblingCount 함수에 접근하고 있습니다.) 하지만 siblingLength라는 변수는 siblingCount라는 함수 내에서만 접근할 수 있는데, 이것이 이 변수의 유효범위인 것입니다.

 

3. 클로저 (Closure)

실행범위에 대해 좀 더 잘 이해했을테니, 이제 거기에 클로저에 대한 개념을 섞어봅시다. 클로저라는 것은 (보통은 함수인) 표현식인데, 어떤 실행 맥락 내의 변수 집합과 연동할 수 있는 것을 의미합니다. 혹은, 좀 더 쉽게 설명한다면, 외부 함수의 지역 변수를 참조하는 내부 함수들은 클로저를 만들게 됩니다. 예를 들면 다음과 같습니다.


function add (x) {
	return function (y) {
		return x + y;
	};
}
var add5 = add(5);
var no8 = add5(3);
alert(no8); // Returns 8


와우, 도대체 무슨 일이 일어난 걸까요? 한 번 자세히 살펴봅시다.

1. add 함수가 호출되었을 때함수가 하나 리턴됩니다.

2. 이 함수는 현재의 실행 맥락(context)을 폐쇄(close)하고 그것이 실행될 때의 파라미터 x의 값을 기억합니다. (위 코드에서는 5입니다.)

3. add함수의 실행 결과가 add5 변수에 할당되었을 때이 변수도 최초 초기화 되었을 때의 값을 알고 있게 됩니다.

4. add5 변수는 항상 입력된 값에 5를 더하는 함수를 참조하게 된 것입니다.

5. , add5에 입력 파라미터로 3을 이용하면, 5 3을 더하여 8을 리턴하게 됩니다.


, 자바스크립트 세계에서 add5 함수는 다음과 같이 동작하게 될 것입니다.


function add5 (y) {
	return 5 + y;
}


- 악명높은 반복문(Loop) 문제

i라는 값을 원하는 방식 대로 할당하기 위해 얼마나 많이 반복문을 만들어 봤습니까? , 엘리먼트들에 입력된 i들이 모두 마지막 값만 리턴하는 것을 본 적이 있습니까?


+ 잘못된 참조

먼저 잘못된 코드를 살펴보기로 합시다. 이 코드에서는 다섯 개의 a 엘리먼트를 생성하고 거기에 각각의 i 에 해당하는 값을 텍스트(‘Link’+i)로 추가하고 alert로 그 i값을 출력하는 onclick 이벤트를 추가합니다. 아마도 다음과 같은 모양이 될 것 같습니다.


function addLinks () {
	for (var i=0, link; i<5; i++) {
		link = document.createElement("a");
		link.innerHTML = "Link " + i;
		link.onclick = function () {
			alert(i);
		};
		document.body.appendChild(link);
	}
}
window.onload = addLinks;


각각의 엘리먼트들은 원하는 대로 “Link0”, “Link1”등의 텍스트를 포함하게 됩니다. 하지만 각각을 클릭했을 때에는 모든 엘리먼트들이 5를 출력하는 것을 볼 수 있을 것입니다. 도대체 무슨 일일까요? 그 이유는, i라는 변수가 반복문 내에서 매번 1씩 증가하는데, onclick 이벤트가 호출되지 않았으므로, 매번 더해진 값이 각각의 엘리먼트에 적용되는 것입니다.

그러므로 반복문은 i 5가 될 때 까지 반복될 것인데, 그 값은 addLink라는 함수가 종료되기 직전의 마지막 값입니다. 그래서, onclick 이벤트가 호출된다 하더라도 i의 마지막 값인 5가 출력됩니다.


+ 실행 참조

이를 위해 클로저를 생성하여 i 값을 설정할 때, 설정하는 순간의 i 값이 onclick 이벤트에 적용되도록 해야 합니다. 다음과 같이 말이죠.


function addLinks () {
	for (var i=0, link; i<5; i++) {
		link = document.createElement("a");
		link.innerHTML = "Link " + i;
		link.onclick = function (num) {
			return function () {
				alert(num);
			};
		}(i);
		document.body.appendChild(link);
	}
}
window.onload = addLinks;


이 코드를 실행하면, 첫 번째 엘리먼트는 0, 두 번째는 1우리가 정확히 원했던 방식대로 출력됩니다. 여기서 사용한 해결책은 onclick 이벤트에 적용되는 내부 함수가 num이라는 파라미터를 입력받는 클로저를 생성하는 것입니다. 그리고 여기에 그 시점의 i가 이용됩니다.

그 뒤 이 함수는 i 값을 안전하게 간수한 뒤 폐쇄(close)되며 호출될 때 최초 입력되었던 값을 그대로 리턴할 수 있게 됩니다.

 

- 자기 실행 함수 (Self-Invoking Function)

자기 실행 함수는 즉시 실행되는 함수를 말하는데, 그를 위해 자기 자신이 클로저를 생성합니다. 다음을 살펴봅시다.


(function () {
	var dog = "German Shepherd";
	alert(dog);
})();
alert(dog); // Returns undefined


알겠지만, dog이라는 변수는 자신의 맥락 내에서만 사용이 가능하도록 숨겨져 있습니다. 숨겨진 개(dog)라니놀랍군요. 하지만 정말 놀라운 부분은 이제부터 시작인데요, 이 방식으로 위에서 다뤘던 반복문 문제를 해결했다는 점입니다. 그리고 이것은 Yahoo Javascript Module Pattern의 기반이기도 합니다.


+ Yahoo Javascript Module Pattern

이 패턴의 요지는 클로저를 생성하는 자기 호출 함수를 이용한다는 것인데, 그 결과 private이나 public 속성/메소드를 정의할 수 있게 됩니다. 다음의 간단한 예를 살펴보죠:


var person = function () {
	// Private
	var name = "Robert";
	return {
		getName : function () {
			return name;
		},
		setName : function (newName) {
			name = newName;
		}
	};
}();
alert(person.name); // Undefined
alert(person.getName()); // "Robert"
person.setName("Robert Nyman");
alert(person.getName()); // "Robert Nyman"


  이 코드의 아름다운 점은 이제 우리가 객체에 대해 어떤 것은 public으로 접근하게 하고, 어떤 것은 private으로 만들어 외부에서 함부러 바꾸지 못하게 할 수 있다는 것입니다. 위에 정의되어 있는 name이라는 변수는 이 함수의 외부에서는 접근이 불가능하지만, name 변수에 대한 참조를 갖고 있는 클로저를 생성하기 때문에 getName 함수와 setName 함수를 이용하여 값을 얻거나 변경할 수 있게 됩니다.

 

4. 결론

필자의 순수한 희망은, 초급이든 숙련된 개발자이든 간에, 자바스크립트 내에서 유효범위와 클로저가 어떻게 동작하는지 명확하게 이해하는 것입니다. 질문과 피드백은 언제든 환영합니다. 여러분들이 제공해 주신 어떤 내용이든 중요하다고 생각되면, 이 글에 지속적으로 반영하도록 하겠습니다.



이해가 잘 되셨나요? 원문에 쓰여 있는 대로, 질문과 피드백은 언제든 환영합니다. 즐거운 코딩 되시길~

신고

'일하기 > JAVASCRIPT' 카테고리의 다른 글

[번역] Explaining Javascript Scope and Closure  (0) 2013.08.28
Posted by Layered 트랙백 0 : 댓글 0

댓글을 달아 주세요


  • 간일 : 2013년 5월
  • 규격 : 320페이지 / 486g / 153x244mm


휴가 기간동안 뚝딱 읽기 딱 좋은 책입니다. 고작 320페이지에 글자 크기도 작지 않고, 여백도 시원시원합니다. 거기다가 들고 다니기에 부담스럽지 않은 486g이니, 수영장 카바나에서나 해변의 파라솔 아래서 슬며시 지적 허영심을 충족시키기에 충분한 책이랄까요. (실제로 제가 그랬습니다.)



내용인 즉슨, 사이코패스(psychopath)라는 존재들이 우리가 일반적으로 생각하는 대로 '잔혹한 범죄를 일으키고 인간성이라고는 눈꼽만큼도 없는 무시무시한 존재'인 것만은 아니라는 것입니다. 상당수의 사이코패스들의 경우, 성격을 구성하는 요소들 중 일부가 극단적으로 발현된 것이며, 그들의 성격적 특성이나 그들이 보이는 행동들이 오히려 현대 사회를 이끌어가는 힘이자 도피처가 될 수 있다고 얘기합니다. 사회와 공동체에 극단적인 피해를 주는 몇 가지 요인들을 제거할 수 있다면 말이죠. 



한국어판 제목은 [천재의 두 얼굴, 사이코패스]라고 되어 있기는 하지만, 원서의 제목은 [the Wisdom of Psychopaths]로 직역하면 "사이코패스들의 지혜" 정도가 될 것입니다. 그리고 솔직히 말하면, 한국어판 제목은 책의 내용을 제대로 요약할 의지가 없는, 말 그대로 "독자를 끌기 위한 낚시" 제목이라고 할 수 있습니다. 천재가 두 얼굴을 가진 사이코패스다라는 개념보다는, 사이코패스들 중 일부는 몇몇 영역에서 천재성을 보인다, 혹은 몇몇 영역에서 매우 유능하다, 혹은 사이코패스의 성격적 특성들이 천재(혹은 유능한 리더)의 특징들인 것 처럼 보일 수 있다 정도로 이해하는 것이 훨씬 이 책의 논조에 부합됩니다. 즉, 이 책은 천재와 천재성에 대해 적극적으로 설명하지도, 정의내리지도 않습니다. 모든 초점은 사이코패스와 그들의 유능성에 맞춰져 있죠. 이런 면에서 볼 때, 원서의 제목이 훨씬 더 적절하다고 할 수 있겠네요.



한국어판 제목이 어쨌든 간에, 이 책이 사고를 넓혀주는 데 도움을 준다는 사실은 분명합니다.(적어도 저의 경우에는 그랬습니다.) 


가장 먼저, "사이코패스"라고 하는 존재의 지평을 넓혀줍니다. 사이코패스는 "잔혹한 도끼 살인마"도 아니고 "감정이 100% 없는 살인 기계"인 것도 아니라는 것이죠. 좀 위험한 발언일 수 있습니다만, '호모 사피엔스보다 진화된 새로운 종족'이라는 말까지 나옵니다. 


'차가운 공감'이라는 개념도 눈길을 끕니다. 공감이라고 하면 일반적으로 "따뜻한, 마음을 주고받는" 이라는 뜻을 내포하지만, 이 책에서는 "완벽하게 상대방의 감정 상태를 이해하고 그것의 근원을 파악해내는"것도 공감이며, 이것이 사이코패스들의 근원적인 힘이라고 말합니다.


또, '기능성 사이코패스'라는 개념을 제시하여, 어떤 사람이 특정 상황에서 보이는 '유능함'이 사이코패스적 특징에 의한 것일 수 있음을 설명합니다.

 

단순화하긴 하였지만, 성공하는 사람들의 일반적인 특징을 정의하고 그것들이 사이코패스적 특질들과 연관이 있는지도 알려줍니다. 일반적으로 사이코패스적 특질이라 알려진 무자비함/매력/집중력/강인한 정신/겂 없음/현실 직시/실행력이 사실은 일반인들이 우리의 리더에게 요구하는 특성임을 상기시켜주면서 말이죠.



약간 무리수인 부분들도 보이긴 합니다. 특히 마지막에 나오는 티벳 승려에 대한 내용이라던가, 명상이나 동양 철학의 공(空) 개념을 사이코패스적 특징에 연결한다던가 하는 내용들이 그러합니다. 사이코패스적 특징들이 현대 사회를 살아가는 데 도움을 줄 수 있다는 얘기를 하면서 너무 멀리 가버린 것이 아닌가 싶습니다. 하지만, 책 전체에 흐르는 일관적인 논조를 해칠 정도는 아니라고 할 수 있을 듯 합니다. 그냥 읽으면서 '아 좀 무리수...' 정도라고 생각된다고 할까요.



어쨌든, 이 책을 읽은 독자가 "사이코패스들의 지혜"를 받아들이건 받아들이지 않건, 한 때의 지적 호기심과 허영심을 채우기에 충분한 책이라 생각됩니다. 마지막으로 이 책에 나오는 사이코패스가 한 말을 인용하며 장황했던 서평(?)을 마칠까 합니다.


"나는 어린 시절부터 사물을 보는 시각이 남달랐습니다. 하지만 이런 남다른 시각은 오히려 살면서 내게 도움이 됐죠. 이게 옳은 표현인지는 모르겠지만, 굳이 말하자면 사이코패스 성향은 현대사회의 치료제와도 같습니다. 이 치료제를 적당히 복용하면 매우 유익하죠. 왜냐하면 부서지기 쉬운 현대인들의 심리 상태를 보호해주고, 삶에서 느끼는 불안감을 덜어 주기 때문입니다. 하지만 과다 복용을 할 경우에는 다른 약과 마찬가지로 부작용이 생길 수 있습니다. "



신고

'읽기' 카테고리의 다른 글

천재의 두 얼굴, 사이코패스  (0) 2013.08.27
Posted by Layered 트랙백 0 : 댓글 0

댓글을 달아 주세요


티스토리 툴바