S2_U2_CH1. 객체 지향

Judevv·2023년 5월 11일
0

Chapter 1. 객체 지향

학습 목표

  • 클로저 모듈 패턴에 대해 설명할 수 있다.
  • 클래스와 인스턴스에 대해 설명할 수 있다.
  • 클래스 문법을 이용할 수 있다.

1-1. 클로저 모듈 패턴

  • 메서드 호출은 객체.메서드()처럼 객체 내에서 메서드를 호출하는 방법을 의미
    • 메서드는 함수와 유사하지만, 객체 지향 프로그래밍에서는 클래스에 속한 함수를 메서드라고 함
  • 메서드 호출 방식
    • 정적 바인딩 방식(static binding)

      • 컴파일 시점에 호출할 메서드가 결정됨

      • 컴파일러가 변수의 타입을 분석하여 호출할 메서드를 결정!

      • 실행 속도가 빠르고, 오류를 미리 잡을 수 있으나 다형성을 제대로 활용하지 못함

        			컴파일 : 소스 코드를 기계어로 변화하는 과정
        			컴파일러 : 소스 코드를 읽고, 구문 분석과 의미 분석을 수행하여, 오류 검출 -> 중간 코드를 생성하고 최적화 -> 기계어 코드 생성
        			다형성 : 객체 지향 프로그래밍에서 코드의 재사용성과 확장성을 높이는 중요한 기법, 상속과 인터페이스를 활용하여 다형성 구현
    • 동적 바인딩 방식(dynamic binding)

      • 실행 시점에 호출할 메서드 결정됨
      • 변수의 실제 타입을 확인하여 호출할 메서드 결정
      • 다형성을 제대로 활용할 수 있으나, 실행 속도가 느리고, 오류가 발생할 가능성이 있음
// 예시
let Counter = (function() {
  // 비공개 멤버
  let count = 0;
  
  // 공개된 멤버 객체를 반환하는 함수
  function getCount() {
    return count;
  }
  
  function incrementCount() {
    count++;
  }
  
  function decrementCount() {
    count--;
  }
  
  // 공개된 멤버 객체
  return {
    getCount: getCount,
    incrementCount: incrementCount,
    decrementCount: decrementCount
  };
})();

console.log(Counter.getCount()); // 0
Counter.incrementCount();
console.log(Counter.getCount()); // 1
Counter.decrementCount();
console.log(Counter.getCount()); // 0
  • Counter 변수는 즉시 호출 함수 표현식(IIFE, Immediately Invoked Function Expression)으로 선언
    • 즉시 호출 함수 표현식 : 함수를 정의하고 바로 호출하는 표현식, 함수 내부에서 변수 등을 선언하여 스코프를 제한하거나, 모듈 패턴을 구현하는 등의 목적으로 사용
  • 이 함수는 비공개 멤버인 count 변수와 공개된 멤버 객체를 반환하는 클로저를 생성
  • 클로저를 통해 외부에서는 count 변수에 직접 접근할 수 없으며, 공개된 멤버 객체를 통해서만 카운터를 조작할 수 있음
// 클로저를 이용해 매번 새로운 객체 생성 예제
function createPerson(name) {
  let person = {
    getName: function() {
      return name;
    },
    setName: function(newName) {
      name = newName;
    }
  };
  return person;
}

let person1 = createPerson('Alice');
console.log(person1.getName()); // Alice

let person2 = createPerson('Bob');
console.log(person2.getName()); // Bob

person1.setName('Carol');
console.log(person1.getName()); // Carol
console.log(person2.getName()); // Bob
  • createPerson 함수는 매개변수 name을 받아서 이름을 가진 객체를 생성하는 클로저를 반환
  • 이 클로저는 getName 메서드와 setName 메서드를 포함하고 있으며, 이들 메서드는 name 변수에 접근할 수 있음
  • createPerson 함수를 호출할 때마다 매번 새로운 클로저가 생성되므로, person1과 person2 객체는 각자 독립적인 name 변수를 가지고 있음
  • person1.setName('Carol')을 호출하여 person1 객체의 이름을 변경하였지만, person2 객체의 이름은 변경되지 않았음
  • 클로저를 이용하면, 각 객체를 독립적으로 다룰 수 있습니다.

1-2. 클래스와 인스턴스

  • 객체 지향 프로그래밍은 하나의 모델이 되는 청사진(blueprint)을 만들고, 그 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴!

  • 클래스는 객체를 만들기 위한 일종의 설계도나 틀

    • 객체가 가져야 할 속성(attribute)과 행동(behavior)을 정의
    • 객체를 생성하기 위해서는 먼저 클래스를 정의하고, 이를 기반으로 객체 생성
  • 인스턴스는 클래스를 기반으로 생성된 구체적인 객체

    • 틀을 바탕으로 만들어진 실체
    • 클래스에서 정의된 속성과 행동(메서드)을 가지고 있고, 이를 이용해 원하는 작업을 수행할 수 있음
    • 인스턴스를 생성하기 위해서는 new 키워드 사용
      • 즉시 생성자 함수가 실행되고, 변수에 클래스의 설계를 가진 새로운 객체(인스턴스) 할당
      • 각각의 인스턴스는 클래스의 고유한 속성과 메서드를 가짐
  • ES5와 ES6에서의 클래스

    • ES5 : 함수로 정의할 수 있음
function Animal(name, age, species){
    // 인스턴스가 만들어 질 때 실행되는 코드
}
  • ES6 : class라는 키워드를 이용해서 정의
    class Animal {
    	constructor(name, age, species) {
      // 인스턴스가 만들어질 때 실행되는 코드
        }
      }
  • 용어들
    • prototype : 모델의 청사진을 만들 때 쓰는 원형 객체(original form)
    • constructor : 인스턴스가 초기화될 때 실행하는 생성자 함수
    • this : 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행 context(execution context), new 키워드로 인스턴스를 생성했을 때에는, 해당 인스턴스가 바로 this의 값이 됨
  • 예시
    • 동물을 클래스로 정의하고, 각각의 동물은 인스턴스로 표현될 수 있음
    • 동물 클래스는 이름(name), 나이(age), 종(species) 등의 속성을 가지고 있을 수 있으며, 움직인다(move), 소리를 내다(makeSound) 등의 행동을 정의할 수 있음
    • 이를 바탕으로 '강아지'와 '고양이'라는 두 개의 인스턴스를 생성할 수 있으며, 각각의 인스턴스는 이름, 나이, 종 등의 속성을 가지고 있으며, 움직이거나 소리를 낼 수 있음
class Animal {
  constructor(name, age, species) {
    this.name = name;
    this.age = age;
    this.species = species;
  } // 동물을 정의 하는 클래스
  // name, age, species 속성
  // constructor 은 생성자 함수 - return 값을 만들지 않음

  move() {
    console.log(this.name + ' is moving.');
  } // 행동

  makeSound() {
    console.log(this.name + ' is making a sound.');
  }
} // 행동

const dog = new Animal('doggy', 3, 'poodle'); // 인스턴스
dog.move(); // 출력: doggy is moving.
dog.makeSound(); // 출력: doggy is making a sound.

const cat = new Animal('kitty', 2, 'persian'); // 인스턴스
cat.move(); // 출력: kitty is moving.
cat.makeSound(); // 출력: kitty is making a sound.

1-3. 객체 지향 프로그래밍

  • 조금 더 공부할 필요... 있음...
  • 객체 지향 프로그래밍은 데이터와 기능을 한 곳에 묶어서 처리
    • 데이터와 기능이 별개로 처리되지 않는다는 뜻
    • 프로그램을 객체(object)들의 모임으로 생각하고, 객체들 간의 상호작용을 중심으로 프로그램을 설계
  • 객체는 속성(attribute)과 메서드(method)로 구성
    • 속성은 객체의 상태를 나타내는 변수
    • 메서드는 객체가 수행하는 동작을 나타내는 함수
    • 객체는 클래스(class)라는 틀(template)에 의해서 정의됨
    • 클래스는 세부사항(속성)이 들어가지 않은 청사진
      • 생성자를 통해 세부 사항(속성)을 넣어줌
  • 객체 지향 프로그래밍에서 중요 개념

    • 캡슐화(encapsulation)

      • 객체의 내부 구현을 외부에서 접근할 수 없도록 보호하는 것을 의미
      • 캡슐화를 통해 객체의 내부 구현을 감추고, 객체를 사용하는 코드는 객체의 인터페이스를 통해서만 접근할 수 있음
      • 객체 간의 결합도를 낮추고, 코드의 유지 보수성을 높일 수 있음
    • 추상화(abstraction)

      • 객체가 가진 복잡한 내부 동작을 단순화하여 필요한 부분만을 추출하는 것을 의미
      • 추상화를 통해 객체를 더욱 쉽게 이해할 수 있도록 만들고, 객체의 내부 구현과 외부 인터페이스를 분리할 수 있음
    • 상속(inheritance)

      • 기존 클래스를 재사용하여 새로운 클래스를 만드는 것을 의미
      • 상속을 통해 클래스의 중복 코드를 줄일 수 있고, 코드의 재사용성을 높일 수 있음
      • 부모 클래스는 자식 클래스에게 자신이 가지고 있는 필드와 메서드를 물려주며, 자식 클래스는 이를 상속받아 자신의 필드와 메서드를 추가하거나 수정할 수 있음
    • 다형성(polymorphism)

      • 하나의 인터페이스를 여러 가지 방식으로 구현할 수 있는 것을 의미
      • 다형성을 통해 코드의 유연성과 재사용성을 높일 수 있음
      • 오버로딩(overloading)과 오버라이딩(overriding)있음
        • 오버로딩은 같은 이름의 메서드를 매개변수의 타입과 개수에 따라 다르게 정의하는 것을 의미
        • 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것을 의미

1-4. 객체지향 차이점

  • 은닉화(private 키워드)의 한계
    • Java나 TypeScript에서 클래스 내부에서만 쓰이는 속성 및 메서드를 구분시키기 위해 제공하는 키워드

    • 하지만 은닉화를 도와주는 기능이 JavaScript에서는 널리 쓰이지 않음 정확히는 지원하는 브라우저가 적음 ㅜㅜ)

    • TypeScript에서는 속성이 존재해도, private 키워드가 붙어 있으면, 클래스 내부에서만 사용 가능

    • JavaScript에서는 은닉화를 돕기 위해서 일반적으로 클로저 모듈 패턴을 사용

      • 클래스/인스턴스 형태로 만들 때에는 ES2019부터 #이라는 키워드가 도입

  • 추상화(interface 키워드) 기능의 부재
    • 객체 지향 프로그래밍의 주요 키워드 중 하나인 추상화는, 속성과 메서드의 이름만 노출시켜서 사용을 단순화한다는 의미
    • 즉, 인터페이스(interface)의 단순화를 의미
    • Java나 TypeScript 언어는 언어의 주요 기능으로 interface를 구현해 놓았지만 JavaScript에는 존재하지 않는 기능(ㅜㅜ)
    • 인터페이스는 일종의 규약처럼 간주되어, 인터페이스를 클래스로 구현하는 사람들이 이에 맞게 작성할 수 있게 함
    • 이는 클래스를 이용하는 입장에서 노출된 인터페이스를 통해 "이 클래스는 메서드 이름이 의도한 바대로 작동할 것이다"라는 것을 명백히 보여줄 수 있음
    • 실질적인 구현 방법을 공개하지 않고, 사용법을 노출시키기에도 유리함
    • 어떤 클래스가 외부 공개용으로 모듈처럼 작동할 때에 인터페이스는 아주 용이한데, 이러한 인터페이스 사용의 대표적인 예가 API(Application Programming Interface)
profile
감성있는 개발자를 꿈꿔요

0개의 댓글