📌 객체 지향 프로그래밍

자바스크립트를 처음 배울때 책이나 강의에서 객체 지향 프로그래밍이라는 말이 자주 등장한다. 하지만 처음 공부를 시작할 때 변수, 데이터 타입 등은 이해를 해도 객체 지향 프로그래밍이라는 단어는 감이 잘 안왔던 내 경험을 토대로 우선 객체 지향 프로그래밍에 대하여 정리해보자 한다.

JS는 명령형, 함수형, 프로토타입 기반 객체지향 언어이다. 자바스크립트는 원시 값을 제외하고 거의 모든 것이 객체로 이루어져 있다. 객체 지향 프로그래밍이란 여러개의 독립적 단위, 즉 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임이다.

객체 지향 프로그래밍의 장·단점


장점설명
재사용성상속을 통해 프로그래밍시 코드의 재사용을 높일 수 있음
생산성 향상잘 설계된 클래스를 만들어 독립적인 객체를 사용함으로써 개발의 생산성 향상
유지보수의 우수성캡슐화를 통해 주변 영향이 적어 유지보수가 쉽다

단점설명
개발 속도가 느림객체를 처리하려는 것에 대한 정확한 이해가 필요
실행 속도가 느림객체지향언어는 대체로 실행속도가 느리다
코딩난이도 상승다중 상속과 같은 이유로 복잡도 상승

객체 지향 언어의 특징

  • 캡슐화

    데이터와 코드의 형태를 외부로부터 알 수 없게 하고, 데이터의 구조와 역할, 기능을 하나의 캡슐 형태로 만드는 방법 (정보 은닉)

  • 추상화

    다양한 속성 중 프로그램에 필요한 속성만 간추려 표현하는 것

  • 상속화

    부모 클래스에 정의된 변수 및 메서드를 자식 클래스에서 상속받아 사용하는 것

  • 다형화

    상속과 연관이 있는 개념으로 한 객체가 다른 여러형태(객체)로 재구성 되는 것


객체 생성 방법

Obejct 생성자 함수

new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수를 말한다. 생성자 함수에 의해 생성된 객체를 인스턴스라 한다.

// 빈 객체의 생성
const person = new Object(); // {}
// 자바스크립트는 Object 생성자 함수 이외에도 
//String,Number,Boolean,Function,Array,Date,RegExp,Promise 등의 빌트인 생성자 함수를 제공
const strObj = new String('abc');
const numObj = new Number(123);
const boolObj = new Boolean(true);
const func = new Function('x','return x * x');
const arr = new Array(1,2,3);
const regExp = new RegExp(/ab+c/i);
const date = new Date();

생성자 함수

객체 리터럴에 의한 객체 생성 방식은 직관적이고 간편하지만 단 하나의 객체만 생성한다. 따라서 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 비효율적이다. 생성자 함수에 의한 객체 생성 방식은 마치 객체(인스턴스)를 생성하기 위한 템플릿(클래스)처럼 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다.

function Circle(radius){
	//생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가르킨다.
  	this.radius = radius;
  	this.getDiameter = function(){
    	return 2 * this.radius;
    }
}

const circle1 = new Circle(5) //반지름이 5인 Circle 객체를 생성
const circle2 = new Circle(10) //반지름이 10인 Circle 객체를 생성

즉 생성자 함수란 new 연산자와 함께 인스턴스를 생성하는 함수이다. new 연산자가 없다면 생성자 함수는 일반 함수로 동작한다.


📌 Class 문법의 등장

자바스크립트는 프로토타입 기반 객체지향 프로그래밍 언어이다. 자바스크립트에는 class라는 개념이 존재하기 않았기 때문에 프로토타입이라는 객체를 활용하여 class처럼 표현하기 위해 사용한다고 볼 수 있다. ES6에서 class문법이 추가되었다. 하지만 생김새만 클래스 구조이고, 엔진 내부적으로는 프로토타입 방식으로 작동된다.

class 선언

class Person {
	  
 	height = 180; // 인스턴스 변수

  	//constructor는 이름을 바꿀 수 없다.
 	constructor(name,age) {
      	//this는 생성할 인스턴스를 가르킴
  		this.name = name;
    	this.age = age;
  	}
}
let personal = new Person('park',26);
console.log(personal.name); //park
console.log(personal.age);	//26
console.log(personal.height); //180

constructor는 인스턴스를 생성하고 클래스 필드를 초기화하기 위한 특수 메서드

class 메서드 정의

class Calculator {
	add(x,y) {
      return x+y;
    }
}

let calc = new Calculator();
calc.add(5,6) // 11

class 상속 / extends 키워드

class Parent {
  // ...
}

class Child extends Parent {
  // ...
}

extends키워드는 클래스를 다른 클래스의 하위 클래스로 만들기 위해 사용
extends키워드를 통해 child 클래스가 parent 클래스를 상속했다.
위 관계를 '부모 클래스-자식 클래스 관계' 혹은 '슈퍼 클래스(superclass)-서브 클래스(subclass) 관계'라고 한다.

클래스를 상속받을 경우

  • 자식 클래스 A를 통해 부모 클래스 B의 정적 메소드와 정적 속성을 사용할수 있다.
  • 부모 클래스 B의 인스턴스 메소드와 인스턴스 속성을 자식 클래스 A의 인스턴스에서 사용할 수 있다.

클래스 상속 / super 키워드

부모 클래스의 값을 상속받고, 추가적으로 자신만의 값을 사용하고 싶다면 super키워드를 사용할 수 있다.

class Pet {
    constructor(name, age) {
        console.log('IN PET CONSTRUCTOR!')
        this.name = name;
        this.age = age;
    }
    eat() {
        return `${this.name} is eating!`
    }
}

class Cat extends Pet {
    constructor(name, age, livesLeft = 9) {
        console.log('IN CAT CONSTRUCTOR!')
        super(name, age)
        this.livesLeft = livesLeft;
    }
    meow() {
        return 'MEOWWWW'
    }
}

const monty = new Cat('monty',9);
// IN CAT CONSTRUCTOR!
// IN PET CONSTRUCTOR!

console.log(monty); // Cat {name: 'monty', age: 9, livesLeft: 9}

📌 모듈화

최근들어 프론트엔드 프로젝트의 규모가 커짐에 따라 자바스크립트 코드를 여러 파일과 폴더에 나누어 작성하고 서로가 서로를 효율적으로 불러올 수 있도록 해주는 시스템의 필요성이 높아졌다.
이에 따라 ES6에서 모듈 시스템이 추가되었다.

script 태그에 type="module" 어트리뷰트를 추가해주면, 이 파일은 모듈로서 동작한다.

<script type="module" src="index.mjs"></script> 
<!--확장자로는 대게 'mjs'가 사용된다.-->

모듈 스코프

모듈 내부의 가장 바깥 스코프에서 이름을 선언하더라도, 전역 스코프가 아니라 모듈 스코프에서 선언된다. 모듈 스코프에 선언된 이름은 (export 하지 않는다면)해당 모듈 내부에서만 접근할 수 있다. 따라서 여러 모듈의 가장 바깥쪽에서 같은 이름으로 변수, 함수, 클래스를 선언하더라도 서로 다른 스코프에서 선언되기 때문에 이름의 충돌이 생길 일이 없다.

Function 형태의 모듈화

//index.js
import FOO from 'foo.js';

let FooComponent = Foo();
console.log(FooComponent); // 'Hello module!'
//foo.js
export default function Foo(){
	return 'Hello module!'
}

Class 형태의 모듈화

//index.js
import FOO from 'foo.js';

let FooComponent = Foo();
console.log(FooComponent.render()); // 'Hello module!'
//foo.js
export default class Foo(){
	render(){
    	return 'Hello module!'
    }
}

Import & export

모듈은 exportimport를 사용해 가져오기, 내보내기가 가능하다. (변수, 함수, 클래스)

  • export를 통해 여러 모듈에서 재사용이 가능하다.

  • 선언과 동시에 export를 붙여주면 선언과 export를 한꺼번에 가능

export const spam = 'eggs';
export function add(x, y) {
  return x + y;
}
  • default export 구문을 통해, 모듈을 대표하는 하나의 을 지정하고 그 값을 다른 모듈에서 편하게 불러와서 사용이 가능하다.

  • export 혹은 import 하는 이름의 뒤에 as를 붙여서, 다른 이름이 대신 사용되게 할 수 있다.

const foo = 'bar';
export { foo as FOO }; // FOO 라는 이름으로 export 된다.

import { Component as Comp } from 'react'; // Comp라는 이름으로 import 된다.

📌 참고 자료

https://poiemaweb.com/js-object-oriented-programming
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes
https://radait.tistory.com/4
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-ES6-Class-%EB%AC%B8%EB%B2%95-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC
https://helloworldjavascript.net/pages/293-module.html

profile
프론트엔드 개발자가 되겠습니다🔥

1개의 댓글

comment-user-thumbnail
2023년 4월 11일

안녕하세요, 제로베이스 프론트엔드스쿨 멘토입니다. 작성해주신 글 잘 읽었고, 앞으로의 더 나은 블로깅을 응원하는 마음에서 작은 의견을 남기고 갑니다 :)

  • 전체적으로 정말 잘 이해하고 잘 작성해주셨습니다. 'Class로 모듈화 해서 export/import해서 사용하는 방법'부터 학습하면 사실 전체 개념을 알기가 어려운데, 처음부터 한 단계씩 잘 풀어서 설명해주셔서 잘 이해하고 계신다는 느낌이 들었습니다.
  • minor) 글 제목에 Javascript 키워드를 추가해주는건 어떨까요?
  • minor) 객체 지향 프로그래밍 개념을 따로 포스팅해주는건 어떨까요? 객체 지향 프로그래밍 개념이 대학 정규 과정에서 6개월동안 배울 정도로 많은 내용이라서, 좀더 깊에 따로 작성해주셔도 좋을 것 같아서 말씀드려봅니다.

감사합니다~!

답글 달기