2.5 구조 분해 할당 (Destructuring)
구조 분해 할당이란?
**구조 분해 할당(Destructuring Assignment)**은 배열이나 객체의 값을 개별 변수로 추출하는 ES6 문법입니다. 코드를 훨씬 간결하고 읽기 쉽게 만들어줍니다.
// 기존 방식
const arr = [1, 2, 3];
const first = arr[0];
const second = arr[1];
// 구조 분해
const [a, b, c] = [1, 2, 3];
배열 구조 분해
기본 사용법
const colors = ["빨강", "초록", "파랑"];
// 기본 구조 분해
const [red, green, blue] = colors;
console.log(red); // "빨강"
console.log(green); // "초록"
console.log(blue); // "파랑"
// 일부만 추출
const [first, second] = colors;
console.log(first); // "빨강"
console.log(second); // "초록"
// 건너뛰기
const [, , third] = colors;
console.log(third); // "파랑"
const [r, , b] = colors;
console.log(r, b); // "빨강" "파랑"
기본값 설정
const [a = 1, b = 2, c = 3] = [10, 20];
console.log(a); // 10 (할당된 값 사용)
console.log(b); // 20 (할당된 값 사용)
console.log(c); // 3 (기본값 사용 - undefined였으므로)
// 실용적 예시
const [status = "pending", data = null] = getResult();
나머지 패턴 (rest)
const numbers = [1, 2, 3, 4, 5];
const [head, ...tail] = numbers;
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
const [first, second, ...rest] = numbers;
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// 나머지는 항상 마지막에!
// const [...rest, last] = numbers; // SyntaxError!
변수 교환 (Swap)
let x = 1;
let y = 2;
// 기존 방식 (임시 변수 필요)
let temp = x;
x = y;
y = temp;
// 구조 분해 방식 (우아함!)
[x, y] = [y, x];
console.log(x, y); // 2 1
// 실용적 예: 정렬 알고리즘
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // 교환!
}
}
}
return arr;
}
중첩 배열 구조 분해
const matrix = [[1, 2], [3, 4], [5, 6]];
const [[a, b], [c, d]] = matrix;
console.log(a, b, c, d); // 1 2 3 4
// 실용적 예: 좌표 쌍
const points = [[0, 0], [1, 5], [3, 2]];
for (const [x, y] of points) {
console.log(`좌표: (${x}, ${y})`);
}
객체 구조 분해
기본 사용법
const user = {
name: "김철수",
age: 25,
email: "chulsoo@example.com",
};
// 기본 구조 분해 (키 이름으로 변수 생성)
const { name, age, email } = user;
console.log(name); // "김철수"
console.log(age); // 25
console.log(email); // "chulsoo@example.com"
새 변수명으로 추출
const { name: userName, age: userAge } = user;
console.log(userName); // "김철수"
console.log(userAge); // 25
// name, age 변수는 생성되지 않음
// API 응답에서 유용
const { data: responseData, status: statusCode } = await fetch('/api/user');
기본값 설정
const config = { theme: "dark" };
const {
theme = "light",
language = "ko",
fontSize = 14,
} = config;
console.log(theme); // "dark" (config에 있으므로)
console.log(language); // "ko" (기본값 사용)
console.log(fontSize); // 14 (기본값 사용)
// 새 변수명 + 기본값 조합
const { theme: appTheme = "light" } = config;
console.log(appTheme); // "dark"
나머지 패턴
const { a, b, ...others } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a); // 1
console.log(b); // 2
console.log(others); // { c: 3, d: 4 }
// 객체에서 특정 키 제외
const { password, ...safeUser } = userWithPassword;
// safeUser에는 password 없음
중첩 객체 구조 분해
const person = {
name: "이영희",
address: {
city: "부산",
district: "해운대구",
zip: "48085",
},
contact: {
email: "younghee@example.com",
phone: "010-1234-5678",
},
};
// 중첩 구조 분해
const {
name,
address: { city, district },
contact: { email },
} = person;
console.log(name); // "이영희"
console.log(city); // "부산"
console.log(district); // "해운대구"
console.log(email); // "younghee@example.com"
// address, contact 변수는 생성되지 않음!
// address도 변수로 받고 싶다면
const { address, address: { city: cityName } } = person;
함수 파라미터 구조 분해
객체 파라미터 구조 분해
// 기존 방식
function createUser(options) {
const name = options.name;
const age = options.age || 0;
const role = options.role || "user";
}
// 구조 분해 방식
function createUser({ name, age = 0, role = "user" }) {
console.log(`${name} (${age}) - ${role}`);
}
createUser({ name: "철수", age: 25 });
// "철수 (25) - user"
createUser({ name: "영희", role: "admin" });
// "영희 (0) - admin"
// React에서 자주 사용하는 패턴
function Button({ label, onClick, disabled = false, className = "" }) {
return `<button class="${className}" ${disabled ? 'disabled' : ''} >${label}</button>`;
}
배열 파라미터 구조 분해
function getCoordinates([x, y, z = 0]) {
return { x, y, z };
}
console.log(getCoordinates([1, 2])); // { x: 1, y: 2, z: 0 }
console.log(getCoordinates([1, 2, 3])); // { x: 1, y: 2, z: 3 }
// 나머지 파라미터와 결합
function sum([first, ...rest]) {
return rest.reduce((acc, val) => acc + val, first);
}
console.log(sum([1, 2, 3, 4, 5])); // 15
for...of에서 구조 분해
const users = [
{ id: 1, name: "김철수", role: "admin" },
{ id: 2, name: "이영희", role: "user" },
{ id: 3, name: "박민수", role: "user" },
];
// 각 사용자 순회
for (const { id, name, role } of users) {
console.log(`${id}: ${name} (${role})`);
}
// 1: 김철수 (admin)
// 2: 이영희 (user)
// 3: 박민수 (user)
// Map 순회
const map = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// Object.entries() 순회
const obj = { x: 10, y: 20, z: 30 };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} = ${value}`);
}
실전 예제: API 응답 처리
// API 응답 데이터
const apiResponse = {
status: 200,
data: {
user: {
id: 42,
name: "김철수",
profile: {
avatar: "/images/user42.jpg",
bio: "JavaScript 개발자",
},
},
posts: [
{ id: 1, title: "JS 입문", likes: 45 },
{ id: 2, title: "비동기 처리", likes: 82 },
],
pagination: {
total: 50,
page: 1,
perPage: 10,
},
},
};
// 구조 분해로 깔끔하게 추출
const {
status,
data: {
user: {
id: userId,
name: userName,
profile: { avatar, bio },
},
posts,
pagination: { total, page },
},
} = apiResponse;
console.log(status); // 200
console.log(userId); // 42
console.log(userName); // "김철수"
console.log(avatar); // "/images/user42.jpg"
console.log(bio); // "JavaScript 개발자"
console.log(posts[0]); // { id: 1, title: "JS 입문", likes: 45 }
console.log(total); // 50
고수 팁
함수 반환값 구조 분해
// 여러 값 반환 (배열)
function minMax(arr) {
return [Math.min(...arr), Math.max(...arr)];
}
const [min, max] = minMax([3, 1, 4, 1, 5, 9, 2, 6]);
console.log(min, max); // 1 9
// 여러 값 반환 (객체) - 이름으로 접근 가능
function parseDate(dateStr) {
const [year, month, day] = dateStr.split('-').map(Number);
return { year, month, day };
}
const { year, month, day } = parseDate("2024-03-15");
console.log(year, month, day); // 2024 3 15
동적 키 구조 분해
const key = "name";
const { [key]: value } = { name: "김철수" };
console.log(value); // "김철수"
// 환경 변수 처리
function getEnvVar(varName, defaultValue = "") {
const { [varName]: value = defaultValue } = process.env;
return value;
}
const port = getEnvVar("PORT", "3000");
const apiKey = getEnvVar("API_KEY");