모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

15강 / 전체 22강

객체와 배열 응용

14분 읽기 조회 4

배열 구조 분해, 객체 배열 CRUD 패턴, 중첩 데이터 처리, 얕은·깊은 복사 차이, JSON 변환까지 실전 복합 데이터 구조를 완전히 다룹니다.

🎯 학습 목표

이 강을 마치면 다음을 할 수 있습니다.

  • 배열 구조 분해 할당과 나머지 패턴을 활용할 수 있습니다.
  • 객체 배열에서 CRUD(추가·읽기·수정·삭제) 패턴을 구현할 수 있습니다.
  • 얕은 복사와 깊은 복사의 차이를 이해하고 상황에 맞게 사용할 수 있습니다.
  • JSON.stringify/JSON.parse로 데이터를 직렬화하고 역직렬화할 수 있습니다.

🔧 배열 구조 분해 할당

이 섹션에서는 14강에서 배운 객체 구조 분해에 이어, 배열에서도 값을 바로 변수로 꺼내는 배열 구조 분해를 살펴보겠습니다.

배열 구조 분해 할당은 객체와 달리 키 이름이 아닌 순서(위치)를 기준으로 값을 추출합니다. 대괄호 []를 사용합니다.

const rgb = [255, 128, 0];

// 기존 방식
const r1 = rgb[0];
const g1 = rgb[1];
const b1 = rgb[2];

// 배열 구조 분해
const [r, g, b] = rgb;
console.log(r, g, b);  // 255 128 0

// 특정 요소 건너뛰기 (쉼표로)
const [first, , third] = ["a", "b", "c"];
console.log(first, third);  // "a" "c"

// 나머지 패턴 — rest
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head);  // 1
console.log(tail);  // [2, 3, 4, 5]

// 기본값 설정
const [x = 0, y = 0, z = 0] = [10, 20];
console.log(x, y, z);  // 10 20 0

// 두 변수 값 교환 — 구조 분해의 우아한 활용
let a = 1, b2 = 2;
[a, b2] = [b2, a];
console.log(a, b2);  // 2 1

// 함수에서 여러 값 반환 패턴
function getMinMax(arr) {
  return [Math.min(...arr), Math.max(...arr)];
}
const [min, max] = getMinMax([3, 1, 7, 2, 9]);
console.log(min, max);  // 1 9

배열 구조 분해에서 특히 두 변수 값 교환 패턴은 매우 우아합니다. 기존에는 임시 변수가 필요했지만, 구조 분해로 한 줄에 처리할 수 있습니다. 함수가 배열을 반환할 때 이를 바로 구조 분해로 받는 패턴도 실무에서 자주 사용됩니다. Math.min(...arr)처럼 스프레드 연산자로 배열을 개별 인수로 펼치는 것도 11강에서 배운 개념입니다.

🗃️ 객체 배열 CRUD 패턴

이 섹션에서는 실무에서 가장 자주 다루는 데이터 구조인 객체 배열에서 항목을 추가·수정·삭제하는 표준 패턴을 살펴보겠습니다.

실제 애플리케이션의 데이터는 대부분 객체 배열(Object Array) 형태입니다. 할 일 목록, 상품 목록, 사용자 목록처럼 같은 구조의 여러 항목을 배열로 관리합니다. 이 데이터를 조작하는 CRUD 패턴을 익혀두면 어떤 기능도 구현할 수 있습니다. 특히 불변성을 유지하는 방식으로 작성하면 React 같은 프레임워크에서도 그대로 사용할 수 있습니다.

let todos = [
  { id: 1, text: "자바스크립트 공부", done: true },
  { id: 2, text: "운동하기",        done: false },
  { id: 3, text: "독서 30분",      done: false }
];

// C — Create: 새 항목 추가
function addTodo(text) {
  const newId = todos.length ? Math.max(...todos.map(t => t.id)) + 1 : 1;
  const newTodo = { id: newId, text, done: false };  // 단축 속성명 활용
  todos = [...todos, newTodo];  // 스프레드로 불변 추가
}
addTodo("리액트 공부");
console.log(todos.length);  // 4

// R — Read: 조건으로 읽기
const doneTodos = todos.filter(t => t.done);
console.log(doneTodos.map(t => t.text));  // ["자바스크립트 공부"]

const todo = todos.find(t => t.id === 2);
console.log(todo.text);  // "운동하기"

// U — Update: 특정 항목 수정
function toggleTodo(id) {
  todos = todos.map(t =>
    t.id === id ? { ...t, done: !t.done } : t  // 해당 id만 done 토글
  );
}
toggleTodo(2);
console.log(todos.find(t => t.id === 2).done);  // true

// D — Delete: 특정 항목 삭제
function deleteTodo(id) {
  todos = todos.filter(t => t.id !== id);
}
deleteTodo(3);
console.log(todos.length);  // 3

이 패턴의 핵심은 불변성(Immutability)입니다. 직접 수정하는 대신 항상 새로운 배열이나 객체를 만들어 변수에 재할당합니다. 수정 패턴에서 t.id === id ? { ...t, done: !t.done } : t는 해당 항목만 새 객체로 교체하고 나머지는 원본 참조를 유지하는 효율적인 방식입니다. 삭제는 filter로 해당 항목만 빼고 새 배열을 만들기 때문에 원본에 접근조차 하지 않습니다. 이 세 가지 패턴은 앞으로 어떤 프레임워크를 사용하든 핵심 데이터 조작 방법입니다.

🏗️ 중첩 데이터 구조 처리

이 섹션에서는 객체 안에 배열, 배열 안에 객체처럼 중첩된 복잡한 데이터 구조를 다루는 방법을 살펴보겠습니다.

실제 API 데이터는 여러 단계로 중첩된 복잡한 구조를 가집니다. 예를 들어 회사 → 부서 배열 → 직원 배열처럼 계층적으로 구성됩니다. 이를 올바르게 읽고 처리하는 방법을 익혀보겠습니다.

const company = {
  name: "테크 코리아",
  departments: [
    {
      name: "개발팀",
      employees: [
        { name: "홍길동", salary: 5000000 },
        { name: "김철수", salary: 4500000 }
      ]
    },
    {
      name: "디자인팀",
      employees: [
        { name: "이영희", salary: 4800000 },
        { name: "박민준", salary: 4200000 }
      ]
    }
  ]
};

// 중첩 접근
console.log(company.departments[0].name);  // "개발팀"
console.log(company.departments[1].employees[0].name);  // "이영희"

// 전체 직원 수
const totalCount = company.departments.reduce(
  (acc, dept) => acc + dept.employees.length, 0
);
console.log(totalCount);  // 4

// 모든 직원 평균 급여
const allSalaries = company.departments
  .flatMap(dept => dept.employees)  // 중첩 배열 펼치기 — 4명의 배열
  .map(emp => emp.salary);          // 급여만 추출
const avgSalary = allSalaries.reduce((a, b) => a + b, 0) / allSalaries.length;
console.log(`평균 급여: ${avgSalary.toLocaleString()}원`);  // 4,625,000원

// 옵셔널 체이닝 — 중첩 접근 시 안전하게
const user2 = null;
console.log(user2?.address?.city);  // undefined (TypeError 없음)

flatMap은 map을 적용한 후 한 단계 펼치는(flat) 동작을 동시에 수행합니다. departments.map(d => d.employees)의 결과는 배열 안의 배열이지만, flatMap을 쓰면 하나의 배열로 펼쳐집니다. 중첩 배열에서 개별 요소 전체를 한 번에 처리할 때 매우 유용합니다. 옵셔널 체이닝(Optional Chaining) 연산자 ?.는 중첩 데이터 접근 시 중간 값이 null이나 undefined이면 오류 대신 undefined를 반환하므로, API 응답처럼 존재하지 않을 수 있는 데이터에 안전하게 접근할 수 있습니다.

📋 얕은 복사 vs 깊은 복사

이 섹션에서는 중첩 객체·배열에서 복사의 한계와 깊은 복사 방법을 살펴보겠습니다.

11강과 14강에서 스프레드 연산자로 복사하는 방법을 배웠습니다. 그런데 이 방법에는 중요한 한계가 있습니다. 얕은 복사(Shallow Copy)는 1단계 속성만 새로 만들고, 중첩된 객체·배열은 여전히 같은 참조를 공유합니다. 이 차이를 이해하지 못하면 예상치 못한 버그가 생깁니다.

const original = {
  name: "홍길동",
  scores: [90, 85, 92],              // 중첩 배열
  address: { city: "서울" }          // 중첩 객체
};

// 얕은 복사 — 스프레드
const shallow = { ...original };
shallow.name = "김철수";             // 기본값 — 독립적 변경 OK
shallow.scores.push(88);            // 중첩 배열 수정
shallow.address.city = "부산";       // 중첩 객체 수정

console.log(original.name);          // "홍길동" (기본값은 독립)
console.log(original.scores);        // [90, 85, 92, 88] 원본도 변함!
console.log(original.address.city);  // "부산" 원본도 변함!

// 깊은 복사 방법 1: JSON 직렬화
const deep1 = JSON.parse(JSON.stringify(original));
deep1.scores.push(77);
console.log(original.scores);  // [90, 85, 92, 88] 원본 유지
// 주의: 함수, undefined, Symbol, Date 객체는 올바르게 복사되지 않음

// 깊은 복사 방법 2: structuredClone (ES2022 표준, 권장)
const deep2 = structuredClone(original);
deep2.address.city = "대구";
console.log(original.address.city);  // "부산" 원본 유지
// 더 많은 타입을 지원하며 현대 브라우저와 Node.js 17+에서 사용 가능

얕은 복사의 한계를 이해하는 것은 매우 중요합니다. 대부분의 실무 상황에서는 스프레드 연산자의 얕은 복사로 충분합니다. CRUD 패턴에서 { ...t, done: !t.done }처럼 사용할 때, 수정하는 속성이 기본값(문자열, 숫자, 불리언)이라면 얕은 복사가 안전합니다. 중첩 객체·배열을 독립적으로 수정해야 할 때만 깊은 복사를 사용하세요. structuredClone()이 없는 구형 환경에서는 JSON 방식을 사용하되, 함수나 날짜 객체가 있을 때는 각별히 주의해야 합니다.

🔄 JSON — 데이터 직렬화

이 섹션에서는 자바스크립트 객체를 서버와 주고받을 때 사용하는 JSON 형식과 변환 방법을 살펴보겠습니다.

JSON(JavaScript Object Notation)은 자바스크립트 객체 리터럴에서 파생된 데이터 교환 형식입니다. 서버 API와 데이터를 주고받을 때 사실상 표준으로 사용됩니다. 자바스크립트 객체와 매우 비슷하게 생겼지만, 차이점이 있습니다. JSON에서는 모든 키가 큰따옴표로 감싸져야 하고, 함수·undefined·Symbol은 표현할 수 없습니다.

const user = {
  name: "홍길동",
  age: 28,
  hobbies: ["독서", "코딩"]
};

// 객체 → JSON 문자열 (직렬화)
const jsonStr = JSON.stringify(user);
console.log(jsonStr);
// '{"name":"홍길동","age":28,"hobbies":["독서","코딩"]}'
console.log(typeof jsonStr);  // "string" — 문자열!

// 보기 좋게 들여쓰기 (디버깅·로그 확인에 유용)
const prettyJson = JSON.stringify(user, null, 2);
console.log(prettyJson);
// {
//   "name": "홍길동",
//   "age": 28,
//   "hobbies": ["독서", "코딩"]
// }

// JSON 문자열 → 객체 (역직렬화)
const parsed = JSON.parse(jsonStr);
console.log(parsed.name);     // "홍길동"
console.log(typeof parsed);   // "object"

// JSON의 제한 확인
const withSpecial = {
  name: "홍길동",
  greet: function() { return "안녕!"; },  // 함수는 직렬화 시 사라짐
  value: undefined,                        // undefined도 사라짐
  createdAt: new Date()                   // Date는 ISO 문자열로 변환
};
console.log(JSON.stringify(withSpecial));
// '{"name":"홍길동","createdAt":"2024-01-01T00:00:00.000Z"}'
// greet, value 속성은 결과에 포함되지 않음

JSON 직렬화는 실무에서 매우 자주 사용됩니다. 26강에서 fetch로 서버 API를 호출할 때, 요청 body를 JSON.stringify()로 변환하고 응답을 response.json()으로 역직렬화하는 과정이 핵심입니다. 또한 localStorage는 문자열만 저장할 수 있어 객체를 저장할 때 JSON 직렬화가 필수입니다. 이 내용은 27강에서 자세히 다룹니다.

📝 핵심 요약

15강에서 배운 내용을 정리해 보겠습니다.

개념핵심 내용
배열 구조 분해위치 기준 추출, 나머지 패턴(...rest), 기본값, 값 교환
객체 배열 추가[...arr, newItem] — 스프레드로 불변 추가
객체 배열 수정map + { ...item, field: value }
객체 배열 삭제filter(item => item.id !== targetId)
flatMapmap + flat 한 번에, 중첩 배열을 펼치며 변환
얕은 복사스프레드/slice — 1단계만 복사, 중첩은 참조 공유
깊은 복사structuredClone()(권장) 또는 JSON.parse(JSON.stringify())
JSON 변환JSON.stringify(obj) ↔ JSON.parse(str)

이로써 2단계(배열·객체, 11~15강)가 완성되었습니다! 다음 강인 16강 — DOM이란부터는 3단계가 시작됩니다. 지금까지 배운 모든 자바스크립트 기초가 실제 웹 페이지와 연결되는 순간입니다. DOM을 통해 HTML 요소를 선택하고 조작하는 방법을 배우면 진짜 인터랙티브 웹 페이지를 만들 수 있게 됩니다!

관련 주제

  • 배열 구조 분해
  • 나머지 패턴
  • 객체 배열 CRUD
  • 얕은 복사 깊은 복사
  • JSON.stringify parse
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 자바스크립트 기초 30강 — 웹을 움직이는 언어
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나

📚 시리즈 전체 공유

자바스크립트 기초 30강 — 웹을 움직이는 언어

이 강의가 속한 시리즈는 총 22강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...