본문 바로가기

변수와 상수 | Javascript & ES6 공부 노트 #4

기술적인 이야기/웹 개발 2019. 4. 11.
반응형

언어를 공부할 때 가장 먼저 익혀야 할 개념은 변수(variable)라고 생각합니다. 데이터를 담을 수 있는 메모리 공간을 할당하고, 여기에 데이터를 넣고, 데이터를 바꾸어서 넣을 수 있다는 점은 논리적인 사고에서 가장 필수적으로 알아야 할 내용이니깐요. 그런 의미로 정말 기초적이지만 중요한 이 변수, 그리고 변수가 나오면 같이 등장하는 상수, 그리고 변수와 상수를 다루는데 필요한 연산자에 대해 간략히 알아보겠습니다.

동적 타이핑(Dynamic Typing)

우선 동적타이핑 개념을 알아야 할 것 같습니다. 자바스크립트는 동적 타이핑 변수 시스템(?)을 가지고 있는 언어입니다. 동적 타이핑은 타입이 유동적이다라는 의미이며, 쉽게 말해서 변수에 아무 타입의 데이터를 넣거나 비교해도 된다는 의미입니다. 예를 들어 자바스크립트에서는 아래와 같은 코드가 허용됩니다.

var a = 10
a = "string"
a = function() { ... }

위의 예는 a라는 변수의 값의 타입이 정수형이든 문자열이든 함수 오브젝트이든 관계없이 넣을 수 있다는 점을 보여주고 있습니다. 참고로 넣을 수 있는 데이터의 타입에 대한 글은 이어서 게시할 예정입니다.

동적 타이핑의 반대되는 개념으로 정적 타이핑(Static Typing)이 있는데 변수를 선언할 때 해당 변수의 타입이 명시되어야 하고 한번 선언된 변수는 타입이 고정되기 때문에 다른 타입을 값을 대입하는 경우 에러가 발생하는 형태입니다. 예를 들어 위의 예가 정적 타이핑 언어였다면 아마도 2번째 라인처럼 '정수형으로 선언된 a 변수에 문자열을 대입하려는 것'은 문법 에러가 됩니다.

정적이든 동적이든 둘 다 장단점이 있기 마련이지요. 개인적으로는 미리 에러를 방지할 수 있는 정적타이핑을 좋아하지만 파이썬이나 자바스크립트처럼 동적 타이핑을 지원하는 언어도 나름의 장점이 있습니다. 이 정도만 이야기하고 넘어갑시다.

변수(variable)

'변수'라는 이름에서 '변할 수 있는'이라는 느낌을 얻었다면 의미 이해에는 성공한 것 같습니다. 실제로 변수는 특정 데이터를 담을 수 있는 그릇으로 비유할 수 있습니다. 이 그릇에는 데이터를 넣거나 바꿀 수 있고 마음껏 볼 수 있습니다.

자바스크립트와 ES6에서는 공통적으로 var라는 키워드를 통해 변수를 정의합니다.

var someVariable = 0

위 코드는 someVariable이라는 이름의 그릇을 만들어 0이라는 데이터를 넣어두는 코드입니다. 이런 코드를 '변수를 선언한다(declare or definite variable)'라고 표현합니다. 그리고 변수를 선언하면서 첫 값을 넣을 수 있는데 이 값을 초기값(initial value)이라 합니다. 즉 위의 예는 초기값을 0으로 someVariable이라는 변수를 선언하고 있다는 것이지요.

상수(constant)

클래식(?) 자바스크립트는 상수 기능이 없었지만 ES6부터는 상수 선언을 지원하는 const 키워드가 생겼습니다. 여기서 상수는 '한번 선언되면 변하지 않는 값을 넣어두는 공간'입니다. 언어에 따라 적절한 설명은 달라질 수도 있겠지만 대충 이렇게 '변하지 않는 값'이라는 점을 이해하기만 하면 됩니다.

const fieldName = "good_field"

위 코드의 경우 fieldName이라는 그릇에 "good_field"라는 문자열 데이터를 담고 거기에 투명한 뚜껑을 덮었다고 볼 수 있습니다. 뚜껑이 투명해서 안에 무엇이 들어있는지는 잘 보입니다. 하지만 뚜껑을 열지 않는 한 데이터를 바꿀 수 없는데 이 뚜껑은 특수해서 열 수가 없습니다.

당연하겠지만 상수는 다른 값을 넣는 것이 불가능한데다 재선언(redefinition)도 불가능합니다.

let, 지역변수?

ES6부터 추가된 새로운 변수를 정의하는 키워드로 let이 있습니다. 의미는 일반적인 변수와 동일하지만, 네임스페이스 스코프가 var와는 다르다는 특징이 있습니다.

let으로 선언된 변수는 스코프(블록)를 벗어나면 더이상 액세스 할 수 없습니다.

if (true) {
  var a = 0
  let b = 0
}
console.log(a)
console.log(b)  // error

갑자기 if 문이 등장했는데 설명을 위한 예제일 뿐입니다. 일단 중괄호로 둘러쌓인 부분 { ... } 안의 내용과 밖의 내용은 차원(?)이 다르다고 생각합시다.

위 코드에서 변수 a와 b를 특정 if문 안에서 선언하고 있습니다. 이 블록 내부에서 a와 b의 액세스는 아무 문제없이 가능합니다. 하지만 if블록을 빠져나가는 순간 let으로 선언된 b는 더 이상 액세스를 할 수가 없게 되고 에러가 발생합니다.

var의 경우 호이스팅, 즉 선언 시점에 관계없이 액세스가 가능하다는 점과는 다르게 let은 실행 순서를 명확하게 하기 때문에 선언하기 전에 액세스 하는 것은 에러로 간주된다는 특징도 있습니다.

let의 최대 스코프는 선언된 파일입니다. 따라서 전역변수가 될 수가 없는 특징이 있다고 볼 수 있습니다.

사족. var의 자유로움(?)은 다른 언어부터 프로그래밍을 시작한 사람에게 욕설을 내뱉게 하는 수준(?)인데, 그나마 let의 경우는 다른 언어들과 비슷한 성향을 보여서 다행이라고 생각됩니다. 따라서 다른 언어에 익숙하다면 var 보다는 let위주로 사용하는 것이 좀 더 익숙하겠지요. 어차피 let이 더 안전한 점도 있고 추천할만한 변수 형식이기도 합니다.

기타 변수

var나 let이 변수를 선언하는 키워드이긴 하지만, 이걸 빼버려도 변수가 선언됩니다. 뭐 이딴 미친 언어가 다 있지 라는 생각이 들었지만 뭐 가능하다니 어쩔 수 없겠지요. 그러니까 대충 아래와 같은 식입니다.

b = 20

이렇게 하면 20을 초기값으로 가지는 b 라는 변수가 생성됩니다.

이렇게 var나 let 같은 특정한 키워드 없이 선언된 변수는 전역(global) 변수로 취급된다고 합니다. 워낙 복잡한(?) 자바스크립트 세상이라 가급적 이런 문법은 안 쓰는 것이 좋겠다고 생각됩니다.

이상한 특징들

앞서 let을 소개할 때 잠깐 언급했지만, var로 선언된 변수는 호이스팅(hoisting)이 되어서 선언 위치와 액세스 위치가 달라고 유연하게 동적으로 처리해주는 친절하면서도 개떡(?) 같은 특징이 있습니다. 물론 개떡 같다는 표현은 다른 몇 가지 언어들을 먼저 공부해 온 제 느낌일 뿐 이것이 객관적인 의견이 아님에 주의합시다.

자바스크립트의 또다른 이상한 점은 재선언(redefinition)이 가능하다는 특징도 있다. 예를 들어 아래와 같은 코드는 에러가 아닙니다.

var a = 10
var a = 20
var a = "string"

이러한 특징은 실행 순서를 엄격하게 따지고 재선언도 금지하는 다른 언어들에서 프로그래밍을 시작한 사람에게는 말도 안 되는 정말 최악의 특징이기도 합니다. 물론 이 글은 자바스크립트를 보는 것인 만큼 이제는 이상하게 보면 안 되겠지만요.

그나마 이런 점은 ES6에 들어서 추가된 특징에 의해 좀 완화되긴 했다는 점이 다행이긴 합니다. 예를 들어 let과 const는 호이스팅이 지원되지 않습니다. 따라서 스코프를 벗어나면 인식이 되지 않습니다. 전역으로 재선언하는 것도 막히기 때문에 어느 정도 안전한 코딩이 가능합니다.

let a = 10
let a = 20  // error

당연하다면 당연한 건데 자바스크립트에서는 뭔가 생각할 거리가 많다는 점은 흥미를 주기도 하는 것 같습니다. 그전에 열 받게 만드는 것도 있긴 하지만 말이지요.

마무리

사실 이 글을 쓰는 데 있어서 예제도 부실한 데다 뭔가 글을 적어야 하는 순서가 반대가 된 것이 아닌가 좀 오래 고민했습니다. 변수 상수 이야기에 타입도 섞여 나오고 제어문도 섞여 나오고 말이죠. 하지만 그걸 고민하는 것보다는 그냥 순서도 이상하고 내용이 부실하더라도 묵혀두기만 하는 것이 더 나쁘다는 결론에 이르렀습니다. 그래서 이런 결과물이 나왔지요.

이 글이 이제 시작하는 분들의 도움이 될 수 있다면 참 좋을 것 같습니다.

728x90
반응형

댓글