본문으로 건너뛰기

버그 제보

이상한 점을 알려 주시면 고칠게요. 지금 보고 있는 페이지와 브라우저 정보가 함께 담겨요.

페이지:

Frontend

객체 지향 프로그래밍과 JavaScript

작성 2026. 10. 17.추가
목차7개 항목
출처와 참고

테오(teo)의 「객체지향 프로그래밍과 javascript (약간의 역사를 곁들인...)」(2022.03)를 바탕으로 재구성하고, 캡슐화 수단은 javascript.info(모던 JavaScript 튜토리얼)의 「private, protected 프로퍼티와 메서드」 글로 보강한 노트다.

기술은 문제를 풀려고 나온다

기술 발전은 대개 네 시기를 돈다. 문제 인식(다들 겪지만 해법은 제각각) → 이름 붙은 기술 등장(해법이 먼저 있고 이름은 나중에 붙는다) → 부흥(모든 문제를 새 관점으로 풀려 한다) → 정체(새 한계가 보이고 다시 문제 인식으로). 낯선 용어는 대개 세 번째 시기에 만들어지므로, 용어보다 어떤 문제를 풀려고 나왔는지를 먼저 보면 이해가 쉽다.

객체 지향까지의 흐름

실제 역사는 여러 갈래로 겹쳐 진행됐지만, 개념의 인과를 보기 위해 한 줄로 단순화하면 다음과 같다.

flowchart LR
  g["goto<br/>흐름 제어가 엉킨다"] --> p["절차적(프로시저)<br/>함수로 재사용"]
  p --> n["네임스페이스<br/>전역 이름 충돌을 prefix로 해결"]
  n --> s["구조체<br/>연관 데이터를 하나로 묶는다"]
  s --> c["클래스<br/>데이터 + 그 데이터를 다루는 함수를 함께"]
  c --> o["객체 지향"]
단계푼 문제남은 문제
goto같은 코드를 다시 실행실행 순서를 강제로 바꾸니 흐름을 따라갈 수 없다
절차적 프로그래밍호출하고 돌아오는 프로시저(함수)로 재사용전역 변수 이름이 겹친다
네임스페이스파일·모듈 단위로 이름 접두어를 관리character1_hp, character1_mp처럼 연관 데이터가 흩어진다
구조체 (C)연관 데이터를 하나로 묶어 데이터 중심으로 코딩특정 구조체만 받는 함수군(character_attack(c))이 생긴다
클래스구조체 + 그 구조체를 받는 함수 = 클래스-

데이터와 처리 방식이 한 단위로 묶이자, 작은 프로그램이 독립적으로 도는 것처럼 보였다. 큰 프로그램을 통째로 짜는 대신 작은 부품을 만들어 조립하는(bottom-up) 방식이 가능해졌다. 클래스는 설계도, 그로 찍어 낸 것은 값과 동작을 함께 가진 사물 같아서 객체(object)라고 불렀다. 프로그램을 객체와 객체 사이의 메시지로 보는 관점이 객체 지향 프로그래밍(OOP)이다. 메시징을 본질로 보는 원래의 관점은 객체 지향의 본질: 메시징에 정리했다.

재사용을 위한 네 가지 개념

부품을 많이 만들어 두고 재사용하는 것이 핵심이 되자 개념들이 붙었다.

개념푸는 문제예
캡슐화밖에서 알 필요 없는 내부를 숨겨 안정성과 사용성을 높인다#mp는 클래스 안에서만 바꾼다
상속객체의 일부분만 재사용한다 (DRY)저글링과 히드라가 같은 이동·사망 로직을 공유
추상화공통 부분에 상위 개념의 이름을 붙인다사과·바나나 → 과일, 저글링·히드라 → Unit
다형성같은 타입으로 다루되 각자 방식대로 동작한다units.forEach(u => u.moveTo(x, y))가 지상·공중 유닛마다 다르게 움직인다

C++과 Java로 OOP가 주류가 됐다. 하지만 클래스만 쓴다고 좋아지지 않았다. 객체 사이 관계를 잘 정해야 하고 초기 설계 비용이 컸다. 그래서 SOLID 같은 설계 원칙과, 반복되는 설계 문제의 해법에 이름을 붙인 디자인 패턴(GoF 20여 개)이 뒤따랐다.

JavaScript의 객체 지향

JavaScript를 만든 Brendan Eich는 OOP에 회의적이었고 Scheme 같은 함수형 언어에 관심이 있었다. 회사는 당시 가장 인기 있던 Java처럼 보이길 원했다. 결과는 Java의 문법을 입은, 클래스 없는 함수형 기반 언어다. 브라우저의 작은 스크립트 언어로 출발했으니 복잡한 클래스 체계도 원하지 않았다.

객체 지향의 요소전통적 OOP (Java)JavaScript의 해법
객체 생성클래스로 인스턴스를 찍는다클래스 없이 객체 리터럴 {}로 바로 만든다
메서드클래스에 정의객체에 함수를 넣고 this로 자기 자신을 넘긴다
상속클래스 상속프로토타입 연결: 내게 없으면 연결된 객체를 찾아간다
다형성오버라이드내게 있으면 내 것을 쓴다
new클래스 생성자생성자 함수 + prototype
타입·인터페이스명시적 타입덕 타이핑: 같은 이름의 메서드가 있으면 같은 타입으로 쓴다
이벤트 리스너리스너 인터페이스 구현 패턴일급 함수: el.onclick = function () {} 한 줄
const animal = { sleep() { console.log('zzz', this.name); } };
const cat = Object.create(animal);   // 프로토타입 연결
cat.name = '냥이';
cat.sleep();                          // cat에 없으니 animal에서 찾는다

클래스가 없다는 이유로 처음엔 낮은 수준의 언어로 취급받았고, prototype.js처럼 클래스를 흉내 내는 라이브러리가 유행했다. 결국 ES6에 class가 들어왔지만 프로토타입 위에 얹은 문법일 뿐이다(class 문법). 체인을 따라 찾는 원리와 new가 하는 일은 프로토타입과 상속에 있다. 반대로 함수를 값으로 다루는 설계는 많은 객체 지향 언어에 영향을 줘, 지금은 함수형과 객체 지향을 섞어 쓰는 쪽으로 흐름이 바뀌었다.

캡슐화: 내부 인터페이스와 외부 인터페이스

캡슐화는 객체의 멤버를 외부 인터페이스(바깥에서 써도 되는 속성·메서드)와 내부 인터페이스(같은 클래스 안에서만 쓰는 구현 세부)로 나누는 것이다. 커피 머신은 버튼 몇 개만 드러내고 보일러와 배관은 커버 안에 숨긴다. 쓰는 사람은 버튼만 알면 되고, 커버를 벗기면 오히려 다치기 쉽다.

이점내용
오용 방지바깥 코드가 내부 상태를 직접 바꿔 객체를 망가뜨리지 못한다
바꾸기 쉬움바깥이 내부에 의존하지 않으므로, 외부 인터페이스만 지키면 내부 메서드의 이름·인자를 자유롭게 고칠 수 있다. 사용자는 새 버전으로 쉽게 올라간다
복잡성 은닉드러난 부분이 작을수록 쓰기 쉽고 문서화하기 쉽다

JavaScript에서 내부를 숨기는 수단은 네 가지다.

수단강제력자식 클래스비고
_name 관례없음(약속)접근 가능다른 언어의 protected 역할
#name private언어가 막음접근 불가클래스 본문 안에서만(class 문법)
클로저언어가 막음해당 없음팩토리 함수의 지역 변수(스코프와 클로저)
모듈 스코프언어가 막음해당 없음export하지 않은 것(모듈)

상속 계층이 내부를 공유해야 하면 _, 그 클래스만 알아야 하면 #을 쓴다.

그래서 JavaScript에서는

대부분의 OOP 이론과 패턴은 Java 전성기에 만들어졌다. 모든 것을 객체로 보고 타입과 인터페이스로 관계를 설계하는 방식이 JavaScript에 꼭 맞는 옷은 아니다.

  • 데이터와 메서드를 묶어 독립된 작은 부품으로 재사용하는 장점은 취한다.
  • 객체 사이 결합이 높아져 구조가 과하게 복잡해지는 것은 피한다. 굳이 객체일 필요 없는 부분은 함수형으로 쓴다.
  • 극단적으로 객체 지향을 배제할 필요도, 무겁게 설계할 필요도 없다. 두 관점 사이의 균형이 JavaScript다운 코드다.

정리

  • 객체 지향은 코드가 커지며 생긴 이름 충돌과 흩어진 데이터 문제를 "데이터 + 그 데이터를 다루는 함수"로 묶어 푼 관점이다.
  • 캡슐화·상속·추상화·다형성은 모두 부품 재사용을 위한 장치다.
  • 객체 지향도 은탄환이 아니어서 SOLID와 디자인 패턴이 뒤따랐다.
  • JavaScript는 클래스 대신 프로토타입, 타입 대신 덕 타이핑, 리스너 패턴 대신 일급 함수로 OOP를 풀었다. class는 그 위의 문법이다.
  • JavaScript에서는 객체 지향과 함수형 중 하나를 고르기보다 간결하고 바꾸기 쉬운 쪽으로 섞는다.

관련 노트: 객체 지향의 본질: 메시징, class 문법, 프로토타입과 상속, JavaScript 디자인 패턴: 생성 패턴, 프론트엔드와 SOLID 원칙, 함수형 프로그래밍, 소프트웨어 설계와 공학

원본 기록3

댓글

GitHub 계정으로 댓글을 남길 수 있어요.