[Javascript] 객체 지향 프로그래밍의 정의

2024. 8. 15. 12:00카테고리 없음

728x90

객체 지향 프로그래밍

객체 지향 프로그래밍을 설명하기 위해 현실 세계를 비유로 많이 든다.

 

현실 세계에 실재하는 대상, 예를 들어 책상, 의자, 노트북 등 실재하는 대상을 소프트웨어 세계에서 표현할 때 “객체”라고 표현한다.

 

현실 세계에서 인간의자에 앉아 책상 위에 있는 노트북을 한다고 해보자.

 

이를 소프트웨어 세계에서 표현한다면 “객체”는 인간, 의자, 책상, 노트북과 같이 실재하는 대상이 될 것이다.

 

또한 각 대상들은 다른 대상과 식별할 수 있는 고유한 속성을 가지고 있고 동작을 가지고 있다.

 

인간은 남들과 식별할 수 있는 이름, 키, 몸무게와 같은 속성을 가지고 있고 숨 쉬기, 걷기와 같은 동작을 가지

고 있다.

 

그리고 인간은 의자, 책상, 노트북과 같은 다양한 대상들과 유기적으로 연관되어 다양한 기능을 수행한다.

 

이렇게 현실 세계를 실재하는 대상들의 상호작용으로 표현해보았다.

 

이를 소프트웨어 세계의 방식으로 표현한 것을 객체 지향 프로그래밍이라고 한다.

 

이제 소프트웨어 세계로 넘어갔을 때 프로그래밍 방식으로 설명하기 위해 객체, 클래스, 인스턴스라는 개념이 나온다.

 

객체는 소프트웨어 세계에 구현할 대상이고 클래스는 대상을 구현하기 위한 설계도이고 인스턴스는 설계도에 의해 실재하는 대상이 된 객체이다.

 

프로그래밍 관점으로 설명한 것은 아래와 같다.

객체(Object)

실체.

 

클래스로 선언된 변수

클래스(class)

객체(Object)를 만들어내기 위한 틀.

 

내부에 속성과 메소드가 정의되어 있다.

인스턴스(instance)

객체가 메모리에 할당이 된 상태.

 

런타임에 구동되는 객체.

 

일반적으로 객체인스턴스는 따로 구분하지 않고 혼용해서 사용하는 경우도 많다고 한다.

 

자바스크립트 관점에서 객체, 클래스, 인스턴스를 확인해보자.

 

다음은 자바스크립트에서 표현한 객체이다.

const person = {
	age: 15,
	weight: 60,
	walk: ()=>{}
}

 

위 코드는 단순한 객체로 만든 것인데 이를 클래스로 표현하면 일종의 “틀”을 생성할 수 있다.

class Person = {
	#age
	#weight
	constructor(age, weight){
		this.#age = age;
		this.#weight = weight;
	}
	walk = ()=>{
	}
}

 

클래스라는 “틀”을 사용해서 인스턴스를 찍어낼 수 있다.

const person1 = new Person(15, 50);
const person2 = new Person(17, 80);

프로퍼티 property와 메소드 method

객체는 프로퍼티의 집합이다.

 

프로퍼티는 객체가 다른 객체와 식별할 수 있는 속성을 의미한다.

 

예를 들어 인간을 소프트웨어 세계의 객체로 표현한다면 키, 몸무게와 같은 속성들이 될 수 있다.

 

또한 자바스크립트에서 메소드는 callable한 함수로 되어있는 프로퍼티라고 표현할 수 있다.

 

이렇게 보면 메소드도 프로퍼티라고 볼 수 있으나 일반적으로 프로퍼티라고 표현하는 것은 동작이 아닌 속성인 경우가

많다.

 

이러한 관점을 기준으로 인간을 소프트웨어 세계의 객체로 표현해보자.

class person = {
	age: 15,
	weight: 60,
	walk: ()=>{}
}

 

위에서 객체 안의 age, weight, walk는 모두 프로퍼티라고 표현할 수 있고 조금 더 구체적으로 표현하면 age와 weight는 프로퍼티, walk는 메소드라고 부를 수 있다.

객체 지향 프로그래밍의 4가지 특성

 

추상화 (Abstraction)

OxfordLanguages에서 정의한 추상화는 다음과 같다.

 

사물이나 표상(表象)을 어떤 성질·공통성·본질에 착안하여 그것을 추출(抽出)하여 파악하는 것.

 

즉 객체 지향 프로그래밍에서 추상화는 공통적인 속성기능을 뽑아서 클래스의 프로퍼티메소드로 표현한 것이라고 볼 수 있다.

 

예를 들어 현실 세계의 인간을 소프트웨어 세계의 객체로 표현할 때의 과정을 생각해보자.

 

인간의 공통적인 속성인 나이, 몸무게와 같은 값들을 프로퍼티로 표현하고 걷기와 같은 기능들은 메소드로 표현했다.

 

그리고 인간마다 이러한 속성과 기능들은 공통적으로 가지고 있지만 다른 대상들과 식별할 수 있는 고유한 속성 값들을 가지고 있다.

 

이렇게 보면 추상화라는 것은 클래스라고 생각할 수 있지만 프로그래밍 관점에서 보통 추상화는 공통적인 속성들을 뽑아내어 구현을 하지 않고 정의만 하는 것을 말한다.

 

Java와 같은 언어는 자체적으로 abstract 혹은 interface를 사용하여 추상화를 구현할 수 있지만 Javascript는 자체적으로 이러한 기능을 구현하지 않는다.

 

Javascript에서 추상화를 구현하기 위해 프로그래머가 직접 처리해야 하는 부분이 있다.

 

현실 세계의 “동물”을 소프트웨어 세계의 Animal 클래스로 표현하려고 하는데 추상화를 적용해보면 다음과 같다.

 

“동물”의 공통적인 특성을 뽑아보자.

 

간단하게 “이름”“걷기”만 표현해보자.

class Animal{
	#name
	constructor(name){
		this.#name = name;
	}
	walk(){
		console.log("걷는 중");
	}
}

 

현실 세계의 “동물”을 소프트웨어 세계의 “클래스”로 표현해보았다.

 

이제 Animal을 상속해서 다양한 동물들을 표현할 수 있는데 한 가지 문제점이 있다.

 

추상화가 적용이 되어있지 않아서 Animal 객체를 생성할 수 있다는 점이다.

 

Animal에 추상화를 적용한다면 Animal 객체는 생성할 수 없고 Animal 객체를 상속한 Cat이나 Dog과 같은 객체를 생성할 수 있어야 한다.

 

Javascript에서 추상화를 구현하기 위해서 constructor와 method에서 Animal 객체의 생성과 메소드 사용을 막을 필요가 있다.

class Animal{
	#name
	constructor(name){
		if (this.constructor === Animal){
			throw new Error("This is a abstract class.");
		}
		this.#name = name;
	}
	walk(){
		throw new Error("This is a abstract class.");
	}
}

 

constructor에서 생성자가 상위 클래스라면 에러를 던지는 이유는 상위 클래스의 인스턴스 생성을 막기 위해서다.

 

상위 클래스의 메소드가 전부 에러를 던지는 이유는 하위 클래스의 메소드 구현을 강제하기 위해서다.

상속에 대해서는 아래에서 설명한다.

상속 (Inheritance)

현실 세계의 실재하는 대상을 “객체”로 표현할 때 공통적인 특성을 뽑아 클래스를 만들어보았다.

 

이 클래스로 다양한 인스턴스를 생성할 수 있는데 클래스를 세부적으로 나누고 싶을 수 있다.

 

Animal이라는 클래스를 생성하고 하위 클래스인 Cat과 Dog으로 나눌 수 있다.

 

만약 Cat을 종류를 기준으로 하위 클래스로 나눈다면 Cat을 상속받아 Persian, Siamese와 같은 하위 클래스를 만들 수도 있다.

 

이럴 경우 Cat과 Dog은 Animal을 상속받아 Animal의 프로퍼티와 메소드를 새로 정의할 필요없이 사용할 수 있다.

 

물론 하위 클래스의 고유한 속성을 만들 수도 있고 상위 클래스의 메소드를 새로 정의하여 사용할 수 도 있다.

 

하위 클래스가 상위 클래스의 메소드를 재정의하여 사용한다면 이를 메소드 오버라이딩이라고 한다.

 

위에서 설명한 추상화는 클래스에 다음 세 가지 제약을 걸어둔 것이라고 생각하면 된다.

  1. 상위 클래스는 구현을 하지 않고 정의만 한다.
  2. 상위 클래스는 직접적인 인스턴스를 생성할 수 없다.
  3. 하위 클래스는 상위 클래스를 상속받아 메소드를 오버라이딩 해야 한다.

다형성 (Polymorphism)

다형성은 맥락에 따라서 객체의 속성이나 기능이 다양한 역할을 하는 것을 의미한다.

 

상속에서 살펴 본 메소드 오버라이딩 또한 다형성 특성을 가지고 있다.

 

또한 다형성은 상위클래스 타입의 참조변수로 하위클래스 객체를 참조하는 것이라고 볼 수 있다.

 

자바와 같은 변수마다 타입이 필요한 언어의 경우 하위 클래스로 생성한 인스턴스를 상위 클래스의 타입으로 표현이 가능하다.

 

예를 들어 자바에서 Animal이라는 상위 클래스를 상속받은 Cat이라는 하위 클래스가 있다고 하면 다음과 같이 표현이 가능한 것이다.

Animal cat = new Cat();

 

Cat 클래스로 생성한 인스턴스이기 때문에 Cat 타입으로 선언하는게 일반적이나 상위 클래스인 Animal 타입으로도 사용이 가능하다.

 

이를 다형성이라고 한다.

 

하지만 자바스크립트에서는 자바와 다르게 타입이 동적으로 할당되기 때문에 다형성을 직접적으로 지원해주는 문법이 존재하지 않는다.

캡슐화 (Encapsulation)

캡슐화는 클래스 내부에 정의된 속성과 기능들을 외부에서 무분별하게 변경하는 일을 막아 보호하고 오직 허용된 데이터에만 접근할 수 있게 제한하는 것이다.

 

클래스 내부 프로퍼티나 메소드에 private 접근 제한자를 설정하여 외부 노출을 막을 수 있다.

 

자바스크립트의 경우 “#”을 사용하여 private 접근 제한자를 사용할 수 있다.

class Animal{
	#name
	constructor(name){
		this.#name = name;
	}
}

 

Animal 클래스의 name 프로퍼티는 private 접근 제한자로 설정이 되어 있어서 외부에서 name 프로퍼티에 접근할 수 없다.

728x90