자바스크립트 기초 #2 변수와 타입
#1 시작과 셋업 에서 환경을 만들었으니 이제 언어 자체를 들어갑니다. 이번 글은 — 변수를 어떻게 선언하고, 자바스크립트가 어떤 타입들을 가지며, 그 사이를 오갈 때 무엇을 조심해야 하는지.
변수 선언 — let과 const
#
자바스크립트에서 변수를 만들 때 쓰는 키워드는 **let**과 const 두 가지입니다.
let count = 0; // 나중에 바꿀 수 있는 값
count = count + 1; // OK
const name = '커티스'; // 한 번 정해지면 못 바꿈
name = '다른 이름'; // ✗ TypeError
규칙은 단순합니다 — 기본은 const, 재할당이 필요할 때만 let. 처음에는 헷갈릴 수 있지만, 익숙해지면 코드의 의도가 더 분명해져요. “이 값은 안 바뀐다"가 한눈에 보이는 것입니다.
var는 어디로 갔나요?
#
옛날 자바스크립트에는 var 라는 키워드가 있었습니다. 지금도 동작하지만 새 코드에는 거의 쓰지 않습니다. var 에는 다음과 같은 함정이 있습니다.
- 함수 단위 스코프 — 블록(
if,for)을 무시함 - 호이스팅 시
undefined로 초기화 — 선언 전에 접근해도 에러가 안 남 - 같은 이름으로 중복 선언 가능 — 사고 위험
let/const는 이 모든 함정을 깔끔하게 정리한 후속입니다. 이 시리즈에서는 var를 거의 쓰지 않습니다.
8가지 기본 타입 #
자바스크립트의 모든 값은 다음 8가지 타입 중 하나입니다.
| 타입 | 예시 | 분류 |
|---|---|---|
string | 'hello', "world", `tpl` | 원시 |
number | 42, 3.14, -1 | 원시 |
boolean | true, false | 원시 |
null | null (의도적 비어 있음) | 원시 |
undefined | undefined (값이 아직 없음) | 원시 |
bigint | 9007199254740993n | 원시 |
symbol | Symbol('id') | 원시 |
object | {}, [], 함수, 클래스 인스턴스 | 참조 |
앞 7개는 원시 타입(primitive), 마지막 object만 참조 타입(reference). 이 분류가 자바스크립트의 모든 동작을 설명하는 출발점입니다.
타입 확인 — typeof
#
typeof 'hello'; // 'string'
typeof 42; // 'number'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof null; // 'object' ← 자바스크립트의 유명한 버그
typeof {}; // 'object'
typeof []; // 'object' ← 배열도 객체
typeof function(){}; // 'function' ← 사실 object지만 특별 취급
typeof null === 'object'는 언어 초기의 버그가 그대로 굳어진 것입니다. 호환성 때문에 못 고치고 있습니다. null을 검사할 때는 value === null로 직접 비교하는 게 안전합니다.
null과 undefined의 차이
#
둘 다 “값이 없음"을 표현하지만 의도가 살짝 다릅니다.
undefined— 값이 아직 정해지지 않음. 자바스크립트가 자동으로 채워줌.null— 값이 의도적으로 비어 있음. 개발자가 명시적으로 적음.
let x; // 선언만 하고 값 없음 → undefined
console.log(x); // undefined
const obj = { name: '커티스' };
console.log(obj.age); // undefined (없는 속성)
function f(arg) {
return arg;
}
f(); // undefined (인자 없음)
let user = null; // 아직 로그인 안 함
// ... 나중에
user = { id: 'u1', name: '커티스' };실무에서는 함수 반환값이나 API 응답에서 두 가지 모두 마주칩니다. “있을 수도 있고 없을 수도 있는 값” 이라는 의미는 둘이 같다고 봐도 무방합니다. ==로 비교하면 둘 다 잡힙니다(다음 절).
원시 vs 참조 — 자바스크립트의 가장 중요한 차이 #
여기가 입문자가 가장 자주 막히는 부분입니다.
원시 타입은 값이 통째로 복사됩니다.
let a = 10;
let b = a; // a의 값(10)을 b에 복사
b = 20;
console.log(a); // 10 (영향 없음)
console.log(b); // 20
참조 타입은 “어디를 가리키는지"가 복사됩니다.
const obj1 = { count: 10 };
const obj2 = obj1; // 같은 객체를 가리키게 됨
obj2.count = 20;
console.log(obj1.count); // 20 ← obj1도 같이 바뀜
console.log(obj2.count); // 20
obj1과 obj2는 같은 객체를 가리키는 두 이름입니다. 한쪽으로 객체를 바꾸면 다른 쪽으로 봐도 바뀐 게 보입니다. 이 차이가 자바스크립트로 일하면서 만나는 수많은 “왜 이게 같이 바뀌지?” 문제의 근원입니다.
객체를 진짜 복사하고 싶을 때 #
const original = { name: '커티스', age: 30 };
const copy = { ...original };
copy.age = 31;
console.log(original.age); // 30 (영향 없음)
console.log(copy.age); // 31
{...original}는 객체의 1단계 속성들만 복사하는 얕은 복사(shallow copy). 중첩 객체가 있으면 그건 여전히 참조가 공유됩니다. 깊은 복사는 다음 시리즈에서 다룹니다.
형 변환 — 함정 #
자바스크립트는 타입을 자동으로 바꾸려는 경향이 있어서, 의도와 다른 결과가 나오기 쉬워요.
의도적 변환 #
Number('42'); // 42
Number('hello'); // NaN (Not a Number)
String(42); // '42'
Boolean(0); // false
Boolean(1); // true
Boolean(''); // false
Boolean('false'); // true ← 'false' 문자열은 비어있지 않음
Boolean 변환에 들어가는 falsy 값 7가지를 외워두면 좋습니다.
Boolean(false); // false
Boolean(0); // false
Boolean(-0); // false
Boolean(0n); // false (bigint 0)
Boolean(''); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
이 7가지 외에는 모두 truthy. 빈 객체 {}와 빈 배열 []도 truthy 라는 게 헷갈리기 쉬워요.
Boolean({}); // true
Boolean([]); // true
Boolean('0'); // true ← 문자열 '0'은 비어있지 않음
Boolean('false'); // true
자동 변환의 함정 #
연산자가 자동으로 타입을 바꾸는 경우들이 있습니다.
'5' + 3; // '53' ← 문자열 연결로 동작
'5' - 3; // 2 ← 숫자 연산
'5' * '2'; // 10 ← 둘 다 숫자로 변환
[] + []; // ''
[] + {}; // '[object Object]'
+가 가장 헷갈려요. 한쪽이 문자열이면 연결, 그 외에는 합산입니다. 헷갈리면 Number() 나 String()으로 명시적 변환을 거치는 게 안전합니다.
==와 === — 항상 ===를 쓰세요
#
비교 연산자가 두 가지 있습니다.
// 느슨한 비교 — 자동 변환 후 비교
'5' == 5; // true ← 문자열을 숫자로 변환해서 비교
0 == false; // true
null == undefined; // true
// 엄격한 비교 — 타입까지 같아야 함
'5' === 5; // false
0 === false; // false
null === undefined;// false
거의 항상 ===를 쓰세요. 자동 변환은 직관과 어긋나는 경우가 많아 사고를 만듭니다. null과 undefined를 한 번에 검사하고 싶을 때만 value == null 패턴을 쓰는 정도입니다(이건 null || undefined와 동치).
let과 const의 스코프
#
마지막으로, let/const가 만드는 블록 스코프 의미.
if (true) {
const message = '안녕';
console.log(message); // 안녕
}
console.log(message); // ✗ ReferenceError — 블록 밖에선 안 보임
{와 } 안에서 선언된 변수는 그 블록 밖에서 보이지 않습니다. for 루프, if 분기, 함수 본문 모두 같습니다. 이 덕분에 변수의 영향 범위가 좁아지고 추적이 쉬워집니다.
마무리 #
이번 글에서 정리한 내용:
- 변수 선언은 기본
const, 재할당이 필요할 때만let.var는 새 코드에 안 씀 - 8가지 타입 — string/number/boolean/null/undefined/bigint/symbol/object
typeof null === 'object'함정 —value === null로 직접 비교- 원시는 값 복사, 객체는 참조 복사.
{...obj}로 얕은 복사 - falsy 7가지: false, 0, -0, 0n, ‘’, null, undefined, NaN
==대신 항상===사용let/const는 블록 스코프
다음 글(#3 제어 흐름)에서는 if/while/for/switch 같은 분기와 반복, 그리고 모던 문법(for...of, for...in, switch의 fallthrough 함정)을 다룹니다.