
⚡ 한 줄 요약: 객체지향을 만든 앨런 케이는 "핵심은 객체(클래스)가 아니라 메시징"이라고 못 박았다.
우리가 배운 OOP는 절반만 본 셈이다.
무슨 일인지
객체지향 프로그래밍(OOP)이라는 말을 만든 사람이자 스몰토크(Smalltalk) 언어의 아버지인 앨런 케이(Alan Kay)가, 2003년 한 메일에서 "당신이 생각하는 객체지향의 정의가 뭐냐"는 질문에 직접 답한 글이 다시 회자되고 있다.
그의 답은 우리가 면접에서 외우는 '캡슐화·상속·다형성' 3종 세트가 아니었다.
핵심만 추리면 이렇다.
"내게 OOP는 메시징, 상태-프로세스의 지역적 보존·보호·은닉, 그리고 모든 것의 극단적인 늦은 바인딩(late-binding), 이 세 가지만을 의미한다."
심지어 그는 이렇게 후회했다.
"오래전에 내가 'object(객체)'라는 용어를 만든 걸 사과한다.
그 단어 때문에 많은 사람이 덜 중요한 아이디어에 집중하게 됐다.
진짜 큰 아이디어는 'messaging(메시징)'이다."
배경 — '클래스'가 아니라 '세포'였다
여기서 스몰토크는 일상어 '스몰토크(잡담)'가 아니라, 1970년대 제록스 파크(Xerox PARC)에서 케이가 만든 프로그래밍 언어다.
이 언어의 모든 것은 객체끼리 메시지를 주고받는 것으로 동작한다.3 + 4조차 "3이라는 객체에게 + 4 메시지를 보낸다"로 해석된다.
케이의 영감은 컴퓨터 과학이 아니라 생물학이었다.
그는 객체를 살아있는 세포처럼 봤다.
세포는 내부 상태를 막(membrane)으로 철저히 숨기고, 오직 화학적 신호(메시지)로만 소통한다.
어떤 세포가 신호를 받을지, 어떻게 반응할지는 그 세포가 스스로 결정한다 — 이것이 '늦은 바인딩'이다.
| 우리가 강조하는 것 | 케이가 강조한 것 |
|---|---|
| 클래스/상속 구조 설계 | 객체 간 메시지 흐름 |
| 컴파일 타임의 타입 안정성 | 런타임의 극단적 늦은 바인딩 |
| 데이터를 가진 객체 | 상태를 숨기고 신호로만 반응하는 객체 |
개발자에게 주는 의미
이건 단순한 '용어 잔소리'가 아니다.
케이의 관점은 지금 우리가 쓰는 현대 아키텍처의 뼈대를 그대로 설명한다.
- 마이크로서비스: 서비스끼리 메서드를 직접 호출하지 않고 HTTP/메시지 큐로 메시지를 보낸다. 받는 쪽 구현은 몰라도 된다.
- 이벤트 기반 아키텍처·메시지 큐(Kafka, RabbitMQ): '누가 처리하는가'를 런타임으로 미루는 늦은 바인딩 그 자체.
- 느슨한 결합(loose coupling): 상속으로 단단히 묶인 클래스 트리보다, 메시지로 대화하는 독립 객체가 변화에 강하다.
요컨대 "상속으로 코드를 재사용한다"는 OOP 1세대 통념보다, "독립적인 단위들이 메시지로 협력하게 설계한다"는 발상이 케이의 원래 의도에 가깝다.
상속보다 합성(composition), 직접 호출보다 이벤트를 권하는 최근 흐름은 사실 50년 전 메일로의 회귀다.
실무 적용 — '호출' 대신 '메시지'로 짜보기
메서드를 직접 부르는 대신, 객체에게 메시지를 던지고 처리를 런타임에 위임하는 작은 패턴이다.
챗봇·핸들러 라우팅 등에 그대로 복붙해 응용할 수 있다.
// 객체에게 '메시지를 보낸다'는 발상 — 메서드를 직접 부르지 않는다
class Mailbox {
#handlers = new Map();
on(message, fn) { // 어떤 메시지에 반응할지 등록
this.#handlers.set(message, fn);
return this;
}
send(message, payload) { // 누가 처리할지는 런타임에 결정 (late-binding)
const fn = this.#handlers.get(message);
if (!fn) return { unhandled: message }; // 모르는 메시지는 무시 → 느슨한 결합
return fn(payload);
}
}
const chatbot = new Mailbox()
.on("greet", ({ user }) => `안녕하세요, ${user}님!`)
.on("summarize", ({ doc }) => doc.slice(0, 80) + "…");
chatbot.send("greet", { user: "민수" }); // 안녕하세요, 민수님!
chatbot.send("translate", { text: "hi" }); // { unhandled: "translate" } — 깨지지 않음
포인트는 두 가지다.
① 보내는 쪽은 누가 어떻게 처리하는지 모른다(은닉·늦은 바인딩).
② 모르는 메시지가 와도 시스템이 죽지 않는다(관용적 결합).
핸들러를 추가·교체해도 호출부 코드는 그대로다.
체크포인트
- 설계할 때 한 번 자문하기: "이 객체들이 서로 무슨 메시지를 주고받는가?" 클래스 다이어그램보다 메시지 흐름을 먼저 그려보면 결합도가 보인다.
- 상속이 답인지 의심하기: 코드 재사용이 목적이라면 상속보다 합성·이벤트 위임을 먼저 검토. 케이의 원래 OOP는 상속을 핵심으로 두지 않았다.
- 원문 한 번 정독 권장: 짧은 메일 한 통이지만, OOP를 보는 눈이 바뀐다. 정확한 정의는 아래 출처에서 직접 확인하자.
참고
'개발 인사이트' 카테고리의 다른 글
| 가로등 밑에는 버그가 없다 (0) | 2026.07.11 |
|---|---|
| AI는 개발자를 죽이지 않는다, 자비스처럼 '아이언맨'으로 만든다 (0) | 2026.07.02 |
| AI가 천재라는 말, 절반은 거짓말입니다 (0) | 2026.07.02 |
| 선형계획법으로 말 가두기, 생각보다 쉽다 (0) | 2026.06.29 |
| 메시징이 핵심이다 스몰토크가 말한 OOP (1) | 2026.06.28 |