객체 지향 프로그래밍(OOP)

 

객체 지향 프로그래밍(Object Oriented Programming)

컴퓨터 프로그래밍 패러다임 중 하나로, 현실 세계를 프로그래밍으로 옮겨오는 과정에서 탄생한 인간 중심적인 프로그래밍 패러다임이다.

패러다임(Paradigm)
한 시대의 사람들의 견해나 사고를 근본적으로 규정하고 있는 인식의 체계. 또는, 사물에 대한 이론적인 틀이나 체계

객체 지향 프로그래밍은 프로그래밍에 필요한 것들을 '속성(Attribute)과 행위(Behavior)를 가진 객체(Object)'로 정의하며, 객체들 간의 상호작용을 통해 프로그램을 구현하는 프로그래밍 방식이다.

 

 

객체 지향 프로그래밍의 5가지 특징

1) 클래스(Class)와 인스턴스(Instance)

클래스란 객체를 정의하는 틀 또는 설계도를 의미한다. 클래스는 객체의 상태를 나타내는 프로퍼티(Property)와 객체의 행동을 나타내는 메서드(Method)로 구성된다. (메서드는 특정 작업을 수행하기 위한 명령문의 집합으로 이루어져 있다.)
이 클래스를 이용하여 만들어진, 메모리에 할당된 객체를 해당 클래스 타입의 인스턴스라고 한다. 하나의 클래스로 여러 개의 인스턴스를 생성할 수 있다.

 

2) 추상화(Abstraction)

객체들의 공통적인 특징(속성과 기능)을 도출해 내는 것.
세부적인 객체들에서 보다 큰, 개괄적인 특징을 뽑아내어 하나로 묶는 것을 의미한다.

 

3) 캡슐화(Encapsulation)

객체의 속성과 기능을 하나로 묶고, 실제 구현 내용을 외부에 노출되지 않도록 은닉하는 것.
외부에서는 객체 전체의 내부 구조를 알 수 없으며, 객체가 제공하는 프로퍼티와 메서드만 사용할 수 있다.
프로퍼티와 메서드를 공개하거나 숨기는 것은 접근 제한자(Access Modifier)를 통해 이뤄질 수 있다.
캡슐화를 하는 이유: 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 보호하기 위해

 

4) 상속(Inheritance)

상위(부모) 클래스가 가진 특징(속성과 기능)을 하위(자식) 클래스가 그대로 물려받는 것.
기존 코드(상위 클래스)를 재활용 함으로써 코드의 중복을 줄일 수 있으며, 유지 보수가 편해진다.

 

5) 다형성(Polymorphism)

동일한 명령의 해석을 연결된 객체에 의존하는 것. 동일한 명령일지라도 객체에 따라 다르게 동작할 수 있다.
- 오버라이딩(Overriding)
부모 클래스의 메서드와 같은 이름, 같은 매개 변수를 사용하되, 내부 기능을 재정의 하여 다른 기능을 동작하게 하는 것.
- 오버로딩(Overloading)
같은 이름, 다른 매개 변수를 가진 메서드를 여러 개 정의한 뒤, 상황에 맞는 메서드를 사용하는 것.

 

 

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

- 👍 소프트웨어 생산성 향상
상속, 캡슐화, 다형성을 활용해 코드를 재사용하기 쉽고 업그레이드하기 쉽다. 내부 동작 원리를 모르더라도 클래스가 제공하는 메서드를 이용하면 해당 기능을 사용할 수 있다. 객체 단위로 코드가 작성되기 때문에 디버깅이 쉽고 유지 보수가 용이하다. 

- 👍 쉬운 모델링
데이터 모델링 단계에서 데이터를 객체와 맵핑하는 것이 용이하기 때문에 모델링이 보다 쉬워지고 덕분에 요구 사항을 명확하게 파악하여 프로그래밍할 수 있다.

- 👍 보안성 향상
캡슐화를 통해 데이터가 은닉되고, 다형성을 통해 필요한 기능을 재정의할 수 있어 보안성이 높다.

- 👎 느린 실행 속도
캡슐화와 격리된 구조 때문에 절차 지향 프로그래밍에 비해 속도가 느리다.

- 👎 필요한 메모리 증가
객체 간의 정보 교환이 메시지를 통해 일어나므로 연산에 추가 비용이 들어가 프로그램 실행 시 오버 헤드(Overhead)가 발생할 수 있다.

 

 

객체 지향 프로그래밍 설계 5 원칙 (SOLID)

1) 단일 책임 원칙 SRP(Single Responsibility Principle)
클래스는 단 하나의 책임을 가져야 하며, 클래스를 변경하려는 이유는 단 하나의 이유이어야 한다.

2) 개방-폐쇄 원칙 OCP(Open-Closed Principle)
클래스는 확장에는 열려있어야 하고, 변경에는 닫혀있어야 한다.

3) 리스코프 치환 원칙 LSP(Liskov Substitution Principle)
상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입 객체를 사용하는 프로그램은 여전히 정상적으로 동작해야 한다.

4) 인터페이스 분리 원칙 ISP(Interface Segregation Principle)
인터페이스는 해당 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.

5) 의존 역전 원칙 DIP(Dependency Inversion Principle)
자신보다 변하기 쉬운 것에 의존하지 말 것.
하위 클래스, 구체 클래스보다 상위 클래스, 인터페이스, 추상 클래스가 변하지 않을 가능성이 크다.

 

 

+ 절차적 프로그래밍(Procedure Programming)

단어 그대로 '절차적'으로 코드를 구성하는 것. 흐름도, 순서도와 비슷한 형태를 띤다. 데이터에 대한 순서를 파악하고 필요한 기능을 함수로 만들어 절차적으로 기능을 수행한다.
하나의 큰 기능을 수행하기 위해 작은 단위의 기능들로 나누어 처리하는 Top-Down 방식으로 설계한다.

객체 지향 프로그래밍과 가장 큰 차이점은 바로 프로퍼티와 메서드를 묶어 하나의 객체로 다루는 것이 아니라 별개로 취급한다는 것이다.
또한, 객체 지향 프로그래밍에서는 객체를 생성하고 그 인스턴스를 이용해 메서드를 호출하는 반면, 절차적 프로그래밍에서는 그런 과정 없이 메서드를 직접 호출해야 한다.

포트란, 베이직 , C 언어 등이 대표적인 절차적 프로그래밍 언어에 속한다.

절차적 프로그래밍은 절차적으로 코드를 구성하기 때문에 흐름을 따라가면서 결과값을 도출하기 쉽지만, 반대로 그 때문에 순서가 바뀌면 원하는 결과값을 도출하기 어렵다는 단점이 있다. 또한, 순서를 유지해야 하기 때문에 유지보수가 어렵고 대형 프로젝트에 부적합하다는 의견이 있다.