Skip to Content
BlogJavaScript 정리기초 정리변수와 자료형 메모리 구조부터 Spread/Rest까지

변수와 자료형 메모리 구조부터 Spread/Rest까지

변수 선언 방식: var vs let vs const

JS에서 변수를 선언하는 방법은 세 가지가 있다. 지금은 let과 const를 기본으로 쓰고, var는 레거시 코드에서나 만나는 정도지만 차이를 알아둘 필요가 있다.

var

var name = "철수"; var name = "영희"; // 재선언 가능 name = "민수"; // 재할당 가능
  • 함수 스코프를 가진다. if, for 같은 블록 안에서 선언해도 블록을 빠져나가면 사라지지 않는다.
  • 재선언, 재할당이 모두 가능하다.
  • 호이스팅될 때 undefined로 초기화된다.

let

let age = 20; age = 21; // 재할당 가능 // let age = 22; // 재선언 불가 (에러)
  • 블록 스코프를 가진다. {} 블록을 벗어나면 접근할 수 없다.
  • 재할당은 가능하지만 재선언은 불가능하다.

const

const PI = 3.14; // PI = 3.15; // 에러: 재할당 불가
  • 블록 스코프를 가진다.
  • 재할당, 재선언 모두 불가능하다.
  • 단, 객체나 배열처럼 참조 타입을 담고 있다면 내부 값은 바꿀 수 있다.
const user = { name: "철수" }; user.name = "영희"; // 가능 (객체 자체를 재할당하는 게 아니라 내부 속성만 변경)

정리: 기본은 const를 쓰고, 값이 바뀔 예정이라면 let을 쓴다. var는 특별한 이유가 없다면 사용하지 않는 게 일반적인 컨벤션이다.



자료형: 원시타입 vs 참조 타입

JS의 자료형은 크게 **원시 타입(Primitive Type)**과 **참조 타입(Reference Type)**으로 나뉜다.

원시 타입 (7종)

  • Number — 숫자 (정수, 실수 구분 없이 하나의 타입)
  • String — 문자열
  • Boolean — true / false
  • undefined — 값이 할당되지 않은 상태
  • null — 값이 의도적으로 비어있음을 나타냄
  • Symbol — 유일하고 변경 불가능한 값 (주로 객체 프로퍼티 키의 충돌을 막을 때 사용)
  • BigInt — 아주 큰 정수를 다룰 때 사용

참조 타입

  • Object, Array, Function 등이 여기 속한다. 원시 타입을 제외한 모든 값은 사실상 객체다.

원시 타입은 값 자체가 변수에 저장된다. 반면 참조 타입은 실제 데이터는 힙(Heap) 메모리에 저장되고, 변수에는 그 데이터가 있는 **주소(참조값)**가 저장된다.

// 원시 타입: 값 복사 let a = 10; let b = a; b = 20; console.log(a); // 10 (a는 영향받지 않음) // 참조 타입: 주소 복사 let obj1 = { count: 10 }; let obj2 = obj1; obj2.count = 20; console.log(obj1.count); // 20 (obj1과 obj2가 같은 객체를 가리키기 때문)

이 차이 때문에 객체나 배열을 복사할 때는 단순 할당이 아니라 별도의 복사 방법(얕은 복사/깊은 복사)이 필요해진다.



타입 변환

타입 변환은 크게 두 가지로 나뉜다.

암묵적 형변환 (Implicit Coercion) JS 엔진이 알아서 타입을 바꿔주는 것. 편리하지만 예상치 못한 버그의 원인이 되기도 한다.

console.log("5" + 3); // "53" (문자열로 변환되어 이어붙여짐) console.log("5" - 3); // 2 (숫자로 변환되어 연산됨) console.log(1 + true); // 2 (true가 1로 변환) console.log("" + null); // "null"

명시적 형변환 (Explicit Coercion) 개발자가 직접 타입을 변환하는 것.

String(123); // "123" Number("123"); // 123 Boolean(0); // false


동등 비교 (== vs ===)

  • == (동등 연산자): 타입이 달라도 값만 비교하며, 비교 전에 암묵적 형변환이 일어난다.
  • === (일치 연산자): 타입과 값이 모두 같아야 true다.
console.log(1 == "1"); // true (타입 변환 후 비교) console.log(1 === "1"); // false (타입이 다름) console.log(null == undefined); // true console.log(null === undefined); // false

암묵적 형변환은 예측하기 어려운 결과를 만들 수 있어서, 실무에서는 특별한 이유가 없다면 ===를 사용하는 것이 권장된다.



템플릿 리터럴

백틱(`)을 사용해 문자열을 작성하는 방식이다. ES6부터 도입되었고, 문자열 안에 변수나 표현식을 쉽게 넣을 수 있다.

백틱(`)을 사용해 문자열을 작성하는 방식이다. ES6부터 도입되었고, 문자열 안에 변수나 표현식을 쉽게 넣을 수 있다.

const name = "철수"; const age = 20; // 기존 방식 console.log("제 이름은 " + name + "이고, 나이는 " + age + "살입니다."); // 템플릿 리터럴 console.log(`제 이름은 ${name}이고, 나이는 ${age}살입니다.`);

주요 특징

  • ${} 안에 변수뿐 아니라 표현식, 함수 호출도 넣을 수 있다.
console.log(`합계는 ${10 + 20}입니다.`);
  • 줄바꿈이 그대로 반영된다. (기존에는 \n을 써야 했음)
const message = `첫 번째 줄 두 번째 줄`;


디스트럭처링 (구조분해 할당)

배열이나 객체의 값을 개별 변수로 쉽게 꺼낼 수 있게 해주는 문법이다.

배열 구조분해

const arr = [1, 2, 3]; const [first, second, third] = arr; console.log(first, second, third); // 1 2 3 // 일부만 꺼내기 const [a, , c] = arr; // 두 번째 값 건너뛰기 console.log(a, c); // 1 3

객체 구조분해

const user = { name: "철수", age: 20 }; const { name, age } = user; console.log(name, age); // 철수 20 // 변수명 바꾸기 const { name: userName } = user; console.log(userName); // 철수

기본값 설정

const { name, height = 170 } = user; console.log(height); // 170 (user에 height 속성이 없으므로 기본값 사용)

중첩 구조분해

const person = { name: "철수", address: { city: "서울", zip: "12345" } }; const { address: { city } } = person; console.log(city); // 서울

함수 매개변수에서 활용

function printUser({ name, age }) { console.log(`${name}, ${age}살`); } printUser(user);

객체에서 필요한 값만 뽑아 쓸 때 코드가 훨씬 간결해진다.



Spread / Rest 연산자

둘 다 ...을 사용하지만 쓰이는 위치와 역할이 다르다.

Spread 연산자 — 펼치기

배열이나 객체를 개별 요소로 “펼칠” 때 사용한다.

// 배열 합치기 const arr1 = [1, 2]; const arr2 = [3, 4]; const merged = [...arr1, ...arr2]; console.log(merged); // [1, 2, 3, 4] // 배열 복사 (얕은 복사) const copy = [...arr1]; // 객체 합치기 const obj1 = { a: 1 }; const obj2 = { b: 2 }; const mergedObj = { ...obj1, ...obj2 }; console.log(mergedObj); // { a: 1, b: 2 } // 함수 인자로 펼치기 function sum(x, y, z) { return x + y + z; } const nums = [1, 2, 3]; console.log(sum(...nums)); // 6

Rest 연산자 — 모으기

여러 개의 값을 하나의 배열로 “모을” 때 사용한다. 함수의 매개변수나 구조분해 할당에서 주로 쓰인다.

// 함수 매개변수에서 나머지 모으기 function sum(...numbers) { return numbers.reduce((acc, cur) => acc + cur, 0); } console.log(sum(1, 2, 3, 4)); // 10 // 구조분해에서 나머지 모으기 const [first, ...rest] = [1, 2, 3, 4]; console.log(first); // 1 console.log(rest); // [2, 3, 4] const { name, ...others } = { name: "철수", age: 20, city: "서울" }; console.log(others); // { age: 20, city: "서울" }

구분 포인트: ...이 값을 펼치는 위치(함수 호출, 배열/객체 리터럴 안)에 있으면 spread, 값을 모으는 위치(함수 매개변수, 구조분해 할당의 왼쪽)에 있으면 rest다.



마지막 수정