(Javascript) 1. Data type? -3- : Variable

김동우·2021년 6월 8일
0

wecode

목록 보기
5/32

잠깐! 시작하기 전에

이 글은 wecode 사전 스터디에서 실제 공부하고, 이해한 내용들을 적는 글입니다. 글의 표현과는 달리 어쩌면 실무와는 전혀 상관이 없는 글일 수 있습니다.

또한 해당 글은 다양한 자료들과 작성자 지식이 합성된 글입니다. 따라서 원문의 포스팅들이 틀린 정보이거나, 해당 개념에 대한 작성자의 이해가 부족할 수 있습니다.

설명하듯 적는게 습관이라 권위자 발톱만큼의 향기가 조금은 날 수 있으나, 엄연히 학생입니다. 따라서 하나의 참고자료로 활용하시길 바랍니다.

글의 내용과 다른 정보나 견해의 차이가 있을 수 있습니다.
이럴 때, 해당 부분을 언급하셔서 제가 더 공부할 수 있는 기회를 제공해주시면 감사할 것 같습니다.

Variable

이제 객체를 배울 시간이 점점 다가오고 있네요. 객체를 배우기 전에 우린 Js에서 변수를 어떻게 처리하고, 정의하는지 미리 알아두어야 합니다.

그 이전에 왜 변수는 객체가 아니냐, 라고 생각하실 수 있겠지만 포괄적인 OOP에 대한 생각이라면 변수 또한 객체에 해당한다고 생각합니다.

다만, Js에서 변수를 Object의 하위 개념으로 포함하고 있지 않기에 따로 적게 되었습니다.

이는 자료형 이전에 설명해도 괜찮은 부분이지만, 자료형을 모르는 상태에서 변수를 선언하는 것은 변수에 부가적인 설명을 요구하기에 MDN에서도 이 순서 쯤에 위치해 있습니다.

Js를 이전에 활용했다면 대부분의 선언에서 const, let, var 3가지로 변수의 특징을 지정해주었죠.

이는 저마다 들어가야 할 상황이 조금씩 다르고, 그 결과, 우린 let과 const를 var에 비해 더욱 많이 활용하게 되었습니다.

그 과정에 대해 생각해봅시다.

1. var + 호이스팅

사용할 용어

  • declaration - 선언
  • assignment - 할당
  • initialization - 초기화

호이스팅 예시

Js에서만 나오는 호이스팅의 개념은 var를 통해 이해할 수 있습니다.

이건 엄연히 Js 개념으로, 프론트엔드 지망생, node.js 백엔드 지망생 여러분들은 한 번 쯤은 생각해도 나쁘지 않은 주제일 것 같습니다.

물론 var를 왜 지양해야 하는가? 에 대한 검색만으로도 양질의 답변을 얻을 수 있습니다만, 저는 제가 직접 작성하며 이해하고자 합니다.

먼저, Js의 경우 var를 통한 변수선언 혹은 함수의 선언 당시 어디에 존재하든 미리 알고 있기 때문에 오류가 발생하지 않는다. 라는 것으로 이해하시면 됩니다.

이건 모든 설명을 관통하는 말입니다.

	console.log(num); // undefined
	var num = 100;

이게 호이스팅의 예시입니다. 원래라면 해당 코드를 입력했을 때, 빌드 자체가 불가능한 케이스가 맞습니다. 하지만 javascript 내에서 initialization 위치는 빌드에 있어 아무런 문제가 되지 않습니다.

다만 결과적으로 원하는 값을 관찰할 수는 없겠습니다. 동작 플로우는 엄연히 수직구조로 이뤄집니다.

해당 코드를 다시 호이스팅에 맞춰 작성하면

	var num; // declaration
	console.log(num); // undefined
	num = 100; // assignment

위 코드와 동일하게 동작합니다. 이는 함수도 마찬가지이며, 이것이 가능한 이유는 사용될 함수의 선언을 브라우저의 Parser가 실제 사용 시점보다 먼저 알고 있기 때문입니다.

단, 이러한 개념을 증명하는 데에는 scope(범위)가 중요하게 작용합니다. 내부에서 선언된 변수를 외부에서 클로저가 아닌 이상 호출할 수는 없기 때문입니다. 따라서, scope를 항상 유의하며 코드를 작성해봅시다.

호이스팅이 가능한 이유

호이스팅은 Js가 함수나 변수의 "선언"을 메모리에 저장하기에 가능합니다.

또한, 함수의 경우 표현식과 선언식에 관계 없이 호이스팅이 발생하게 됩니다.

이를 설명하기 위해 많은 사람들은 "선언 자체를 위로 끌어올린다."는 표현을 사용합니다.

실제로는 메모리에 먼저 저장하기 때문에 선언의 위치는 크게 관계가 없다. 정도로 생각할 수 있습니다.

요약

즉 정리하자면,

var 선언의 오류는 해당 local 혹은 global, 어느 위치던 간에 범위 내 "실행 순서"와는 전혀 관계가 없다.

그러나 해당 변수를 사용하는 메서드나 함수의 호출에서 반환값은 순서를 무시하지 않는다. -> assignment의 위치는 신경을 써야한다. 그렇지 않으면 undefined를 관찰할 수 있다.

호이스팅이 가능한 것은 Js의 함수와 변수의 선언이 메모리에 먼저 저장되기 때문이다.

선언이 위로 끌어당겨지는 시점은 브라우저가 Js를 해독하는 시점이며, 가능케 하는 것은 Parser의 역할이다.

자, 이와 같이 var는 호이스팅의 개념을 증명하는 변수선언 방식입니다.

const와 let은 그렇지 않죠. 왜일까요?

2. TDZ(Temporal Dead Zone)

Hoisting에 대해 우린 이제 겉핥기했습니다. 그렇다면 왜 변수 선언에서는 const, let을 사용하는지 알아야겠죠.

우리가 실제 const, let을 사용하는 이유는 사실 지극히 실용적으로 말할 수 있습니다.

"유지보수에 쉽고, 디버깅에 유용하니까."

이보다 더 효율적인 이유가 있을까요?

그 배경에 있는 것이 바로 TDZ입니다.

사용하려는 변수나 함수를 초기화 이전에 사용하는 블럭 혹은 지역을 TDZ 라고 말합니다. 그리고 const, let의 경우는 TDZ의 존재를 용인하지 않는 변수타입이죠.

즉, const와 let은 초기화가 필수적인 선언들입니다.

initialization = declaration + assignment

그렇기에 해당 타입의 변수들은 declaration의 호이스팅이 이루어지지만 assignment가 없기 때문에 Reference Error를 출력하게 됩니다.

그렇다면 이게 왜 유지보수에 쉬울까요?

배경에는 바로 ReferenceError가 있습니다. 참조오류 정도의 말로 직역하셔도 상관이 없겠습니다.

초기화 이전에 참조하는 것을 방지해주는 ReferenceError 덕분에 우리는 어디서 어떤 방식으로 코드가 잘못되었는지 console창을 통해 확인할 수 있습니다.

Javascript의 undefined도 예상치 못한 값일 경우 설계자에게는 오류지만, ReferenceError에 해당하는 is not defined의 경우는 실행이 불가능한 오류입니다. 이는 구문오류와는 달리 실행환경의 오류로, Runtime error에 해당합니다.

이를 통해서 우리가 var를 프로젝트에서 주로 사용하지 않게 되는 이유를 어느정도 알 수 있지 않을까 싶습니다.

3. 전역변수

우린 OOP 언어를 활용합니다. 이러한 언어에서 무분별한 전역변수의 사용은 결코 바람직한 방향이 아닙니다.

참조 얘기가 나왔으니 전역변수 얘기도 잠깐 해보도록 합시다.

어느 곳에서든 선언된 {변수 혹은 메서드}(=객체)가 이후 다른 블럭에서 참조될 경우 객체 원본에 의도치 않은 영향을 끼칠 수 있는 상황이 옵니다.

동명의 변수를 지정할 경우, 해당 변수들을 사용하는 곳 전체에 영향을 끼치는 것은 물론, 어디서 왜 꼬였는지 모를 아주 애매한 상황이 발생하게 됩니다.

자바스크립트는 객체참조에 관한 글을 첨부합니다.
Js 참조복사

const, let

그럼에도 우린 전역변수를 부득이하게 선언해야 하는 상황이 있습니다.

그래서 상수, const의 형태로 지정을 하게 되는 것이죠.

다른 파일에서 같은 변수를 선언하더라도 export 하지 않는다면 값을 사용할 수 없고, 애초에 수정이 불가능한 const 라는 선언을 통해서요.

이러한 형태의 선언은 하나의 파일에 따로 변수들을 모아놓고 전역에서 사용할 경우 상당히 유용할 수 있습니다. (cpp에서 다양한 상수값들을 분리해 파일로 저장해둔 기억이 나네요.)

반대로 let의 경우 범위 내에서 언제든 수정은 가능하지만, 그렇기에 전역변수로의 사용은 조금 애매하다는 생각이 드는 것 같습니다.

저는 전역변수로 let을 선언하는 행위를 지양하고 있습니다. 물론 전역변수를 거의 사용하지 않기도 하지만, const가 아닌 타입의 변수를 전역으로 사용하는 코딩을 해본 경험은 없습니다.

그러나, 초기화만 잘 이루어진다면 const에 비해 상당히 자유로운 타입의 변수입니다.

실제 Object를 구성할 때는 대부분 let으로 선언을 하게 됩니다.

요약

그렇다면 우리가 const, let을 활용하는 이유는 다음과 같이 정리할 수 있겠네요.

const는 전역변수 혹은 지역변수의 선언 시 값의 변경을 원하지 않는 것으로 해석하시면 됩니다. (주로 DOM.)

let은 value의 변경의 가능성이 있는 지역변수를 선언한다는 의미입니다. (이건 그냥 일종의 약속이에요. 전역으로 사용해도 무관합니다만, 전역변수는 최대한 피하는게 낫지 않을까 생각합니다.)

또한, 이러한 배경에는 TDZ가 있고, 우린 var와 const, let의 차이를 호이스팅, TDZ, ReferenceError를 통해 알아볼 수 있습니다.

추후 나올 객체 복사에 대한 개념과 함께 설명할 수 있도록 저도 더욱 공부해야겠습니다.

그럼 이번 글은 여기서 마치겠습니다. 감사합니다.

0개의 댓글