- Published on
Object-Oriented Programming (1)
- Authors

- Name
- 이지영
| What is Object-Oriented Programming?
OOP
OOP = 어떻게 우리가 코드를 쓰고 정리하는 지에 관해 오브젝트 관점에서 정리한 프로그래밍 기법
우리는 to-do list item과 같은 실생활에서 쓰이거나 HTML 요소 또는 데이터 구조와 같은 추상적인 feature를 표현(model)하기 위해 오브젝트를 사용한다.
오브젝트는 데이터(프라퍼티)와 함수(메서드)를 가질 수 있다. 데이터와 그와 관련된 함수를 하나의 코드 블락에 담을 수 있다.
오브젝트는 "self-contained(자족적인) 코드 블락"으로, 우리는 이걸 서로 상호작용하게 만들 수 있다.
오브젝트끼리의 상호작용은 공공 인터페이스(API)를 통해 일어날 수 있는데, API는 오브젝트 바깥의 코드가 오브젝트에 접근하여 사용할 수 있는 많은 양의 메서드라고 볼 수 있다.
OOP는 왜 존재할까?
이 패러다임은 스파게티 같은 코드 작성을 피하고, 코드를 예쁘게 정리하는 목적(좀 더 유연하고, 유지하기 쉽도록)에서 시작됐다. 이렇게 더 정돈된 코드를 작성하기 위해 만들어진 패러다임은 여러가지가 존재하고, 그 중에 하나가 OOP이며, 중요한 패러다임 중 하나로는 "functional programming"이 있다. 우리는 지금까지 object-literal을 사용해 오브젝트를 이용해왔고, 굳이 우리가 직접 오브젝트를 만들 필요도, 이들끼리 상호작용하게 만들 필요도 없는 간단한 코딩만 해왔다. 하지만 이제 OOP에서는 우리 손으로 직접 새로운 오브젝트 자체를 생성할 방법을 배울 필요가 있다.
먼저, 전통적인 OOP (객체지향 코드작성기법)에서는, class라는 것을 이용한다. class는 정해진 규칙에 따라 새로운 오브젝트를 만들기 위한 하나의 blueprint(밑그림) 정도의 개념으로 이해하자. 이 건물을 짓기 위한 설계도 역할을 하는 청사진은 단지 계획에 불과할 뿐, 실제로 존재하진 않고, 실제 데이터(실제 집을 짓기 위한 재료…)를 가지고 있지도 않는다! 하지만 이걸 이용해 우리는 실제 아주 근사한 집을 지을 수 있듯이, 자바스크립트 OOP에서도 똑같은 원리가 적용된다.
Class = A blueprint from which we can create new objects
이때, class는 설계도 역할을 하는 하나의 계획일 뿐, 실제 쓰이는 데이터를 포함하진 않는다. 실제 데이터를 가지지 않는 대신, 데이터와 관련된 모든 데이터와 메서드를 하나의 블락안에 가지고 있다. ex) login method to send messages
그렇다면 이렇게 잘 완성된 설계도(Class)를 가지고 실제 데이터를 갖고 있는 집(Object)을 지어보자!
클래스를 이용해 만든 오브젝트를 instance라고 하며, 이는 우리의 코드 상에서 사용할 수 있는 real 오브젝트로서, class처럼 유저 관련 데이터를 묘사한 것에 그치지 않고, 실제 데이터와 메서드를 가진다.
이러한 메커니즘이 아름다운 이유는, 클래스를 이용해서 우리가 원하는 만큼의 오브젝트를 계속해서 만들 수 있다는 점이다. 마치 하나의 청사진으로 여러 집을 만들 수 있듯이! 이때 만들어진 여러 개의 오브젝트(instances)들은 각기 다른 데이터를 소유할 수 있지만, 같은 기능을 공유하고 있다.
그렇다면, 우리는 클래스를 어떻게 디자인할까? 어떻게 실제 데이터를 클래스 안에 집어넣을까?
좋은 class implementation을 위한 기본적인 4가지 원리가 존재한다.
1. Abstraction
: 중요하지 않은 세부사항을 무시하고 숨기는 것.
-abstraction.png&w=1920&q=75)
이것은 실제 크게 중요하지 않은 세부사항에 얽매이지 않고, 우리가 시행하고자 하는 것의 개요를 얻게 해준다. 이 개념은 OOP에서 뿐만이 아니라, 프로그래밍 전역에서 중요하게 자리잡고 있는 개념이다.
ex) addEventListener가 어떻게 동작하는지에 대한 원리를 우리는 정확하게 알고 쓰는가? 아니다! 그냥 우리는 html으로부터 가져온 돔 노드 상에서 불러올 수 있는 하나의 higher-order function으로서, 이벤트가 발생했을 때 또 다른 함수를 불러와 특정 동작을 실행시킬 수 있는 함수라고 생각하고 쓰는 것이다.
2. Encapsulation → "Closure를 이용하는 이유"
: 클래스 안에 존재하는 데이터나 메서드를 private하게 만들어 코드 바깥에서 사용할 수 없도록 만드는 것.
-encapsulation.png&w=1920&q=75)
하지만, 공공 인터페이스를 통해 상호작용이 일어나는 오브젝트의 경우, 여전히 바깥으로 노출될 수 있다. 반면 프라이빗 처리한 데이터나 메서드는 바깥에서 사용할 수 없고, 코드 블락 내에서만 접근을 허용함으로써, 바깥 코드가 내부 프라퍼티나 상태를 실수로 조작할 수 있는 가능성을 막아 버그 발생을 줄일 수 있다. 단, 프라이빗하게 만들 데이터나 메서드는 당연히 모든 데이터와 메서드가 캡슐화되지 않은(=프라이빗 처리되지 않은) 공공 API의 부분으로 만들지 않는다.
3. Inheritance
: OOP에서 긴밀하게 연결된 2개의 클래스를 가질 때, 하나의 클래스를 다른 하나로부터 상속시켜 계층관계를 형성하는 것.
-inheritance.png&w=1920&q=75)
즉, 이 둘을 부모-자식 관계로 연결시킴으로써, 좀 더 글로벌한 클래스인 부모 클래스에 있는 모든 프라퍼티와 메소드들을 더 세부적인 클래스인 자식 클래스가 사용가능하게끔 만드는 작업을 뜻하는데, 이는 우리가 공통된 로직을 사용할 수 있도록 해주고, 실제 세계 관계를 모델링할 수 있게 해준다. 이때 자식 클래스는 자기 자신만의 메소드와 프라퍼티를 소유 가능하며, 부모 클래스로부터 기본적으로 상속받은 프라퍼티/메소드 외에 특별한 기능이 추가된다고 보면 된다.
ex) 부모클래스: user, 자식클래스: Admin (관리자도 유저긴 유저니까 유저 클래스에 있는 모든 프라퍼티와 메서드를 상속!)
4. Polymorphism(= Many shapes)
: OOP의 맥락에서, Polymorphism은 child class가 부모 class로부터 상속 받은 메소드를 덮어쓸 수 있다는 것.
-polymorphism.png&w=1920&q=75)
위의 예시를 그대로 갖고오되, 여기서 user에 속하는 author에 대한 정보가 담긴 클래스가 있다고 가정했을 때, author도 역시 user이므로, admin과 author는 User 클래스에 있는 모든 정보를 상속받는다고 해보자. 이때, admin(관리자)는 특별히 두 단계를 거친 더 엄격한 로그인 과정을 거치고, author는 일반 유저와는 다른 특별한 로그인 과정을 거쳐야 한다고 하면, 어떤 식으로 두 클래스에 각각 다른 메서드를 줄 수 있을까? => 방법은 아주 간단하다. 각각의 클래스에서 이미 상속받은 로그인 메소드 위에 새로운 메소드를 쓰면 polymorphism 원리에 의해 덮어씌어져 새롭게 작성한 메소드가 적용된다.