[JSTS-003][입문] 배열·객체를 원본 변경 없이 다루기
페이지 정보

본문
[이번 수업]
JavaScript 배열과 객체에 여러 값을 담는 방법을 익히고, 원본을 직접 바꾸지 않는 불변 데이터 처리의 이유를 배웁니다. map과 펼침 문법으로 새 값을 만들어 결과를 비교합니다.
[선수지식]
JSTS-001의 실행·기본문법과 JSTS-002의 타입·함수·스코프를 읽고 Node.js를 준비하세요.
[학습목표]
1. 배열과 객체의 쓰임을 구분한다.
2. 값 복사와 참조 공유의 차이를 설명한다.
3. 배열과 중첩 객체를 원본 변경 없이 갱신한다.
[핵심개념]
배열은 순서가 있는 값의 목록입니다. 대괄호로 만들고 0부터 시작하는 인덱스로 읽습니다.map은 각 항목에 함수를 적용한 새 배열을 만듭니다.
객체는 이름이 붙은 속성과 값을 묶습니다. 배열도 객체도 변수에 객체 자체가 복제되는 것이 아니라 그 객체를 가리키는 참조가 저장됩니다. const는 변수에 다른 값을 다시 대입하지 못하게 하지만 배열과 객체 내부 변경까지 막지는 않습니다.
불변 데이터 처리는 기존 배열·객체를 수정하는 대신 변경 내용을 반영한 새 값을 만드는 방식입니다. 바뀐 경로의 배열과 객체만 새로 만들고 바뀌지 않은 부분은 안전하게 재사용하는 구조적 공유를 사용할 수 있습니다.
배열 펼침 [...items]과 객체 펼침 { ...item }은 바깥 한 단계의 열거 가능한 속성을 복사합니다. 이것은 얕은 복사입니다. 중첩 객체까지 자동으로 새 객체가 되지 않으므로 profile.settings.theme을 바꾸려면 profile과 settings를 각각 펼쳐 새로 만들어야 합니다.
[따라하기]
immutable_demo.js에 다음을 저장하세요.
const original = [
{ id: 1, name: "A", active: false },
{ id: 2, name: "B", active: false },
];
const updated = original.map((item) =>
item.id === 2 ? { ...item, active: true } : item,
);
const profile = { name: "민수", settings: { theme: "light" } };
const updatedProfile = {
...profile,
settings: { ...profile.settings, theme: "dark" },
};
console.log("same_array", original === updated);
console.log("original_second", original[1].active);
console.log("updated_second", updated[1].active);
console.log("themes", profile.settings.theme, updatedProfile.settings.theme);
console.log("shared_first", original[0] === updated[0]);
Windows·macOS·Linux 모두 터미널에서 node immutable_demo.js로 실행합니다. 예상 결과는 다음과 같습니다.
same_array false
original_second false
updated_second true
themes light dark
shared_first true
updated는 original과 다른 배열입니다. id가 2인 객체만 펼침 문법으로 새로 만들었으므로 원본의 active는 false로 남습니다.
[흔한 실수]
첫째, const가 객체 내부도 불변으로 만든다고 생각합니다. 둘째, copy = original을 복사라고 생각합니다. 셋째, 객체 펼침 한 번이면 중첩 객체까지 모두 복사된다고 믿습니다.
[보안 주의]
불변 업데이트는 입력 검증이나 권한 검사를 대신하지 않습니다. 외부 객체를 합칠 때 허용할 키만 골라 새 객체를 만들고 __proto__·constructor·prototype 같은 위험한 키를 데이터 경로로 사용하지 마세요. JSON 크기와 중첩 깊이를 제한하고 예상한 배열·객체 구조와 값 범위를 검사합니다.
[직접 해볼 과제]
상품 배열 [{ id: 1, stock: 2 }, { id: 2, stock: 5 }]를 만드세요. map과 펼침 문법으로 id 1의 stock만 3으로 바꾼 새 배열을 만들고, 원본 stock은 2인지 확인하세요. 이어 없는 id를 받았을 때 모든 기존 객체를 그대로 재사용하는지도 ===로 검사합니다.
[확인문제]
1. const로 선언한 배열도 push로 바뀔 수 있는 이유는 무엇인가요?
2. 객체 펼침이 얕은 복사라는 말은 무슨 뜻인가요?
3. 예제에서 original[0]과 updated[0]이 같은 객체인 이유는 무엇인가요?
[다음 학습]
다음 글은 WEB-003 반응형 화면과 모바일 우선 설계입니다. JSTS 트랙에서는 JSTS-004 이벤트 루프와 비동기 처리로 이어집니다.
[공식 참고 자료]
ECMAScript Array.prototype.map 규격
https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.map
ECMAScript 객체 초기화·펼침 규격
https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-object-initializer
ECMAScript Object.freeze 규격
https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.freeze
Node.js 명령줄 실행 문서
https://nodejs.org/api/cli.html#node-options-script-arguments
OWASP 프로토타입 오염 방지 지침
https://cheatsheetseries.owasp.org/cheatsheets/Prototype_Pollution_Prevention_Cheat_Sheet.html
JavaScript 배열과 객체에 여러 값을 담는 방법을 익히고, 원본을 직접 바꾸지 않는 불변 데이터 처리의 이유를 배웁니다. map과 펼침 문법으로 새 값을 만들어 결과를 비교합니다.
[선수지식]
JSTS-001의 실행·기본문법과 JSTS-002의 타입·함수·스코프를 읽고 Node.js를 준비하세요.
[학습목표]
1. 배열과 객체의 쓰임을 구분한다.
2. 값 복사와 참조 공유의 차이를 설명한다.
3. 배열과 중첩 객체를 원본 변경 없이 갱신한다.
[핵심개념]
배열은 순서가 있는 값의 목록입니다. 대괄호로 만들고 0부터 시작하는 인덱스로 읽습니다.map은 각 항목에 함수를 적용한 새 배열을 만듭니다.
객체는 이름이 붙은 속성과 값을 묶습니다. 배열도 객체도 변수에 객체 자체가 복제되는 것이 아니라 그 객체를 가리키는 참조가 저장됩니다. const는 변수에 다른 값을 다시 대입하지 못하게 하지만 배열과 객체 내부 변경까지 막지는 않습니다.
불변 데이터 처리는 기존 배열·객체를 수정하는 대신 변경 내용을 반영한 새 값을 만드는 방식입니다. 바뀐 경로의 배열과 객체만 새로 만들고 바뀌지 않은 부분은 안전하게 재사용하는 구조적 공유를 사용할 수 있습니다.
배열 펼침 [...items]과 객체 펼침 { ...item }은 바깥 한 단계의 열거 가능한 속성을 복사합니다. 이것은 얕은 복사입니다. 중첩 객체까지 자동으로 새 객체가 되지 않으므로 profile.settings.theme을 바꾸려면 profile과 settings를 각각 펼쳐 새로 만들어야 합니다.
[따라하기]
immutable_demo.js에 다음을 저장하세요.
const original = [
{ id: 1, name: "A", active: false },
{ id: 2, name: "B", active: false },
];
const updated = original.map((item) =>
item.id === 2 ? { ...item, active: true } : item,
);
const profile = { name: "민수", settings: { theme: "light" } };
const updatedProfile = {
...profile,
settings: { ...profile.settings, theme: "dark" },
};
console.log("same_array", original === updated);
console.log("original_second", original[1].active);
console.log("updated_second", updated[1].active);
console.log("themes", profile.settings.theme, updatedProfile.settings.theme);
console.log("shared_first", original[0] === updated[0]);
Windows·macOS·Linux 모두 터미널에서 node immutable_demo.js로 실행합니다. 예상 결과는 다음과 같습니다.
same_array false
original_second false
updated_second true
themes light dark
shared_first true
updated는 original과 다른 배열입니다. id가 2인 객체만 펼침 문법으로 새로 만들었으므로 원본의 active는 false로 남습니다.
[흔한 실수]
첫째, const가 객체 내부도 불변으로 만든다고 생각합니다. 둘째, copy = original을 복사라고 생각합니다. 셋째, 객체 펼침 한 번이면 중첩 객체까지 모두 복사된다고 믿습니다.
[보안 주의]
불변 업데이트는 입력 검증이나 권한 검사를 대신하지 않습니다. 외부 객체를 합칠 때 허용할 키만 골라 새 객체를 만들고 __proto__·constructor·prototype 같은 위험한 키를 데이터 경로로 사용하지 마세요. JSON 크기와 중첩 깊이를 제한하고 예상한 배열·객체 구조와 값 범위를 검사합니다.
[직접 해볼 과제]
상품 배열 [{ id: 1, stock: 2 }, { id: 2, stock: 5 }]를 만드세요. map과 펼침 문법으로 id 1의 stock만 3으로 바꾼 새 배열을 만들고, 원본 stock은 2인지 확인하세요. 이어 없는 id를 받았을 때 모든 기존 객체를 그대로 재사용하는지도 ===로 검사합니다.
[확인문제]
1. const로 선언한 배열도 push로 바뀔 수 있는 이유는 무엇인가요?
2. 객체 펼침이 얕은 복사라는 말은 무슨 뜻인가요?
3. 예제에서 original[0]과 updated[0]이 같은 객체인 이유는 무엇인가요?
[다음 학습]
다음 글은 WEB-003 반응형 화면과 모바일 우선 설계입니다. JSTS 트랙에서는 JSTS-004 이벤트 루프와 비동기 처리로 이어집니다.
[공식 참고 자료]
ECMAScript Array.prototype.map 규격
https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.map
ECMAScript 객체 초기화·펼침 규격
https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-object-initializer
ECMAScript Object.freeze 규격
https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.freeze
Node.js 명령줄 실행 문서
https://nodejs.org/api/cli.html#node-options-script-arguments
OWASP 프로토타입 오염 방지 지침
https://cheatsheetseries.owasp.org/cheatsheets/Prototype_Pollution_Prevention_Cheat_Sheet.html
- 이전글[WEB-003][입문] 작은 화면부터 반응형 카드 화면 만들기 26.08.30
- 다음글[PY-003][입문] 리스트·튜플·딕셔너리·집합 구분하기 26.08.30
댓글목록
등록된 댓글이 없습니다.
