데이터(속성)와 기능(메서드)를 하나의 객체로 묶어서 코드를 구조화하는 프로그래밍 패러다임
📦 예: "자동차(Car)"를 객체로 본다면
const car = {
color: 'red',
speed: 0,
drive() {
this.speed += 10;
console.log(`Driving at ${this.speed}km/h`);
},
stop() {
this.speed = 0;
console.log('Car stopped');
}
};
여기서 color, speed는 속성(property)
drive(), stop()은 기능(method)이다.
| 특징 | 설명 |
|---|---|
| 캡슐화 | 데이터와 기능을 묶고, 외부에서 직접 접근 못 하게 보호함 (private, get/set 등) |
| 상속 | 기존 클래스의 기능을 물려받아 새로운 클래스를 만들 수 있음 |
| 다형성 | 같은 메서드 이름으로도 다르게 동작할 수 있음 (오버라이딩 등) |
| 추상화 | 복잡한 내부는 숨기고 필요한 정보만 보여줌 |
클래스와 객체를 이용해 작성한 코드는 한 번 만들어두면 여러 곳에서 재사용할 수 있어.
예시: Car 클래스를 만들어두면, BMW, Hyundai 객체를 따로 만들 수 있어.
코드가 모듈화되어 있어서, 버그 수정이나 기능 추가 시 관련 클래스만 수정하면 됨.
예시: 자동차 기능을 수정할 때 엔진 관련된 코드만 고치면 됨.
객체 내부의 데이터는 외부에서 직접 접근하지 못하고, 메서드를 통해서만 접근 가능하게 함.
예시: 사람 객체의 주민번호는 getResidentNumber()로만 확인할 수 있게.
복잡한 내부 구현은 감추고, 필요한 정보와 기능만 외부에 보여줌.
예시: 버튼을 누르면 어떤 동작이 실행되지만, 사용자는 내부 동작을 몰라도 됨.
동일한 메서드 이름으로도 다른 동작을 하도록 구현 가능.
예시: draw()라는 메서드가 Circle에서는 원을, Rectangle에서는 사각형을 그림.
- 💡 코드를 재사용하기 좋음 (상속, 모듈화)
- 🛠️ 유지보수 쉬움 (기능별로 분리)
- 📦 현실 세계를 코드로 표현하기 쉬움
- 👥 협업에 유리 (클래스 단위로 나눠 작업 가능)
사실 프론트엔드에서는 함수형 스타일을 더 많이 쓴다고 생각했다.하지만 점점 규모가 커지고 유지보수가 필요한 프로젝트를 하다 보면 객체지향적인 사고가 왜 중요한지 깨닫게 된다.
우리의 목표는 "객체지향을 배우는 것"이 아니라 유지보수하기 좋은 코드를 만드는 것이다.
객체는 하나의 책임만 가지도록 설계한다.
내부 구현은 감추고 필요한 기능만 외부에 드러낸다.
관련 기능들을 하나의 객체에 묶어서, 변경 시 영향 범위를 최소화한다.
class User {
#name;
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
}
const user = new User("호이초이");
console.log(user.getName()); // 호이초이
객체는 스스로의 책임을 다하면서도, 다른 객체와 협력해야 한다.
너무 많은 일을 혼자 처리하는 객체는 자율적이지만 고립됨
너무 많은 것을 외부에 의존하면 협력적이지만 불안정함
프론트엔드 개발자도 OOP를 알아야 하는 이유는 간단하다.규모가 커지고 협업이 많아질수록 유지보수 가능한 코드가 필요하기 때문이다.
객체의 책임을 분리하고, 내부 구현은 숨기며, 외부에는 필요한 기능만 드러내기
이러한 객체지향적 사고는 프론트엔드 개발에서도 명확한 협업, 예측 가능한 코드, 그리고 유연한 구조 설계로 이어진다.