JavaScript 입문 6편 - 객체 다루기

사용자 정보를 저장한다고 생각해보세요. 이름, 나이, 이메일을 각각 변수로 만들면 관리가 어려워요. 이럴 때 객체를 쓰면 관련된 데이터를 하나로 묶을 수 있습니다.
객체 배울 때 obj1 = obj2 하면 복사가 아니라 참조라는 걸 몰라서 한참 헤맸어요. obj2 바꿨는데 obj1도 같이 바뀌길래 뭐지? 했죠. 지금은 복사할 땐 무조건 스프레드 연산자 씁니다.
객체가 뭔가요?
객체는 키(key)와 값(value) 쌍으로 이루어진 데이터 모음이에요.
let person = {
name: "철수",
age: 25,
email: "chulsu@example.com"
};
중괄호 {}로 만들고, : 로 키와 값을 연결합니다.
객체 만들기
객체 리터럴 (가장 흔함)
let car = {
brand: "현대",
model: "소나타",
year: 2023,
color: "흰색"
};
new Object() (잘 안 씀)
let car = new Object();
car.brand = "현대";
car.model = "소나타";
객체 접근하기
점 표기법
let person = {
name: "철수",
age: 25
};
console.log(person.name); // "철수"
console.log(person.age); // 25
실행 결과:
대괄호 표기법
console.log(person["name"]); // "철수"
console.log(person["age"]); // 25
실행 결과:
언제 대괄호를 쓰나요?
// 키에 공백이나 특수문자가 있을 때
let obj = {
"first name": "철수",
"email-address": "test@test.com"
};
console.log(obj["first name"]); // 점 표기법 불가능
console.log(obj["email-address"]);
// 변수로 키에 접근할 때
let key = "name";
console.log(person[key]); // "철수"
실행 결과:
객체 수정하기
let person = {
name: "철수",
age: 25
};
// 값 변경
person.age = 26;
console.log(person.age); // 26
// 속성 추가
person.email = "chulsu@test.com";
console.log(person.email); // "chulsu@test.com"
// 속성 삭제
delete person.email;
console.log(person.email); // undefined
실행 결과:
메서드 (Method)
객체에 함수를 넣으면 메서드가 돼요.
let person = {
name: "철수",
age: 25,
sayHello: function() {
console.log("안녕하세요!");
}
};
person.sayHello(); // 안녕하세요!
실행 결과:
메서드 단축 문법
let person = {
name: "철수",
age: 25,
sayHello() { // function 키워드 생략 가능
console.log("안녕하세요!");
}
};

this 키워드
메서드 안에서 this는 그 객체 자신을 가리켜요.
let person = {
name: "철수",
age: 25,
introduce() {
console.log(`안녕하세요, 제 이름은 ${this.name}이고, 나이는 ${this.age}살입니다.`);
}
};
person.introduce(); // 안녕하세요, 제 이름은 철수이고, 나이는 25살입니다.
실행 결과:
주의: 화살표 함수는 this를 다르게 처리해요!
let person = {
name: "철수",
sayHi: () => {
console.log(`Hi, ${this.name}`); // undefined (화살표 함수는 this 바인딩 안 됨)
}
};
메서드에는 일반 함수를 쓰세요.
객체 안의 객체
객체 안에 객체를 넣을 수 있어요.
let person = {
name: "철수",
age: 25,
address: {
city: "서울",
district: "강남구",
zipcode: "06000"
}
};
console.log(person.address.city); // "서울"
console.log(person.address.zipcode); // "06000"
실행 결과:
객체와 반복문
for…in 문
let person = {
name: "철수",
age: 25,
email: "chulsu@test.com"
};
for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// 출력:
// name: 철수
// age: 25
// email: chulsu@test.com
실행 결과:
Object 메서드
let person = {
name: "철수",
age: 25,
email: "chulsu@test.com"
};
// 모든 키
console.log(Object.keys(person)); // ["name", "age", "email"]
// 모든 값
console.log(Object.values(person)); // ["철수", 25, "chulsu@test.com"]
// 키-값 쌍
console.log(Object.entries(person));
// [["name", "철수"], ["age", 25], ["email", "chulsu@test.com"]]
실행 결과:
실전 예제
1. 사용자 객체
let user = {
username: "chulsu123",
email: "chulsu@test.com",
isLoggedIn: false,
login() {
this.isLoggedIn = true;
console.log(`${this.username}님이 로그인했습니다.`);
},
logout() {
this.isLoggedIn = false;
console.log(`${this.username}님이 로그아웃했습니다.`);
}
};
user.login(); // chulsu123님이 로그인했습니다.
user.logout(); // chulsu123님이 로그아웃했습니다.
실행 결과:
2. 쇼핑 카트
let cart = {
items: [],
addItem(item) {
this.items.push(item);
console.log(`${item}이(가) 추가되었습니다.`);
},
removeItem(item) {
let index = this.items.indexOf(item);
if (index > -1) {
this.items.splice(index, 1);
console.log(`${item}이(가) 삭제되었습니다.`);
}
},
getTotal() {
return this.items.length;
}
};
cart.addItem("사과"); // 사과이(가) 추가되었습니다.
cart.addItem("바나나"); // 바나나이(가) 추가되었습니다.
console.log(cart.getTotal()); // 2
실행 결과:
3. 계산기 객체
let calculator = {
result: 0,
add(num) {
this.result += num;
return this;
},
subtract(num) {
this.result -= num;
return this;
},
multiply(num) {
this.result *= num;
return this;
},
getResult() {
return this.result;
},
clear() {
this.result = 0;
return this;
}
};
// 메서드 체이닝
calculator.add(10).multiply(2).subtract(5).getResult();
console.log(calculator.result); // 15
실행 결과:
생성자 함수
같은 구조의 객체를 여러 개 만들 때 씁니다.
function Person(name, age) {
this.name = name;
this.age = age;
this.introduce = function() {
console.log(`안녕하세요, ${this.name}입니다.`);
};
}
let person1 = new Person("철수", 25);
let person2 = new Person("영희", 23);
person1.introduce(); // 안녕하세요, 철수입니다.
person2.introduce(); // 안녕하세요, 영희입니다.
실행 결과:
구조 분해 할당
객체에서 값을 꺼내는 편리한 방법이에요.
let person = {
name: "철수",
age: 25,
email: "chulsu@test.com"
};
// 기존 방식
let name = person.name;
let age = person.age;
// 구조 분해 할당
let { name, age } = person;
console.log(name); // "철수"
console.log(age); // 25
// 다른 이름으로 저장
let { name: userName, age: userAge } = person;
console.log(userName); // "철수"
실행 결과:
자주 하는 실수
1. this 헷갈림
let person = {
name: "철수",
sayHi() {
setTimeout(function() {
console.log(this.name); // undefined (this가 바뀜)
}, 1000);
}
};
// 해결 방법: 화살표 함수
let person2 = {
name: "영희",
sayHi() {
setTimeout(() => {
console.log(this.name); // "영희" (this 유지됨)
}, 1000);
}
};
2. 객체 복사 실수
let obj1 = { name: "철수" };
let obj2 = obj1; // 참조만 복사됨!
obj2.name = "영희";
console.log(obj1.name); // "영희" (obj1도 바뀜!)
// 제대로 복사하려면
let obj3 = { ...obj1 }; // spread 연산자
obj3.name = "민수";
console.log(obj1.name); // "영희" (obj1은 안 바뀜)
실행 결과:
운영자 실전 노트
실제 프로젝트 진행하며 겪은 문제
- obj1 = obj2로 복사했는데 obj2 수정 시 obj1도 변경됨 → 스프레드 연산자나 Object.assign()으로 얕은 복사
- 깊게 중첩된 객체를 복사했는데 내부 참조는 그대로 → JSON.parse(JSON.stringify()) 또는 lodash cloneDeep 사용
이 경험을 통해 알게 된 점
- JavaScript 객체는 참조 타입이므로 = 연산자는 복사가 아니라 같은 메모리 주소를 가리킨다
- React/Vue 같은 프레임워크에서는 불변성 유지를 위해 항상 새 객체를 만들어야 한다
다음 단계
다음 글에서는 DOM 조작 기초를 배운다. JavaScript로 웹 페이지의 HTML 요소를 찾고 수정하는 방법을 알아볼 예정이다. 드디어 화면에 뭔가 보이는 걸 만들 수 있다.
this 키워드는 지금도 가끔 헷갈린다. 특히 화살표 함수와 일반 함수에서 this가 다르게 동작하는 게 까다롭다. 메서드 안에서는 일반 함수, 콜백에서는 화살표 함수로 구분해서 사용한다.
JavaScript 독학 가이드 시리즈:
← 블로그 목록으로