■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (7)

이번에는 자바스크립트의 함수 메모리 구조에 대해서 살펴보도록 하겠다.
먼저 메소드 오버로딩에 대해서 살펴보겠다.
객체지향언어에서 메소드오버로딩은 같은 메소드명을 가졌지만 시그니쳐중에서, 인자값의 개수나 형이
다른것을 의미한다.
하지만 자바스크립트에서는 메소드오버로딩이 동작하지 않는다.
오히려 그보다 훨씬더 유연하게 개발이 가능하다.
예를 하나 보자.

function add(a, b) {
    var total = 0;
    for (var i = 0; i < arguments.length; ++i) {
        total += arguments[i];
    }
}

먼저 add(10); 이렇게 호출하면 a = 10이 처음 할당되고, b에는 undefined가 할당된다.
즉 파라미터 처음부터 값이 할당되고 호출부분에서 인자수가 부족하다면 나머지 값은 모두 undefined로 채워진다.

다음으로는 선언한적도 없는 arguments라는 배열이 보인다. 하지만 이것은 배열이 아니다. 자바스크립트에서 배열처럼 보이게
만들어준 것일 뿐이다. 따라서 Array객체의 함수들은 사용할수 없고 다면 length나 []연산자를 제공한다.

다시 함수 메모리 구조로 돌아와 보겠다.
먼저 함수의 구조를 살펴보겠다.

함수는 위에서 오버로딩을 설명하면서 이야기했던 arguments와 a,b같은 인자값을 하나의 객체로 들고 있는 호출객체가 있다.
위 코드를 살짝 바꿔보겠다.
add(10)을 호출하는 순간 내부에서는

add({a:10, b:undefined, arguments:[10]});

이렇게 바뀐다. 즉 10만 호출했을 뿐인데 저렇게 하나의 호출객체가 들어간다는 의미이다. 그리고 저 객체는 이름이 없다.
즉 add함수 내부에서는 저 객체가 전역객체 처럼 작용한다.
전역객체란 말이 나왔는데 바꿔말하면 우리가 브라우져스크립팅을 할때 내부에 코드를 작성하면
우린 window란 전역객체가 생긴다. 또한 window는 생략이 가능하다.
console.log(); 이부분도 window.console.log()처럼 될수 있다는 의미이다.

var console = {
    log:function(…){}
};

(function(??){
    console.log(1);
})({console:console});

이런식으로 사용하는것이 생략되었다고도 가정할 수 있다.

현재 메모리구조를 설명하면서 함수의 호출객체에 대해서 설명했다. 즉 함수가 만들어지면 저러한 호출객체가 자동으로 만들어 진다는 의미이다.
다음 구조를 보도록하겠다.
다음으로는 prototype 객체가 하나 만들어진다. 하지만 이것은 일반적인 우리가 알고있는 객체와는 조금 다른 성질을 지녔다.
이부분은 나중에 다시 설명하도록하겠다.

다음구조는 실제 코드가 올라가는 영역이 필요하다.
이부분에서 선언되어진 변수들은 객체지향에서 private메소드, 속성과 대응된다.

마지막 구조는 함수의 속성값을 달수 있다는 부분이다. 함수는 앞에서 말한 일반 객체가 아니다. 그럼에도 불구하고 저렇게 사용할 수 있으며, public 메소드와 대응될수도 있으며, 만약 add를 Addition라고 대문자 명사로 바꾸면서 생성자로서 사용한다고 하면
static 메소드, 속성이 될수도 있다는 의미이다.

add는 함수이다. 하지만 자바스크립트에서 함수는 first class function 즉 일반 객체처럼도 사용이 가능하다는 의미이다.
따라서 add.a = 10; 이렇게 사용이 가능하며 마지막 구조인 “함수의 속성값을 달수있다”라는 부분이 나타난다.

정리하면 함수의 구조는
호출객체, prototype객체, 코드영역, 공개영역 이렇게 나누어진다.

살짝더 정확히 이야기하면 코드영역 즉 private영역에 예외적으로 (자바스크립트엔진에 의해서) prototype을 가르키는 객체가 하나더 있으며 이는 앞서 말한 prototype객체를 참조한다.

다음시간에는 객체 참조 체인에 대해서 알아보도록하겠다.

Standard
■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (5)

1. 논리연산자
자바스크립트에서는 논리연산자가 특별하게 사용된다.
다음 코드를 보자.

var a = true;
var b = “hello”;
var c = 0;
var d = null;
var e = “”;

var result = a || b;
var result2 = b && c;
var result3 = c && d;
var result4 = d || a && b;
var result5 = a && b || c;
var result6 = e || a;

각각의 result값은 어떻게 될까?

논리연산자를 일반 변수에 사용한 것이 이상하게 보일 수 있다.
하지만 자바스크립트에서는 이것이 허용되며 다른 언어와는 다른 특별한 의미도 갖고 있다.

각 결과는 다음과 같다.

result = true;
result2 = 0;
result3 = 0;
result4 = “hello”;
reulst5 = “hello”
result6 = true;

이것을 보고 유추를 할수 있는 것은 다음과 같다.

X || Y 에서 X가 거짓이면 Y를 반환한다. 그리고 X가 참이면 X를 그대로 반환한다.
X && Y 에서 X가 거짓이면 X를 반환한다. 그리고 X가 참이면 Y를 반환한다.

간단한 실제 예를 들어보겠다.

if (param && param.user && param.user.lv >= 100) {
//blabla
}

위 코드는 param이 존재하면 param.user를 반환하고, param.user가 존재하면 param.user.lv을 반환하고 100과 비교하여
참 혹은 거짓을 판별한다.
이때 param이 거짓이면 바로 거짓으로 판단하고 해당 if문을 수행하지 않는다.

다음으로 유추할 수 있는것은
거짓으로 구분하는 형태들이다.

자바스크립트에서는

null, undefined, 0, “”, false, NaN 은 모두 거짓으로 판단한다.

2. null 과 undefined
null은 명시적으로 데이터가 없다는 것을 의미한다.
반면 undefined는 데이터의 초기값이 정해지지 않았을때 할당된다.

두 값 모두 거짓을 의미한다.

var a = null;
var b;

if (a == b) {
// blabla
}

위와 같은 코드가 있을때 if문 로직을 수행할까?
정답은 수행한다 이다.

그렇다면

if (a === b) {
// blabla
}

위와같은 코드는 어떨까? if문 로직을 수행할까?
해당 로직은 수행하지 않는다.

== 비교와 === 비교가 있다.
== 비교는 비교하기전에 두 피연산자를 같은 타입으로 변환시킨 후 비교한다.
하지만 ===비교는 해당 타입 그대로 비교하기 때문에 타입과 값이 모두 같아야 한다.

3. for문

자바스크립트에서는 for in 문이 존재한다.

var persons = {a:1,b:2,age:24};
for (var key in persons) {
    console.log(key, persons[key]);
}

처럼 객체또한 for문을 돌릴 수 있다.

하지만 어쩔수 없는 상황이 아니라면 for in문은 자재하도록 하자.
그 이유는 뒤에서 다시 알아보도록하자 일단
성능이 급격히 저하된다는 사실을 인지하면된다.

또한 자바스크립트에서는 최대한 a.b.c.d.e 와같은 접근을
var f = a.b.c.d.e;
로 해놓고 f로 접근 하는 것이 좋다.
이또한 비슷한 이유이다.

Standard
■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (4)

아주 간단하지만, 두번의 실행단계에 의해서 이루어지는 다음의 코드를 설명하려면 약간 복잡할 것이다.

그래도 한번 도전해보자!.

 

1. 아래 코드를 파싱과 실행 단계로 나누어서 순차적으로 설명하시오.

console.log(1, Person());
console.log(2, person);

var person = 1001;

var Person = function(age, height) {
    return age + “:” + height;
}

function Person() {
    console.log(SubPerson());
    var SubPerson = function() {
        return 10000;
    }
    function SubPerson() {
        return 20000;
    }
    return SubPerson();
}

person = Person(10,100);

console.log(3, person);
Standard
■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (3)

이번엔 좀더 자바스크립트의 내부를 살펴보도록 하겠다.

 

먼저 다음의 코드 부터 확인해보자.
아래 코드의 console.log()의 값은 1,2,3 각각 어떻게 나올까?

console.log(1, Person());
console.log(2, person);

var person = 1001;

function Person() {
    return 1000;
}

var Person = function(age, height) {
    return age + “:” + height;
}

person = Person(10,100);

console.log(3, person);

설명을 하면, 자바스크립트는 크게 두단계의 과정을 걸쳐서 프로그램을 실행시킨다.
이러한 이유는 자바스크립트는 약한타입언어이기 때문에, var라는 키워드로 모든 변수의 타입을 결정한다.
이말은 즉 런타임때 자료형이 결정된다는 의미이다. (여기서 자료형과 타입은 같은 말이다.)
그렇다면 어떤 과정이 강한타입언어와 다른지 살펴보자.

위에서 두단계과정을 걸쳐 실행한다고 했는데 첫번째가 파싱단계이다.
파싱단계는 자바스크립트의 코드중에서 var, function 두 키워드에 집중한다.
(WebStorm과 같은 IDE들을 보면 var, function 키워드만 다른 키워드와는 다른색으로 하이라이팅이 되어있다.)

이단계에서는 var 키워드로 만들어진 변수에 undefined를 할당하고, function 키워드로 만들어진 함수를 위해
메모리에 해당 함수의 로직을 올리고 Person이라는 변수에 주소를 할당한다. (특별히 = 연산자 뒤에 function은 무시한다.)

[파싱단계] *주소는 예시이다.

1. person = undefeind (0x111)

2. 0x123 = “function{return 1000;}”

3. Person = 0x123

4. Person = undefined(할당안함) => 그대로 0x123

4번 부분을 보자. 원래대로라면 undefined가 된다고 생각하겠지만 function 키워드가 var 키워드보다 우선순위가 높다는 것을 기억해두자.

다음은 실행단계이다.
이 단계에서는 실제 var, function키워드를 가지고 했던 파싱단계에서 수행했던 위 4단계를 제외하고 남은 모든 코드를 실제 수행한다.
로그 1번에서는 Person()를 수행한다.

[실행단계]

console.log(1, Person());
console.log(2, person);

var person = 1001;

function Person() {
    return 1000;
}

var Person = function(age, height) {
    return age + “:” + height;
}

person = Person(10,100);

console.log(3, person);

1. console.log(1, Person());
이부분은 Person이라는 0x123에 접근한뒤 () 연산자를 통해서 함수를 실행시킨다.
그러면 “function{ return 1000; }” 이라는 코드가 위에서 말한 파싱과 실행단계를 다시한번 거치고,
1000을 반환한다. 따라서 console.log(1, 1000)과 같게된다.
(여기서 유추할수 있는건 파싱과 실행단계는 함수단위로 이루어진다. 그렇다면 실제 아무것도 없는 상태에서
코드를 작성했단 것은 아무것도 없는 것도 무언가의 함수스코프 영역내 라는 의미이다.)

2. console.log(2, person); 을보면 현재 person에는 undefined가 할당되어 있다. 따라서 console.log(2, undefined)와 같게 된다.

3. person = 1001; var 부분을 제외하고 person에 1001이 할당된다.

4. 함수코드를 메모리 어딘가에 올린다.
0x999 = “function(age, height) {
return age + “:” + height;
}”

5. Person = 0x999
var 부분을 제외하고 아래 코드가 수행된다. 즉 Person에 함수의 주소를 할당한다.

6. person = Person(10, 1000);
에서 먼저 Person(10, 1000)를 수행하면, 리턴되는 값인 문자열 “10:100″이 person에 할당된다.
즉 person = “10:100″; 과같다.

7. console.log(3, person)
이부분은 결국 console.log(3, “10:100″); 으로 된다.

Standard
■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (2)

앞서 간단한 자바스크립트 내용에 대해서 살펴보았다.

그럼 얼마나 공부가 되었나 스스로 문제를 풀어보길 바란다.

 

1. 리터럴

var a = 10;
var b = “abc”;
var c = 10.3;
“good literal”;

리터럴에대해서 설명하시오.

[객체리터럴]
아래 프로퍼티 표현을 객체 리터럴로 표현하시오.

[객체 프로퍼티 표현] *여기서는 객체 전체가 아닌 28, “172m” 두 값만 리터럴이 된다.
var obj = new Obj();
obj.age = 28;
obj.tall = “172m”;

[배열리터럴]
아래 배열표현을 리터럴표현으로 바꿔보시오.

[배열표현]
var arr = new Array();
arr.push(“nice”);
arr.push(1);
arr.push(3);

2. 변수는 생략한다.

3. 데이터 타입

데이터 타입은 크게 두가지 범주로 나뉜다.

첫번째는 프리미티브(원시) 타입, 그리고 그외로 나눌 수 있다.
나누게 되는 기준은 (                                                               )이다.

프리미티브타입은 다시 크게 5가지로 나뉜다.

프리미티브타입 5개를 쓰고 설명하시오.

그외(                                                                    ) 등이 있다.

4. var
var는 모든 변수를 만들기 위한 키워드이다.
데이터 타입이 정해져 있지 않기 때문에, 약한타입언어라고 한다.
이부분 때문에 일반 강한타입형언어와는 다른 특색들이 나타난다. 아래서 다시 알아보자.

5. 값 타입과 포인터(참조) 타입

두 타입에 대해서 설명하시오.

Standard
■ Javascript

[자바스크립트] Javascript를 기초부터 시작해보자! (1)

자바스크립트에 대해서 알아보도록 하겠다.

현재 Client scripting으로서, jQuery 및 backbone.js, angluar.js 등 다양한 프레임워크가 사용된다. 허나 이는 모두 자바스크립트란 사실!  기본부터, 아주기본이지만 중요한것 위주로 알아보도록 하겠다.

레퍼런스는 “객체지향자바스크립트 (황인균 저 | 위키북스)”를 토대로하나 추가되거나 빠진 내용이 있다.

1. 리터럴

var a = 10;
var b = “abc”;
var c = 10.3;
“good literal”;

여기에서 10, “abc”, 10.3, “good literal” 이것이 모두 상수 이고, 이러한 상수를 리터럴 이라고 한다.
literal뜻은 “문자그대로” 란 의미인데, 보통 우리가 작성하는 코드는 변수 및 키워드로 대부분 이루어져 있다. 그중에 상수값, 즉 변수가 아닌 값이 되는 상수는 코드상에 적혀있는 있는 그대로의 값이 되며 따라서 리터럴 이라고 부른다.

이중에서 특별히 객체, 배열의 리터럴도 존재한다. 따라서 일반적으로 쓰이는 상수가 아닌 리터럴 이라고 하는 것이다.

[객체리터럴]
{age:28, tall:”172m”};

[객체 프로퍼티 표현] *여기서는 객체 전체가 아닌 28, “172m” 두 값만 리터럴이 된다.
var obj = new Obj();
obj.age = 28;
obj.tall = “172m”;

[배열리터럴]
[“nice”,1,3];

[배열 인덱표현]
var arr = new Array();
arr.push(“nice”);
arr.push(1);
arr.push(3);

2. 변수는 생략한다.

3. 데이터 타입

데이터 타입은 크게 두가지 범주로 나뉜다.

첫번째는 프리미티브(원시) 타입, 그리고 그외로 나눌 수 있다.
나누게 되는 기준은 포인터값인가, 실제 값인가의 차이이다.

프리미티브타입은 다시 크게 5가지로 나뉜다.

– 숫자 (Number) : 모든 숫자는 부동소숫점이다. 정수는 없다.
– 문자열 (String) : 문자는 없다 모두 문자열이다.
– 불린 (Boolean)
– null : 명시적으로 데이터가 없음을 나타낸다.
– undefined : 초기화가 되지 않았을때 자동으로 들어가 있는 값이다.

그외 Object, Array, Function, Date, RegExp 등이 있다.

4. var
var는 모든 변수를 만들기 위한 키워드이다.
데이터 타입이 정해져 있지 않기 때문에, 약한타입언어라고 한다.
이부분 때문에 일반 강한타입형언어와는 다른 특색들이 나타난다. 아래서 다시 알아보자.

5. 값 타입과 포인터(참조) 타입
간단한 예로, 함수를 예를 들어보자.
자바스크립트에서 함수는, 코드를 가르킨다. 이말은 즉, 우리가 작성한 자바스크립트 코드가,
메모리 어딘가에 올라가 있다는 의미이다. 근데 다른 언어와는 다르게 코드 자체가 그대로 올라간다.
그럼 어떤 변수를 이용해서 함수를 호출할때 함수안에는 코드가 있을까?
정답은 아니다. 함수안에 코드가 직접적으로 문자열 형태로 들어가 있다면 여러 문제가 발생한다.
예를 들면 A함수에 B함수를 넣어서 두개가 동일한 함수로 만든다고 가정해보자.
그럼 A함수와 B함수 모두 해당 함수의 문자열을 들고 있는다. 따라서 중복의 문제가 발생한다.
따라서 A와B는 모두 함수의 대한 주소값 (여기서는 메모리 주소)을 가르킨다.
특히 () 키워드는 해당 코드를 실행 시키라는 의미이다.

Standard
■ Web

[Web] RestFul Service에 대해서 알아보자 (4)

오늘은 NHN에서 쓴 “자바스크립트 성능이야기”란 책에서 좋은내용이 있어 발췌하여 설명하도록 한다.

먼저 중요한 것부터 짚고 넘어가자.

 

브라우저가 요청을 처리하는 순서를 이번엔 도메인 주소 입장이 아닌 브라우저 자체 프로세스를 통해 좀더 세부적으로 살펴보도록하겠다.

브라우저는 젤 처음 서비스 이동단계로 시작한다.

이부분은 우리가 브라우져를 처음 키고 접속해오는 상황을 말한 것은 아니다.

현재 어떤 페이지를 보고 있다고 가정하고, 다른 도메인을 통해 페이지를 이동한다고 했을때, 앞에서 말한 우리가 보고 있던 어떤페이지란 것을 다른 페이지로 이동하기 전에 처리하는 과정을 말한다.

beforeunload라는 이벤트 핸들러를 통해 메모리 해제와 같은 처리를 해줄 수 있다.

 

다음으로 리다이렉트 단계이다.

예를들면

http://bravo114.kr로 접속하면

http://bravo114.kr/ 이부분으로 리다이렉트 되고, 이것은 다시http://bravo114.kr/main으로 리다이렉트 되도록 구성되어있다. 여기서 http://bravo114.kr/ 이부분은 index가 생략되어있는 것이 보통이나, 요즈음의 웹서버들은 routing 개념을 사용하기 때문에 꼭 index가 생략되어있다고 볼순 없다.(물론 내부적으론 index로 처리할 수도있다.)

여기서 중요한 점은 리다이렉트의 경우 정적파일 캐시가 되지 않기 때문에 리다이렉트 되기전 페이지는 최대한 가볍게 하거나 사용을 자제하는 편이 좋다.

 

다음으로는 애플리케이션 캐시확인 단계이다.

앞서 REST를 공부할때도 보았지만 캐시 정보를 활용해서 서버부화를 줄이는 방법이 있었다.

이때 Last-Modified(서버), if-Modified-Since(브라우져) 등을 활용하거나, Expires, Cache-Control등을 활용할 수있다.

순서는 Expires로 만기날짜를 먼저 확인하고 만기가 되었다면 if-Modified-Since를 통해 현재 받아온 데이터가 클라이언트가 알고 있는 갱신날짜보다 최신인지 확인하고, (Last-Modified를 통해비교) 최신이 아니라면 서버로부터 다시 받아온다.

 

다음으로는 네트워크 통신단계이다.

이부분은 다시 세부적으로 8단계 정도로 나뉜다.

1. Blocked : 브라우져가 서버와의 통신을위해 준비하는 시간이다. (이때 host별로 병렬로 요청하는데 현재 2개의 동시요청의 개수가 가장 최적이다라는 보고가 있다.)

2. DNSLookup : 앞서 도메인을 설명할때 DNS Server에 대해 설명했다. 이때NS레코드가 DNS서버에 이미 저장되어 있다면 해당 TTL(캐시 시간)에 따라 DNS서버는 최종 보여줘야할 ip주소를 캐시한다. 바로 이부분을 체크하는 시간이다.

3. TCP(Connect) 실제 http통신을 위해 TCP연결을 하는 시간이다. (http는 TCP통신으로 구현한 프로토콜이다.)

4. Request 실제 요청하는 시간이다. 이때 CDN같은 정적파일 전용서버를 만들어 놓아서 최적화를 할수 있다. 무슨말이냐면, 매번 요청할때 실제 서버는 Cookie를 갖고 있는데, 이부분이 꽤 헤더에서 차지하는 부분이 크다보니 트래픽을 유발시킬수 있다. 따라서 CDN은 보통 Cookie를 해더에 들고있지 않는다.

5. Wait 서버로부터의 응답을 기다리는 시간이다. 서버의 속도가 가장 중요한 부분이다. 실제 Node.js나 아파치+php조합에서의 속도차이는 이부분에서 발생한다.

6. Response 응답메세지를 받는 시간이다. 이때 서버와 클라이언트간 통신은 데이터를 일정부분으로 잘라 분할해서 전송한다. 분할전송을 통해 모든 데이터를 받게 되는 시간이 Response에 걸리는 시간이다. 따라서 Gzip등으로 압축해서 용량을 줄인다. (혹은 코드를 minify한다.)

7. TTFB 서버가 Response시에 받을 데이터중 가장 처음 데이터 바이트 정보를 받아 브라우져에 보내는데 걸리는 시간이다. 안드로이드와 같은 모바일 디바이스로 통신할때 파일을 나누어서 보낸다. 그때 처음으로 write하고 처음으로 보낸 바이트를 클라이언트가 받아 처리하는 시간이다.

8. Cache Read 사용자 PC로부터 캐시된 데이터를 읽어오는 시간이다. 위에 설명한 캐시 확인단계에서 캐시가 되어있다고 설정되어있으면 캐시된 데이터를 불러오고 그렇지 않으면 윗단계에서 통신을 수행하여 데이터를 받아온다.

이상 8가지 단계가 네트워크를 처리하는 단계이다.

 

다음으로는 실제 브라우져가 데이터를 처리하는 단계이다.

이부분은 브라우져가 받아온 데이터의 MIME타입을 확인하여 해당 타입에 맞게 파싱후 렌더링하는 과정이다.

대표적으로 HTML,JS,CSS등이 파싱의 대상이다.

 

이상으로 대략적인 브라우져의 수행 단계를 살펴보았는데 대략적으로 정리하면

서비스이동단계 – 리다이렉트단계 – 캐시확인단계 – 네트워크통신단계 – 브라우저 데이터 처리단계 로 나눠진다.

이중 네트워크 통신단계는 8가지로 이루어져있다.

Standard