시각화/D3.js

▶d3.js 튜토리얼 :: 자바스크립트이해하기

비주얼라이즈 2015. 4. 3. 13:48





▶d3.js 튜토리얼 :: 자바스크립트이해하기


자바스크립트는 브러우저에 이미 떠 있는 페이지의 DOM을 조작해서 페이지를 동적으로 만들 수 있는 스크립트 언어다. 앞서 D3를 이해하는 건 자바스크립트를 이해하는 과정이라고 말했다. 앞으로 깊게 파헤쳐 보겠지만 여기서는 시작하는 의미로 조금만 맛보자.[각주:1]



자바스크립트는 보통 텍스트파일로 작성해서 저장하고 브라우저의 웹페이지에서 파일을 불러온다.

+

하지만, 웹페이지에서 직접 자바스크립트 파일을 입력하는 방법도 있다.

*새로 일을 시작할 때는 이 방법으로 코드를 빠르고 쉽게 테스트해 볼 수 잇다.

* 또한 디버깅하고 코드에서 무슨일이 일어나는지 보기위한 핵심도구로 자바스크립트 콘솔을 사용할 수도 있다.


크롬 : [설정 및 관리] - [도구]에서 자바스크립트 콘솔을 사용할 수 있다.



콘솔은 코드를 한 번에 한 줄씩만 입력받고, 어떤 코드를 입력하든 바로 결과를 뱉어낸다.

실제로 사용할 때에는 코드가 어떻게 진행되는지 지켜보기 위해서 콘솔에 자동으로 값이 출력되길 원할 수도 있다. 이렇게 하면 앞으로 나올 예제에서볼 수 있는 


console.log("something");


과같은 코드를 사용한다.






변수


변수는 데이터를 위한 공간이다. 일반변수는 하나의 값을 갖는다.[각주:2]


var number = 5;

var는 '새로운 변수를 정의하는 중'이라는 뜻이다.

'우변의 것을 좌변에 할당한다.'라고 읽자.


defalutColor = "hot pink";

변수에는 숫자와 텍스트의 문자열을 저장할 수 있다. 그리고 boolean값도 가능하다.


var thisMakeSenseSoFar = true;

자바스크립트는 구문 끝에 세미콜론(;)을 사용한다.







변수의 다른 타입


변수는 데이터의 가장 작은 단위이며, 설정이 조금씩 다른 모든 데이터 구조의 기초 형태이다.



배열

배열은 단일 변수에 적절히 저장된 값을 나열한 형태이다.


var numbers = [5, 10, 15, 20, 25];

numbers[2] //15를 반환한다.

배열에는 모든 데이터 타입을 담을 수있고, 한 배열에 다른 타입의 데이터 값을 담을 수 있다.(권장형태는 아니다.)


객체

배열이 여러 개의값을 간단한 목록으로 표현하기에는 최고의방법이지만, 좀 더 복잡한 데이터 집합은 객체에 담는게 더 적절하다.

객체는 중괄호로 표현하며, 괄호안에 프로퍼티 명과 값을 넣는다. 


var fruit = {


kind : "grape",

color : "red",

quantity : 12,

tasty : true

};


이 값을참조하려면 구두점(.)과 프로퍼티명을 사용한다.



fruit.kind //"grape"를 반환

fruit.color // "red"를 반환




객체와 배열

배열과 객체,두 구조는 객체가담긴 배열이나 배열이 담긴 객체, 혹은 객체가 담긴 객체 처럼 합칠 수있다. 기본적으로 여러분의 데이터 집합을 위한 어떤 구조도 가능하다.



과일이 두 종류 더 생겨서 목록을 확장하기를 원한다고 해보자.


바깥에는 배열을 나타내는 대괄호를 사용하고

안쪽에는 객체 기호인 중괄호를 쓴다. 

각 객체는 콤마(,)로 구분한다.



var fruits = [

{

kind : "grape",

color : "red",

quantity : 12,

tasty : true

},

{

kind : "kiwi",

color : "green",

quantity : 5,

tasty : false

},

{

kind : "orange",

color : "yellow",

quantity : 3,

tasty : true

}

];


객체가 담긴 배열에 접근하기


fruits[1].kind //"kiwi"를 반환한다.

fruits[2].color //"yellow"를 반환한다.







JSON


D3를 업으로 삼다보면 JSON(JavaScirptObjectNotation)을 맞닥뜨리게 된다. JSON에 대해서는 별도 자료로 따로 공부할 수도 있지만, 기본적으로 데이터를 자바스크립트 객체로 최적화시키는 문법 명세라고 알고 있으면 된다.[각주:3]



JSON은 자바스크립트와 AJAX의요청에 확실하게 최적화 되어있어서 JSON형태로 반환하는 웹기반 API에 많이 사용된다. JSON은 XML보다 자바스크립트로 파싱하기쉽고 빠르다. 

=그래서 D3도 JSON과 함께 사용할 때 더 잘 동작한다.


JSON은 앞에서 살펴본 형태와 크게다르지 않다.



차이점 : 프로퍼티명을 문자열로 만들기 위해서 큰따옴표(")를 사용했다는 점이다.

+또한, JSON은 다른 자바스크립트 객체와 마찬가지로 객체를 변수에 저장할수있다.***







GeoJSON


JSON은 단지 기존의자바스크립트 객체 문법을 양식화한 것이다. 

GeoJSON은 지리 정보를 저장할 목적으로 최적화한 JSON객체의 특정한 형태다.

= 결국 모든 GeoJSON객체는 JSON객체이고 모든 JSON객체는 자바스크립트 객체인 셈이다.


GeoJSON에는 지정학적 공간의 한 지점을 저장할 수있다(보통의 위도/경도 좌표다). 하지만 선과 다각형 같은 도형, 다른 공간적인 특징도 저장이 가능하다. 가지고 있는 지리 정보가 있다면 GeoJSON으로 파싱함으로써 D3와 최적의궁합을 맞출 수 있다.


** 주의 : GeoJSON에서는 항상 경도(longitude)를 위도(latitude)보다 앞에 적어야 한다. lat, lon순서 대신에 lon, lat순서에 익숙해지자.




제어문



for(): 반복문

지정된 횟수 동안(for) 코드를 순회하기 때문에 for문이라고 부른다. 처음에 초기화(initialization)구문이 실행되고, 작은 if문에 해당하는 테스트(test)구문을 평가한다. 테스트가 참이면 중괄호안의 코드를 실행하고, 마지막에 업데이트(update)구문을 실행한다. 그리고 테스트를 재평가한다.[각주:4]


for문에서 i값을 1이 아니라 0부터 시작하는 이유는?

관습이긴하지만 컴퓨터가 배열값을 세는 방법과 멋지게 들어맞는다. 웬만하면 for 반복문은 0부터 시작하자.



배열과 for문으로 하는일

코드기반의 데이터시각화는 배열과for() 반복문이라는 무기 없이는 만들수없다. 데이터 매니아에게 배열과 for()문은 환상적인 듀엣이다.

*모든 배열에는 length라는 프로퍼티가 있다.





함수


함수란 어떤일을 하는 코드 덩어리를 말한다. 함수는 전달인자를 입력 받은 후, 출력 값을 반환할 수 있는 특수한 형태다.

괄호는 함수 호출(실행)을 위해 사용한다. 함수가 전달인자로요구하는 입력 값을 괄호 안에 적으면, 그 인자가 함수로 전달된다.


가장 중요한 것은 스스로 함수를 정의할 수 있다는 것이다.

자바스크립트는 함수를 정의하는 여러가지 방법을 제공한다. 가장 간단한 방법은 다음과 같다.


// 레스토랑에서 식사를 하고 직원에게 줘야하는 팁을 계산하는 함수.


var calculateGratuity = function(bill) {

return bill * 0.2;

};


이 함수는 입력값을 취해서 0.2를 곱한결과를 출력 값으로 반환한다.



이 출력값 자체를 나중에 사용하기 위해 변수로 저장할 수 있다.

var tip = calculateGratuity(38);

console.log(ti); // 콘솔에 7.6을 반환한다.


calculateGratuity와 같이 이름이 없는 함수를 익명함수(anonymous function)라고 한다. 익명함수는 D3에서 빈번하게 사용된다.




자바스크립트 파일 참조하기


자바스크립트는 script태크를 사용해서 HTML안에 직접 넣어서 사용할 수 있다.


<body>

<script type = "text/javascript">

alert("Hello, world!");

</script>

</body>


또한, .js 확장자를 사용한 별도 파일로 HTML 어딘가에 넣어서 참조할 수도 있다.

(head에 넣거나 body의 닫는태그(</body>)바로 앞에 넣을 수 있다.)


<head>

<title> 페이지 타이틀 </title>

<scirpt type = "text/javascript" src="myscript.js"></script>

</head>





자바스크립트의 핵심개념 4가지


스캇머레이(2014)는 저서 『D3.js』에서 자바스크립의 핵심 개념을 네 가지로 나누어 정리했다. 그에 따르면, 네 가지 개념을 잘 이해하면 디버깅으로 인한 늦은 야근을 피할 수 있을 것이라고한다. 



스캇머레이가 말하는 자바스크립트의 핵심개념 4가지

① 동적타입

② 함수 호이스팅

③ 함수 단위의 유효범위

④ 전역네임스페이스




① 동적타입


자바스크립트는 타입이 매우 느슨한 언어이다. 느슨한 타입이란 여러분이 변수에 저장할 정보가 어떤 타입인지 사전에 지정할 필요가 없다는 의미다.


자바같은 다른 언어들은 int, float, boolean, String등의 변수 타입을 반드시 사전에 선언해야 한다.

//자바에서의 변수선언

int number = 5;

float value= 5.2302;

boolean active = true;

String text = "문자열 변수선언";



하지만 자바스크립트는 여러분이 할당한 정보의종류를 바탕으로 변수의타입을 자동으로 지정한다.

//자바스크립트의 변수선언

var number = 5;

var value = 5.2302;

var active = true;

var text = "문자열 변수 선언";

 ('이나 "는 문자열 값을 나타낸다. 작은따옴표를 쓰는 사람들도 있지만 가능하면 큰 따옴표를 사용하자.)



유연하다

이렇게 자바스크립트는 변수에 들어갈 데이터 타입을 알기전에도변수를 선언하고 명명할 수 잇으므로 좀 더 유연하다.


그때 그때 필요에 따라서 타입 변경을 할수도 있다.

var value = 100;

value = 99.999;

value = false;

value = "필요에따라 타입변경이 자유롭다.";



유연한만큼 주의가 필요하다.

코딩을 하다보면 숫자가 들어가야할 변수에 우연히 문자를 저장하는 일이 생길 수 있다. 이로 인해서 코드 일부가 잘못 동작할 수 있다. 우리는 변수 타입이 언제나 불확실하다는 사실을 정확히 아는 게 도움이 된다.



변수타입을 확인할 수 있는 typeof연산자를 활용하자.

typeof 67; // "number"를 반환한다.








변수 호이스팅(hoisting)


자바스크립트가 보통 위에서 아래로 실행될거라고 생각하지만, 실제로는 조금 다르다. 


var numLoops = 100;

for (var i = 0; i < numLoops; i++){

console.log(i);

}


다른 프로그래밍 언어에서는 여러분의 예상대로 반복문이 시작될 때 i가 선언된다. 하지만 자바스크립트에서는 변수 호이스팅(variable hoisting)이라는 현상 덕분에, 변수 선언이 변수가 속한 함수컨텍스트의 최상단으로 끌어올려진다. 그래서 앞의예제의 변수 i는 사실상 for반복문이 시작되기도 전에 선언된다. 


var numLoops = 100;

var i;

for(i = 0; i < numLoops; i++){

console.log(i);

}


이처럼 변수 i는 실제로 for()반복문 앞에서 선언되는 것 처럼 동작한다. 

= 따라서 변수 명이 충돌하는 문제가 발생할 수 있다.



이러한 자바스크립트의 특성은 함수(function)에서도 동일하게 적용된다. 함수 역시 변수에 할당되는 객체이기 때문이다.




함수 단위의 유효범위


프로그래밍에서 변수 유효범위(variable scope)란 어떤 변수가 어떤 컨텍스트에서 접근 가능한지를 알려 주는 개념이다. 일반적으로 모든 값을 어디서나 접근 가능하게 하는 건 좋은 생각이 아니다. 그렇게 하면 변수 값의충돌이나 값이 돌발적으로 변경되는 경우가 많아서 미쳐버릴지도 모른다.


많은 언어들은 블록 레벨 유효범위(block-level scope)를 사용한다. 이 유효범위를 따르면 변수는 코드의 해당 '블록'에서만 존재한다.블록은 보통 중괄호({)로 표현한다. for()반복문을 예로들면, 반복문 밖에서 i를 참조하거나 정의하려고 하면 실패한다. 이렇게 유효범위가 블록단위이면 전체 코드 중 어딘가에 존재할지도 모를 변수와 충돌하지않는 다는 사실을 확실히알고 개발할 수 있기 때문에 상당히 유용하다.


하지만 자바스크립트에서는 변수가 함수 레벨에서 유효범위를 갖는다.

즉, 자바스크립트는 블록이 아니라 변수가 속한 함수 기준으로 접근을 제한한다.

*자바스크립트에서는 함수로 감싸야지만 변수값을 유지할 수 있다.






전역 네임스페이스


window는 자바스크립트문서요소의 계층구조에서 최상위 객체다. 객체와 값은 전부 전역 레벨에 존재하는 window객체 아래에 있다. 즉, 새로운 변수를 선언할 때마다 window에 새로운 값이 추가된다.


예를들어 웹브라우저 자바스크립트콘솔창 window에 다음과 같이 새로운 변수를 추가한다고 하자.

zebras = "amazing"

//var zebras = "amazing"과 동일하다.


이로써 야기될 수 있는 문제는 무엇일까? 

처음은 괜찮지만 프로젝트가 복잡해지기시작하고 D3가 아닌 자바스크립트 코드(jQuery나 페이스북의 좋아요버튼, 구글 웹 로그 분석용 코드 등)를 하나 둘 포함하기 시작하면, 충돌이 일어나는 상황에 맞닥뜨리게 된다.


왜냐하면, 프로젝트에 zebras란 변수를 사용하고 있는데, zebraTracker.js라는 라이브러리가 동명의 변수를 사용할 수 있기 때문이다.( 결과는 혼돈속으로 흘러가거나 아니면 적어도 어떤 불량 데이터가 예상할 수 없는 동작이나 에러를 유발하게 될 것이다. )



변수 선언에 관한 문제는 두 가지 방법으로 쉽게 해결할 수 있다.

① 함수 안에서만 변수를 선언한다.

② 전역 객체를 하나 선언하고,그 객체에 필요한 전역 변수를 모두 추가한다.


① 함수 안에서만 변수를 선언한다.

보통은 실현하기 어렵지만, 함수 레벨 유효범위는 다른 변수와의 충돌을 막아 준다.


② 전역 객체를 하나 선언하고,그 객체에 필요한 전역 변수를 모두 추가한다.


var Vis = {}; // 텅 빈 전역 객체를 선언한다.

Vis.zebras = "still pretty amazing";

Vis.monkeys = "too funny LOL";

Vis.fish = "you konw, not bad";


이제 더 이상 동물 이름의 변수들이 전역 네임스페이스를 오염시키지 않는다. 대신에 Vis라는 단일 전역 객체에 값으로 저장된다. 물론 Vis라는 객체 명은 zebras경우처럼 다른 라이브러리와 충돌할 만한 이름만 아니면 어떤 이름이든 관계없다.


























  1. 스캇 머레이 지음, 변치훈 옮김, 『D3.js : 쉽고 빠른 인터랙티브 데이터 시각화』, 인사이트, 2014.3, 46쪽. [본문으로]
  2. 위의 책, 47쪽. [본문으로]
  3. 위의 책, 51쪽. [본문으로]
  4. 위의 책, 55쪽. [본문으로]