OOP - Abstraction
객체의 불필요한 구현 세부 사항은 감추고, 필수적인 기능만 제공하여 단순화 시키는 속성을 “추상화“라고 한다. 예시를 들어보면, 한 유명 가수의 콘서트를 홍보하기 위해서는 ‘공연 날짜’, ‘공연 장소’, ‘티켓 판매일’ 등등의 정보를 제공해야 한다. 하지만, 홍보와 관련없는 정보까지 주게 되면 (‘스태프 수’, ‘장비 종류’, ‘리허설 일자’ 등) 정보를 받는 사람은 쉽게 이해하기 힘들고, 목적도 흐려지게 된다. 그렇기에, 목적에 맞는 인터페이스만 제공하고, 그 외의 세부 정보/기능들은 드러내지 않는 것이 “추상화”의 핵심이다.
추상화의 장점/단점
[추상화의 장점] → 가독성 향상 : 외부에서는 기능에 집중하고, 세부 구현은 무시할 수 있기에, 프로그램/코드를 빠르게 이해할 수 있게 된다. → 유지보수 용이 : 세부 구현이 변경되어도 인터페이스는 그대로 유지되니까, 다른 부분에 영향을 미치는 일을 줄일 수 있다.
[추상화의 단점] → 과도한 설계 : 클래스들이 많아질 경우, 복잡도도 같이 증가하여, 비효율적인 설계가 될 가능성이 있다. → 어려운 디버깅 : 세부 구현이 감춰져 있어, 내부에 오류가 났다고 하면, 원인을 추적하기까지 시간이 걸린다. → 성능 오버헤드 : 추상 클래스/인터페이스 호출은 추가적인 연산, 메모리 사용으로 성능에 영향을 줄 수 있다.
추상 클래스
하위 클래스가 공통적으로 가지는 속성과 기능을 정의하고, 일부 기능을 하위 클래스에서 구현하도록 맡기면서 하위 객체를 공통된 형태로 다루기 위한 추상 계층 클래스이다. C++에서는 ‘순수 가상 함수‘가 하나 이상 있는 클래스를 말한다. 추상 클래스는 하위 클래스가 순수 가상 함수로 만들어진 함수를 직접 구현하도록 요구한다.
class Person { // Abstract
protected:
int Age;
float Weight;
public:
void Eat() { ... }
virtual void Sound() = 0;
}
인터페이스
추상 클래스의 일종으로, 객체가 무엇을 해야 하는지 ‘규약‘을 정의하는 목적의 추상화 방식이다. C++에서 클래스를 인터페이스 용도로 만들 때에는 순수 가상 함수만 사용하여 선언하여, 기능들만 정의하고, 데이터와 구체적인 구현은 두지 않는다. 구체적인 구현은 인터페이스를 받는 하위 클래스가 담당하여, 기능을 구현하도록 요구한다.
class Vehicle { // interface
public:
virtual void Move() = 0;
virtual void Stop() = 0;
};
// Vehicle을 상속받는 클래스는 Move, Stop을 구현하도록 강제 된다.
class Car : public Vehicle {
public:
void Move override { ... }
void Stop override { ... }
};
추상화와 캡슐화
개념 정의를 보면, 추상화와 캡슐화가 크게 다를 것 없다는 것을 알 수 있을 것이다. ‘내부에 숨길 것은 숨기고, 외부에 보여줄 것은 보여주자’ 라는 뜻은 같다. 하지만 이 두 개념은 지향하는 점이 다르기 때문에 구분되어질 수 있는 것이다.
- 추상화 : “무엇을 보여줄 것인가” 라는 점이 중심이다. 외부에 제공할 기능들에 초점이 맞춰져 있기에, 외부에선 ‘덜 복잡한’ 기능, 내부에선 ‘필수적인’ 기능을 중심으로 한 개념이다.
- 캡슐화 : “어떻게 보호하고 통제할 것인가” 라는 점이 중심이다. 외부에서 접근이 불가능 하도록 ‘통제’시키는 것이 주 목적이며, 데이터와 내부 구현에 대한 접근 통제를 중요시한다.
그렇기에 C++에서도 추상화는 ‘인터페이스/추상 클래스’를 이용하여 ‘기능을 제공‘하고, 캡슐화는 ‘접근 지시자’를 통해 데이터의 ‘접근을 통제’ 시킨다.
SOLID 와 추상화
이전에 SOLID에 대해 정리하면서 떠올랐는데, OCP(개방-폐쇄 원칙) 와 DIP(의존성 역전 원칙) 이 추상화와 연관이 깊다.
이미 SOLID 포스트에서 한 번 언급했지만, OCP에 따르면, 설계시에 기존의 기능을 수정하는 대신 새로운 기능을 추가하는 방향이 좋다. 그렇기에, 새로운 기능을 추가할 때 추상화에 의존하도록 설계하여, 생산성을 향상 시키게 만드는 것이 OCP와 추상화의 핵심이고.
DIP는 정의부터 “추상화”란 말을 그대로 사용했다. ‘클라이언트는 인터페이스에만 의존해야 한다.’ 즉, 위에서 말한 것의 반복이다. 구체적인 구현이 아니라 추상화에 의존하자는 뜻으로 클라이언트는 내부 구현을 알 필요가 없게 만드는 것이다.
정리하자면, OCP는 추상화를 통한 확장의 용이함을, DIP는 추상화에 의존하도록 하여 세부 사항에 대한 의존도를 줄이는 점을 강조한다.
Comments