고대 그리스 철학과 현대 프로그래밍이 만나는 신기한 접점을 발견한 글을 다시 정리했습니다.
결국 우리가 코드를 작성할 때, 2400년 전 철학자들이 고민했던 세계관을 디지털로 구현하고 있는지도 모른다는 생각을 했습니다.
이전에 작성했던 플라톤 철학과 OOP의 관계 글을 리팩토링 했습니다.
프로그래밍을 공부하다 보면 우연히 철학과 맞닿는 지점들을 발견할 때가 있습니다. 본래 의미인, 글쓰기부터 시작해서 어떠한 개념을 만드는 데 있어서 인문학적인 요소를 가져와 사용하는 경우가 더러 있습니다. 철학을 좋아했던, 문과인 저로써는 되게 신기한 경험이 되기도 합니다.
그 중 하나로 플라톤의 이데아론이 객체지향 프로그래밍(OOP)의 개념과 유사하다는 점을 들 수 있겠네요. 이 재밌는 부분이 이 글을 작성하게 했습니다.
객체 지향으로 개발하는 개발자들이 사실 2400년 전 아테네의 철학자가 제시한 세계관을 사용하고 있다는거죠.
플라톤(Plato, BC 427-347)은 고대 그리스의 철학자로, 서양 철학의 기초를 닦은 인물입니다.
그의 스승인 소크라테스의 가르침을 바탕으로 독창적인 철학 체계를 세웠고 그 중심에는 '이데아'가 있습니다.
Forms, εἶδος: eidos, ἰδέα: idea
현실 세계에 존재하는 모든 사물의 본질적이고 영원한 원형
플라톤에 따르면 우리가 감각으로 인식하는 현실 세계는 단지 이데아 세계의 불완전한 그림자일 뿐입니다. 예를 들어 우리는 '의자'라는 요소를 가진 물체를 보고 포괄적으로 '의자'라고 부를 수 있습니다.
다시 말해, 이 모든 의자들은 '의자'라는 추상적 개념의 부산물들이라고 할 수 있겠습니다.
이러한 각각 개별의 '의자'들은 '의자'의 이데아(원형)를 불완전하게 모방한 것 뿐입니다. 이 '의자 이데아'는 모든 의자가 갖춰야 할 본질적 속성을 완벽하게 담고 있는 영원한 형태입니다.
플라톤은 이를 두 개의 세계로 구분했습니다.
플라톤의 『국가』에 등장하는 '동굴의 비유'는 이데아론을 설명하는 가장 유명한 예시입니다.
동굴 안에 갇힌 사람들이 벽에 비친 그림자만을 보며 그것이 현실이라고 믿는 상황을 가정합니다.
여기서, 동굴 밖으로 나간 사람만이 진짜 사물을 보고 진실을 깨닫게 됩니다.
이 비유는 대부분의 인간이 감각 세계의 그림자(불완전한 복사본)만 보며 살고 있으며, 철학자만이 이데아(진정한 실재)를 볼 수 있다는 플라톤의 생각을 표현합니다.
뭔가 데미안의 아브락사스 얘기 같기도 하네요
이를 통해 플라톤은 인식론 및 정치 철학을 확립하기도 했습니다.
이제 플라톤의 이론을 알았으니 객체지향 프로그래밍으로 넘어가봅시다.
1960년대에 등장해 1980-90년대에 널리 보급된 프로그래밍 패러다임
프로그램을 상호작용하는 '객체'들의 집합으로 구성
더 자세한 내용은 OOP 글 참고
객체지향 프로그래밍의 핵심 개념은 아래와 같습니다.
이외에도 SOLID 설계법, 합성, 집약 등의 개념들이 있습니다.
이제 플라톤의 이데아론과 OOP 사이의 철학적 연결고리를 살펴보겠습니다. 혹자는 우연이라고 생각할 수 있지만, 그래도 연관성을 찾아보니 비슷한 부분들이 많아 클래스 측면에서 정리해봤습니다.
OOP에서 클래스는 객체가 가져야 할 속성(properties)과 행동(methods)을 정의합니다. 이는 플라톤의 이데아의 정의인 '사물의 본질적 형태를 규정'과 일치합니다.
Chair
클래스가 모든 의자 객체가 가져야 할 속성과 기능// 현대 프로그래밍의 '의자' 이데아
class Chair {
// 의자의 재질, 다리 개수 등
private material: string;
private legs: number;
constructor(material: string, legs: number) {
this.material = material;
this.legs = legs;
}
// 모든 의자는 무게를 지탱할 수 있어야 함
supportWeight(): boolean {
return true;
}
}
// 현실 세계에 존재하는 구체적인 의자들 (이데아의 불완전한 모방)
const woodenChair = new Chair("wood", 4);
const modernChair = new Chair("steel", 1);
woodenChair
와 modernChair
는 이데아로부터 파생된 현실 사물(Object), 즉 객체(Object)입니다.
객체(Object)는 클래스의 인스턴스로, 실제 메모리에 할당된 구체적인 실체입니다. 이는 플라톤 철학에서 현실 세계의 사물이 이데아의 불완전한 모방인 것과 유사합니다.
즉, 클래스 정의(이데아)는 추상적이지만, 객체(현실 사물)는 구체적이고 감각적으로 경험할 수 있습니다(코드가 실행될 때).
OOP에서 추상화(Abstraction)는 복잡한 실체에서 필수적인 특성만 추출하는 과정입니다.
플라톤의 철학에서도 이데아는 사물의 우연적 속성을 제거하고 본질적 속성만 남긴 추상적 형태입니다.
// 도형의 추상적 개념 (이데아)
abstract class Shape {
abstract calculateArea(): number; // 모든 도형은 넓이를 계산할 수 있어야 함
}
// 구체적인 도형들
class Circle extends Shape {
private radius: number;
constructor(radius: number) {
super();
this.radius = radius;
}
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
private width: number;
private height: number;
constructor(width: number, height: number) {
super();
this.width = width;
this.height = height;
}
calculateArea(): number {
return this.width * this.height;
}
}
위 코드에서 Shape
는 추상 클래스로, 모든 도형이 공유하는 본질적 속성(넓이를 계산할 수 있음)만 정의합니다. 이것이 바로 플라톤이 말한 이데아의 본질 추구와 같은 맥락입니다.
플라톤은 이데아들 사이에도 계층 구조가 있다고 보았습니다. 더 근본적인 이데아가 있고, 그보다 하위에 있는 이데아들이 있다고 생각했죠. 예를 들어, 플라톤은 '선의 이데아'는 모든 이데아들의 근본이고, 그 아래 '용기', '정의' 등의 이데아들이 위치해 있다고 생각했습니다.
이는 OOP의 상속 개념과 직접적으로 연결됩니다.
// '가구' 이데아 (상위 개념)
class Furniture {
protected material: string;
constructor(material: string) {
this.material = material;
}
getDescription(): string {
return `이 가구는 ${this.material}으로 만들어졌습니다.`;
}
}
// '의자' 이데아 (하위 개념이며 '가구'의 특성을 상속)
class Chair extends Furniture {
private legs: number;
constructor(material: string, legs: number) {
super(material); // 상위 이데아의 속성을 물려받음
this.legs = legs;
}
getDescription(): string {
return `${super.getDescription()} ${this.legs}개의 다리가 있습니다.`;
}
}
위 예시에서 Chair
클래스는 Furniture
클래스의 속성과 메서드를 상속받습니다. 이는 플라톤이 말하는 하위 이데아가 상위 이데아의 특성을 포함하면서 더 구체적인 형태를 띠는 것과 유사합니다.
이번엔 좀 더 철학적 측면인 플라톤의 이데아론과 OOP의 연관성을 더 깊이 살펴보겠습니다. 이에 대한 몇 가지 흥미로운 철학적 함의를 발견할 수 있었습니다.
- 형이상학: 존재의 근본 원리를 탐구하는 철학의 한 분야, 존재, 인식, 도덕 등의 근본적인 문제를 연구
- 형이하학: 형체를 갖춘 사물에 관한 학문으로, 구체적인 성질과 형태를 연구
결론부터 얘기하자면, OOP를 잘한다는 것은 그 클래스의 존재에 대한 의의와, 사용하려는 기능을 잘 활용할 수 있게끔 대한 성질 및 형태를 제대로 정의한다는 것입니다. 형이상학적인 설계와, 형이하학적인 기능과 쓸모를 다 해야한다는 얘기죠.
플라톤은 진정한 지식이란 이데아에 대한 지식 또는 이데아의 인식이라고 보았습니다. 그는 감각 세계의 사물들이 끊임없이 변하기 때문에, 그것들에 대한 지식은 불완전하고 참된 지식이 될 수 없다고 주장했습니다.
따라서 진정한 지식은 감각 경험을 넘어 이성을 통해 얻어지는 것이며, 이데아를 학습하고 관철하는 과정을 통해 도달할 수 있다고 생각했습니다.
OOP에서도 유사한 관점을 발견할 수 있습니다. 개발자들은
이런 식으로 기능을 구현하게 됩니다.
즉, 프로그램의 기본 구조와 동작 방식을 이해하려면 객체들이 아닌 클래스의 정의를 관찰해야 합니다.
플라톤 철학에서 이데아는 영원불변하지만, 현실 세계의 사물은 계속 변합니다. OOP도 그런 측면이 있죠.
class BankAccount {
private balance: number;
constructor(initialBalance: number) {
this.balance = initialBalance;
}
deposit(amount: number): void {
this.balance += amount;
}
withdraw(amount: number): boolean {
if (amount <= this.balance) {
this.balance -= amount;
return true;
}
return false;
}
}
// 계좌 객체의 상태는 계속 변하지만, BankAccount 클래스(이데아)는 변하지 않음
const account = new BankAccount(1000);
account.deposit(500); // 잔고: 1500
account.withdraw(200); // 잔고: 1300
위 코드에서 보듯이, BankAccount
는 계좌 기능의 원형으로서 작용하고 있습니다. 다시 말해, 클래스 정의는 프로그램이 실행되는 동안 변하지 않지만, 객체의 상태는 메서드 호출에 따라 계속 변합니다.
모든 프로그래밍 언어가 플라톤의 이데아론 모델을 따르지는 않습니다. 각자 패러다임을 취하는 방식이 다르기 때문입니다.
여기서 신기하게도 JS와 같은 프로토타입 기반 언어는 더 아리스토텔레스적인 접근을 취합니다.
아리스토텔레스는 플라톤의 제자였지만, 스승의 이데아론에 반대했습니다. 그는 형상(form)이 실체와 별개로 존재하는 것이 아니라, 실체 안에 내재한다고 봤습니다. 좀 더 형이하학적이죠?
마찬가지로 프로토타입 기반 언어에서는 클래스 없이 객체 자체가 다른 객체의 원형(prototype)이 됩니다.
// JavaScript의 프로토타입 기반 접근법
const chair = {
material: "wood",
legs: 4,
supportWeight: function() {
return true;
}
};
// 기존 객체를 기반으로 새 객체 생성
const modernChair = Object.create(chair);
modernChair.material = "steel";
modernChair.legs = 1;
이 방식에서는 추상적 '의자' 클래스(이데아)가 없습니다. 대신 구체적 의자 객체가 존재하고, 그것을 기반으로 새로운 의자 객체가 생성됩니다. 이는 아리스토텔레스가 말한 '개별 실체로부터의 귀납적 추론'과 맥락을 같이 합니다.
이처럼 프로그래밍 패러다임 간의 차이는 고대 철학자들의 논쟁을 반영하는 것 같기도 합니다 !
플라톤과 아리스토텔레스가 객체지향 등 프로그래밍 패러다임을 예견했다고는 할 수 없지만, 이것은 철학이 인간의 사고방식이 시대와 분야를 초월하는 개념이고, 이와 동시에 방법론적인 패러다임은 유사한 패턴을 따를 수도 있다는 것을 보여줍니다.
오히려 이렇게 아는 개념을 비유해 패러다임을 학습하니 쉽게 학습한 거 같기도 합니다.
이 학습을 통해서 프로그래밍 패러다임은 단순한 패턴이나 기술이 아니라 세계를 이해하고 구조화하는 철학적 행위라고 학습했습니다. 너무 웅장한 것 같기도 하네요.
또, 어쩌면 우리가 코드를 작성할 때, 우리는 2400년 전 아테네에서 이루어진 철학적 사유를 디지털 형태로 계승하고 있는지도 모릅니다.
다음에 클래스를 정의하거나 객체를 인스턴스화할 때, 아니면 그냥 코드를 작성할 때 잠시 멈추고 생각할 거 같습니다.
'지금 나는 이데아를 어떻게 표현하고 있는 것인가?'
좋은 글 잘 보고 갑니다