먼저 객체지향 프로그래밍이 등장하게 된 배경을 이해하기 위해 객체 지향 프로그래밍 등장 이전에 존재했던 여러 가지 프로그래밍 패러다임 중 '비구조적 프로그래밍' 과 '절차적 프로그래밍'에 대해 알아보자.
비구조적 프로그래밍
- 정의한 기능의 흐름에 따라 순서대로 동작하며 프로그램을 완성하는 방식으로, 작은 프로그램일 경우엔 흐름이 한눈에 보여 직관적이다는 장점이 있다.
하지만 프로그램의 크기에 살이 붙어 커질 경우엔 큰 단점이 되는데, 예를 들면 기능 A->B->C 순서로 동작하다 C에서 갑자기 A로 돌아가야 할 경우 스파게티 코드가 되어 버리 때문에 직관적인 장점이 사라지게 된다.
이러한 단점을 보완하기 위해 등장한 다음 패러다임은 절차적 프로그래밍이다.
절차적(구조적) 프로그래밍
- 절차적 프로그래밍은 명령형 프로그래밍과 동의어로 쓰이기도 한다. 절차적 프로그래밍에서 절차란 함수를 의미한다. 따라서 절차적 프로그래밍은 반복되는 동작을 함수나 프로시저(리턴값이 없는, 인자만 소비하는 함수)형태로 모듈화 하여 사용하는 방식이다.
함수를 모듈화하여 사용하면 코드량을 줄일 순 있다. 하지만 프로시저 자체는 추상적이라는 단점이 있다.
그 이유는 만약 내가 저금통 관리 프로그램을 만든다고 가정했을 때, 동전이라는 자료형과 동전에 대한 함수가 필요하다.
그러나 절차적 프로그래밍에서는 동전과 동전을 주체로 하는 함수는 따로 존재하기 때문에 논리적으로 묶을 수 없는 구조이므로 동작이 추상적이라고 볼 수 있다.
다시 말해 동전을 중심으로 함수들이 만들어지고 순서에 따라 순차 진행되므로 동전과 동전에 관한 함수들을 논리적으로 한 덩어리로 보기엔 무리가 있다.
따라서 이런 개념들을 하나로 묶기 위한 패러다임으로 '객체지향 프로그래밍'이다.
객체지향 프로그래밍이란?
- 특정 개념에 대한 자료형과 함수를 하나의 객체(object) 형태로 묶어 관리하기 위해 등장하게 되었다.
핵심은 객체 내부에 자료형 필드와 함수가 함께 존재하는 것으로 가능한한 물리적, 논리적 요소를 객체로 만드는 것이다.
위에서 설명한 저금통 관리 프로그램도 객체 지향으로 구현하면 동전의 종류, 넣을 개수, 모인 개수와 같은 자료형 필드와 동전 넣기, 동전 빼기 등의 메소드를 저금통이라는 객체에 묶어서 관리할 수 있다.
이렇게 되면 서로서로 분리되어 추상적이었던 동작도 보다 직관적으로 볼 수 있게 되어 코드의 가독성 또한 증가한다.
정리하면 객체 간의 독립성이 명확하고, 중복되는 코드 양이 줄어듬에 따라 유지보수가 더욱 쉬워진다.
객체 지향의 특징
- 객체지향 프로그래밍은 대표적인 특징 4가지가 있다.
바로 추상화, 캡슐화, 상속, 다형성 으로 각각의 개념을 알아보자.
- 추상화
- 객체들이 공통적으로 사용하는 동작이나 속성을 하나의 공통점으로 묶어내는 작업이다.
쉽게 예를 들어보면 된장찌개, 갈치조림, 잔치국수, 고등어구이는 음식이라는 공통점이 있다.
이렇게 음식이라는 추상화 집합을 만들어두고, 위 음식이 가지는 공통적인 특징들을 만들어 사용하면 된다.
특징의 예로는 이름, 가격, 맛, 칼로리 조회 등이 있다. - 만약 여기서 김치찌개가 음식에 추가되더라도, 추상화로 구현했다면 구현되어있는 다른 코드의 수정 없이 김치찌개의 이름, 가격, 맛, 칼로리 조회만 새로 정의해주면 된다.
- 객체들이 공통적으로 사용하는 동작이나 속성을 하나의 공통점으로 묶어내는 작업이다.
- 캡슐화
- 한 곳에서 변화가 일어나도 다른 곳에는 사이드 이펙트를 최소화 하는 것을 의미한다.
각각의 객체 내부의 어떤 동작에 대한 구현이 어떻게 되어있는지 감추어 외부에서 이를 손상시키는 것을 방지할 수 있다.
또한 객체 각자가 독립적으로 작동할 수 있도록 응집를 높여야 하고, 다른 객체 또는 모듈에 대한 의존도를 낮추어 결합도는 낮추어야 한다. 이런 높은 응집도와 낮은 결합도는 은닉화를 통해 구현할 수 있는데, 외부에서 알 필요가 없는 요소들엔 private으로 지정하여 접근에 제한을 걸고 의도치 않은 동작을 방지할 수 있다.
- 한 곳에서 변화가 일어나도 다른 곳에는 사이드 이펙트를 최소화 하는 것을 의미한다.
- 상속
- 상속은 자식 클래스가 부모 클래스의 필드나 메소드를 그대로 물려받아 사용하거나 수정하여 사용할 수 있도록 해준다.
하지만 상속을 통해 자식 클래스가 부모 클래스의 내부 구현을 알아야 할 경우 캡슐화를 깨뜨리게 된다.
그 이유는 상위 클래스의 함수를 오버라이딩할 상위 클래스 내부 구현을 확인하게 되기 때문이다. - 상속은 반드시 IS-A(포함관계) 관계가 성립할때, 기능의 확장 관점에서만 사용되어야 한다.
상속을 단순히 코드 재사용의 목적으로 사용하면 클래스의 결합도가 높아져 유지 보수하기 힘들어진다.
일반적인 개념을 정제 혹은 정리하는 상황에서 상속을 사용해야 한다.
- 상속은 자식 클래스가 부모 클래스의 필드나 메소드를 그대로 물려받아 사용하거나 수정하여 사용할 수 있도록 해준다.
- 다형성
- 다형성은 서로 다른 클래스의 객체가 같은 동작을 할 때, 각자의 특성에 맞는 방식으로 동작하는 것이다.
상속과의 시너지를 통해 코드를 간결하게 해주고, 유연하게 해 준다. 또한, 어떤 클래스의 객체가 참조되는지 무관하게 프로그래밍하는 것이 가능해진다. 다형성을 구현하는 방법으로는 오버로딩, 오버 라이딩, 함수형 인터페이스가 있다. - 추상화에 들었던 예시의 음식을 상속하여 보쌈과 족발이라는 객체를 만들었는데, 음식의 '칼로리 조회'라는 메소드를 실행했을 때 각각 음식마다의 칼로리를 출력한다면 다형성이 나타난 것이다.
이처럼 상속 관계에 있다면 새로운 자식클래스가 생겨나도 부모 클래스의 함수를 통해 참조하면 되기 때문에, 다른 클래스에는 영향을 받지 않는다.
- 다형성은 서로 다른 클래스의 객체가 같은 동작을 할 때, 각자의 특성에 맞는 방식으로 동작하는 것이다.
'CS' 카테고리의 다른 글
Garbage Collection (0) | 2022.05.25 |
---|---|
Process와 Thread (0) | 2022.05.17 |
소프트웨어 개발방법론 (0) | 2022.01.20 |
임계 영역 동시접근 해결 방안 (0) | 2021.12.21 |
임계 구역과 경쟁 상태 (0) | 2021.12.21 |