Javascript와 OOP는 잘 맞을까?

곽태민·2023년 3월 24일
0

TIL

목록 보기
52/63

개요


Express로 개발하면서 TypeScript로 OOP 개발을 하고 있다. 하면서 이 둘은 잘 맞는지 의구심이 들어서 정리를 하게 되었다. Class도 알겠고, OOP도 알겠는데 JavaScript에서는 어떻게 해야할지 감이 잘 잡히지 않았다.

JavaScript에서 객체 지향 프로그래밍

JavaScript도 객체 지향 패러다임의 영향을 받았다. 하지만 JavaScript를 설계한 사람은 객체 지향 프로그래밍에 대한 시선이 썩 좋지는 않았다. 그래서 객체 지향 개념은 가져오지만 Java와는 다른 방식으로 OOP를 풀어나가게 된다.

JavaScript는 설계자의 철학도 철학이지만 웹 브라우저에서는 복잡한 언어를 만들 생각이 없었다. 그저 간단한 script 언어면 될 거라 생각을 했다. 그래서 Class 설계, 추상화나 다형성을 만들고 싶지 않았다.

하지만 당시 인기있던 Java 개발자 유입을 위해서 Java 문법과 패러다임은 최대한 유지를 하고자 했다. 그래서 Class가 없는 함수형 언어를 기반으로 하되 객체 지향 프로그래밍 맛을 느낄 수 잇는 언어가 됐다.

JavaScript 최초 설계는 어떻게 했을까?

OOP와 Class는 복잡해서 최대한 간단하게 만들고자 했지만 그러면서도 객체 지향처럼 상속, 추상화, 다형성을 할 수만 있다면 괜찮다는 목적을 가지고 JavaScript 최소 설계를 어떻게 했을지 정리를 해보려고 한다.

Class가 없는데 객체는 어떻게 만들까?

Class 없이 바로 Object를 생성할 수 있게해서 JavaScript는 No Class 언어로하고, Java처럼 dog.name, dog.age 이렇게 객체 문법을 쓸 수 있다.

const dog = {
	name: '강아지',
	age: 2;
};

console.log(dog.name);
console.log(dog.age);

Type이 없이 객체가 가진 메소드 동작 방법

Java와 비슷하게 객체에 함수를 정의해서 this를 넘겨준다.

const dog = {
	name: '강아지',
	age: 2,
	speak: function() { console.log('알알알', this.name, this.age) }
};

dog.speak();

상속, 추상화, 다형성 하는 법?

상속은 이미 만들어진 값들을 받아서 쓰는 걸로 Class가 아니라 Object로 받아오면 가능하고, 값이 있으면 해당 Class를 쓰고 없으면 부모 Class의 값을 쓴다면 같다. (상속을 받는게 아니라 없으면 찾아간다는 식)

const animal = {
	name: '',
	age: 0,
	sleep: function() { console.log('sleep... zzz', this.name) },
	speak: function() { console.log('...', this.name) }
};

const dog = {
	name: '강아지',
	age: 1,
	speak: function() { console.log('알알알', this.name, this.age) }
};

// 상속을 받는 것 같지만 아니며, prototype 연결이 된다.
dog.__proto__ = animal;

newObj.sleep();  // dog에는 sleep이 없으니 animal에서 sleep 호출 _ 상속
newObj.speak();  // dog에 있는 method이니 본인의 speak호출 - 다형성

Class와 new 없이 객체를 생성하기

설계자는 Class를 안 넣고 싶어서 function으로 해결을 했다. prototype을 통해서 정리를 해서 class 없이도 객체 지향을 할 수 있게 했다.

function Dog(name, age) {
	this.name = name;
	this.age = age;
}

Dog.prototype.speak = function() { console.log('알알알', this.name, this.age) };

const dog = new Dog('강아지', 2);
dog.speak();

위와 같이 Class가 없어도 object에 prototype을 연결하는 방식으로 객체 지향의 상속, 추상화, 다형성을 구현했다. 그리고 이런 객체를 바탕으로 Object, String, Number, Function, Array 등 객체 지향의 개념을 부여한 기본 라이브러리도 만들었다.

이러한 라이브러리를 만들어서 class 없이 객체 지향 언어를 사용하는 느낌으로 코드를 짤 수 있는 언어가 됐다.

Class가 없이 객체 지향이 가능할까?

당시에 class없이 프로그래밍을 한다는 것은 개발하기 힘들었다. 그래서 JavaScript 출시 초반에는 수준 낮은 언어로 폄하를 당했다. 브라우저 성능의 한계, 언어의 단순한 구성 ( 당연히 있어야할 Class가 없음.) 으로 인해서다.

class가 없었기 때문에 당시에는 class처럼 코딩하기 위해서 라이브러리들이 엄청 생겨났다. 결국에는 제작자의 의도와 관계 없이 가장 많이 요구하던 문법 기능은 class여서 ES6에서는 Class가 정식 문법이 됐다.

하지만 ES6의 class는 JavaScript 객체 지향의 근간인 prototype 방식을 문법적으로 class 처럼 보이게 만들어준 도구에 불과했다.

JavaScript에는 Type과 Interface가 없다?

JavaScript는 Type으로 인한 복잡성을 추구하지 않아서 객체의 Type을 따지지 않는다. 같은 이름의 변수, method를 가지고 있으면 같은 Type의 객체로 사용할 수 있다.

이를 통해 복잡한 객체 지향 프로그래밍의 설계를 복잡한 Type 정의와 상속을 통해서 Interface를 맞추지 않고 간단하게 만들 수 있다.

물론 Type을 기반으로 하는 설계가 중요한 전통 언어의 시작으로 보기에는 어딘가 조잡해 보여서 TypeScript가 생겼다.

결론

Javascript는 결국 완벽하게 객체 지향을 지향하지 않았기 때문에 이러한 개념들이 다른 객체 지향 언어의 영향을 끼친거 같다. JavaScript는 타 언어에 비해 논란이 많았지만 초기 설계 중 그래도 함수가 1급 객체라는 것이다.

JavaScript에서 객체 지향 개념으로 재사용성을 높이면서 장점을 누리긴 하되, 객체들의 결합이 높아져서 프로그램이 과도하게 복잡하지 않도록 굳이 객체로 만들지 않아도 될 부분들은 함수로 대체해도 될 것 같다.

코딩에는 정답이 없다고 생각하여 요즘 트렌드는 객체 지향이다 해서 따라갈게 아니라 간단하면서 가독성이 좋고, 규모가 커져도 유지보수하기 좋으며, 재사용이 편한 코드를 짜내는게 중요할 거 같다.

profile
Node.js 백엔드 개발자입니다!

0개의 댓글