[TIL] JS에서 객체 지향 프로그래밍(OOP)

lmimoh·2022년 9월 21일
0

TIL

목록 보기
11/26
post-thumbnail

객체지향 프로그래밍이란?

객체 지향 프로그래밍은 하나의 모델이 되는 청사진(Class) 을 토대로 객체(Instance) 를 만들어내는 프로그래밍 패턴(개발 방법론)을 의미한다.

이를 자동차 생산 공장을 예시로 들었을 때, 청사진은 자동차의 기본적인 설계도 를 의미한다.

이는 자동차가 기능하기 위한 세부 부품들(바퀴, 좌석, 엔진)에 대한 기본적인 설정 을 가지고 있다.

이러한 청사진(Class) 를 토대로 색깔이 다르거나, 스펙이 상이한 다양한 자동차 모델들(Instance) 가 생산되게 된다.

또한, OOP는 프로그램 설계 철학 중 하나라고 할 수도 있는데 이는 데이터의 접근 및 처리 과정에 대해 모형을 만들어내는 방식으로 모든 것을 객체로 그룹화한다.

특히, 클래스는 일종의 원형 (Instance object의 원형)으로, 해당 상태에서 생성자 함수를 통해 속성이 부여하여 객체(Instance)를 만들어 낸다.


Objacet Oriented Programming의 주요개념

OOP는 4가지 주요 개념을 통해 코드의 재사용성을 극대화시킬 수 있다.

1. 캡슐화

데이터와 기능을 따로 정의하는 것이 아닌 하나의 객체로 묶는 것(느슨한 결합)

마우스를 예시로 들었을 때 다음과 같다.

// 개별적인 변수와 함수들로 mouse의 동작을 표현했을 때
// 개별 변수 mouse 생성
const mouse = [x, y];

// 개별 함수 move... 과 click... 생성
const moveMouse = (x, y) => { //마우스를 움직이는 함수 };
const clickMouse = (obj) => { //마우스 클릭을 동작시키는 함수 };
  
// mouse의 위치 변경 및 클릭 실행
mouse = moveMouse(0, 100);
clickMouse(mouse);
  
// OOP를 통해 마우스를 class와 instance로 생성했을 때
class Mouse() {
  cunstructor() {
    //마우스의 초기상태 설정
    this.x = 0;
    this.y = 0;
    this.status = 'normal;
  }
  
  move(x, y) { //마우스를 움직이는 메서드 }
  func(status) { //마우스 status를 변경하는 메서드 }   
}
    
// Mouse 클래스를 통해 객체 mouse1 생성
const mouse1 = new Mouse();
// 메서드를 통해 마우스 동작
mouse1.move(0, 100);
mouse1.func('click);

// Mouse 클래스 재사용 가능
const mouse2 = new Mouse(); // mouse1 != mouse2

또한, 캡슐화는 은닉화의 특징도 일부 포함한다. 이는 캡슐 내부에 중요 속성들을 감추고, 외부에서 이용되는 기능들만을 노출시키는 것을 의미한다.

즉, 내부의 속성들은 외부에서 접근하기 어려우므로 데이터의 변경에 의한 영향을 최소화시킬 수 있다.

2. 상속

상속은 기본클래스의 속성과 메서드를 파생클래스가 물려받는 것을 의미한다.
이때, this는 해당 클래스를 / super는 기본 클래스를 의미한다.

예시로, 사람이라는 기본클래스에 학생이라는 파생클래스가 존재하는 경우

class Person {
  constructor(gender, age) {
    console.log('Person 생성자 동작');
	this.gender = gender;
	this.age = age;
  }
}
  
class Student extends Person {
  constructor(gender, age, grade) {
    super(gender, age);
    console.log('Student 생성자 동작');
	this.grade = grade;
  }
  
  study() {}
}

const mimohh = new Student('m', 24, 3);
// mimohh = { gender : 'm', age : 24, grade : 3 , ...}

이때, 만약 상속한 파생 클래스에 생성자가 존재하지 않는 경우 JavaScript는 자동으로 빈 생성자를 생성하고 기본 클래스의 생성자가 먼저 동작한 뒤 파생 클래스의 생성자가 동작합니다.

3. 추상화


Class와 Instance?

Instance object를 생성하기 위한 설계도를 Class라고 부른다.

과거 ES5에서는 function의 형태로 OOP를 구현하고자 했으나, ES6에서 'Class'라는 키워드가 생겨나게 되었고 현재는 Class를 주로 사용한다.

ES6 이전에 Class를 구현하는 방식은 다음과 같다.

//생성자 생성
function Car (color, engine, wheel) {
  // 클래스의 전달인자로 들어온 세부 설정을 세팅한다.
  this.color = color;
  this.engine = engine;
  this.wheel = wheel;
};

// 클래스의 매서드를 구현하기 위해 prototype을 사용한다.
Car.prototype.drive() {
  console.log('주행을 시작합니다...');
}

let avante = new Car('black', 'normal', 'normal'); // instance 객체 생성
avante.engine; // normal
avante.drive(); // 주행을 시작합니다...

ES6를 이용한 Class 구현은 다음과 같다.

class Car {
  //생성자 생성
  constructor(color, engine, wheel) {
    this.color = color;
    this.engine = engine;
    this.wheel = wheel;
  }
  
  drive() {
    console.log('주행을 시작합니다...');
  }
}

let avante = new Car('black', 'normal', 'normal'); // instance 객체 생성
avante.color; // black
avante.drive(); // 주행을 시작합니다...

이처럼 ES6 문법부터는 'class' 키워드를 사용하여 클래스를 생성하며, 이때 class 내부의 생성자(constructor)가 초기에 동작하게 된다.

또한, 'new'키워드를 통해 생성된 각각의 인스턴스 객체는 클래스의 고유한 속성과 매서드를 가지게 된다.

이때, this라는 키워드는 인스턴스 객체를 의미 하는데 생성자 내부의 'this.color = color;'과 같은 코드는 전달인자로 넘어온 설정값을 인스턴스 객체에 설정하는 것을 의미한다.


화살표 함수가 지양되는 이유?

Class를 통해 새로운 Instance object를 생성되어 생성자 함수가 실행될 때, 생성자는 'this' 키워드를 사용하여 전달인자를 객체에 설정 하게 된다.

그러나, 화살표 함수는 자신을 가리키는 this가 존재하지 않기 때문에 화살표 함수를 둘러싸는 렉시컬 범위의 this가 사용되게 된다.

이는 화살표 함수가 일반적인 변수의 조회 규칙을 따르기 때문이며, 현재 범위에서 존재하지 않는 this를 찾기 위해 바깥 scope를 탐색하게 되는 것이다.

즉, 화살표 함수가 사용되는 경우, 'this' 키워드가 의미하는 대상이 생성된 Instance object가 아닐 수 있다는 의미이다.

이는 프로그래밍 과정에서 개발자가 의도한 상황을 벗어나 코드가 동작할 수 있음을 의미하므로, 객체 지향 프로그래밍(OOP)에서 화살표 함수의 사용은 지양된다.

function Person(gender, age) {
  this.gender = gender;
  this.age = age;
};

Person.prototype.info = () => {
  console.log(this.gender);
  console.log(this.age);   
};

const man = new Person('m', 24);
man.info(); // undefined

profile
성장하는 개발자, 이민훈입니다.

0개의 댓글