728x90

좀 더 나은 개발자가 되기위해

나를 되돌아보고

무엇을 다시 혹은 더 공부해야 될지

고민하던중

 

내가 OOP를 제대로 못하고있다고

생각이 들었다.

 

아직도 OOP를 제대로 못한다니

부끄럽지만 숨기지않고

인정하고 공부했을때

나아갈수 있는것이다.

 


아래 내용 관련 Github :)

https://github.com/jaekwangLee/oop_js_study

 

 

그러면 가장 기본적인

객체지향 프로그래밍의 의미를 알아본다.

 

시중에서 접하는 책들에서는

자동차, 커피머신, 로봇 등을 예시로 든다.

 

그 전에

더 이전부터 존재했던 개념인

절차지향 프로그래밍의 의미와

단점에 대해서 알아야

왜 객체지향이 등장했는지,

객체지향을 적용해야만 하는 이유를

알수있다.

 

절차지향 프로그래밍이 뭘까?

말그대로 절차를 중요시하며

순차적으로 실행되는 프로그래밍 기법을 말한다.

 

예를들어, 자동차가 있다면

시동 (start) 을 구현한다고 가정해보자.

절차지향적인 프로그래밍에서는 어떻게 할까?

// car.js
function car() {
  const fuel = 50;
  const brand = 'porche';
  const owner = 'steve';
  const tires = 4;
  
  function stop() {
    1. 사용자가 시동을 끈다.
    2. 액션을 엔진에 전달한다.
    3. 엔진이 신호를 받는다.
    4. 엔진이 동작을 멈춘다..
  }

  function start() {
    1. 사용자가 시동을 건다
    2. 액션을 엔진에 전달한다.
    3. 엔진이 신호를 받는다.
    4. 엔진이 동작을 시작한다.
  }
}
...

 (역시 개발자는 코드 구조로 봐야 이해가 쉽다)

 

이렇게 개발을 하면 단점이 뭘까?

무슨 문제가 있기에 객체지향을 해야하는 걸까?

 

1. 유지보수

누군가 저렇게 개발해둔 코드를 유지보수 하게 됐다면

지옥을 맛볼것이다.

시동 부분의 일부를 수정하는데도

이해해야 하는 코드가 너무나도 방대한것이다.

 

자동차 관련 코드 전체를 읽어야지

수정이 가능한 상황이 발생하기 쉽상이다.

 

2. 재사용성

start라는 시동 액션이 여기서만 쓰일까?

1) 개발중인 자동차와 다 똑같은데,

시동걸때 "시동!" 이라고 음성을 들려주는 자동차를 만들려면

수없이 중복되는 코드들을 짜야될것이다.

 

2) 자동차가 아닌 오토바이의 시동을 개발하게 되었다면,

자동차의 시동부와 액션이 같을 확률이 높지만 우리는

수없이 중복되는 코드들을 짜야될것이다.

 


 

이런 문제들을 알고

객체지향에 대해 다시 알아보자.

 

흔히 말하는 객체지향의 장점은

아래의 코드로 확인할 수 있다.

{
  interface NormalCar {
    start(): void;
    stop(): void;
    run(): void;
    spec: Specifications;
    ownerName: string;
  }

  interface SuperCar {
    start(): void;
    stop(): void;
    run(): void;
    boost(): void;
    spec: Specifications;
    ownerName: string;
  }

  type Specifications = {
    tires: number;
    fuel: number;
    owner: string;
  };

  type OnOff = "off" | "on";

  class Vehicle {
    private engine: OnOff = "off";
    constructor(tires: number, fuel: number) {
      console.log(tires, fuel);
    }

    start = (): void => {
      console.log("start");
      this.engineToggle("on");
    };

    stop = (): void => {
      console.log("stop");
      this.engineToggle("off");
    };

    run = (): void => {
      console.log("keep going...");
    };

    boost = (): void => {
      console.log("speed up!!!");
    };

    get status() {
      return "car status : " + this.engine;
    }

    private engineToggle = (nextStatus: OnOff): void => {
      this.engine = nextStatus;
    };
  }

  class Car extends Vehicle {
    constructor(private tires: number, private fuel: number, private owner: string) {
      super(tires, fuel);
    }
    
    get spec() {
      return {
        tires: this.tires,
        fuel: this.fuel,
        owner: this.owner,
      };
    }
    
    get ownerName() {
      return this.owner;
    }
    
    set ownerName(newName: string) {
      this.owner = newName;
    }
  }

  // car 인스턴스 생성
  const myCar = new Car(4, 50, "steve");
  myCar.start();
  console.log(myCar.status);
  
  myCar.stop();
  console.log(myCar.status);

  // car 인스턴스 생성할 때 interface를 이용해 추상화
  const myFamilyCar: NormalCar = new Car(4, 60, "steve_family");
  // myFamilyCar.boost() <-- error

  const myHobbyCar: SuperCar = new Car(4, 48, "steve_hobby");
  myHobbyCar.boost();
}

 

다음 장에서

위 코드에 대한 분석과

객체지향의 장점에 대해

이어서 공부해보도록 하자.

728x90
반응형