객체지향
객체지향(Object Oriented)은 프로그램 구현에 필요한 객체를 파악하고 각각의 객체들의 역할이 무엇인지를 정의하여 객체들 간의 상호작용을 통해 프로그램을 만드는 것을 말한다. 객체는 클래스(class)라는 틀에서 생겨난 인스턴스(instance)이다. 따라서 객체지향 프로그래밍은 객체와 객체 간의 연결로 되어 있으며 각각의 객체 안에 자료구조와 알고리즘이 들어 있는 것이다.[1]
목차
개요
객체지향은 실제 세계를 모델링 하여 소프트웨어를 개발하는 방법으로서, 객체지향 프로그래밍에서는 데이터와 절차를 하나의 덩어리로 묶어서 생각한다. 이는 마치 컴퓨터 부품을 하나씩 사다가 컴퓨터를 조립하는 것과 같은 방법이다. 여기서 객체(object)란 보고 만질 수 있는 것, 지성적으로 이해할 수 있는 것, 생각이 나 행동이 추구하는 바를 말한다. 또는 문제 영역에서 잘 정의된 역할을 갖고 있는 각각에 대해서 구별할 수 있는 품목(item), 단위(unit), 개체(entity)라 정의하기도 하며 단순히, 정의된 경계를 갖고 구별되는 어떤 것이라 말할 수도 있다. 이 방법은 오늘날 자바(Java), C# 등의 프로그래밍 언어(programming language)들을 지배하고 있는 가장 중요한 맥박이라고 할 수 있다. 객체지향의 캡슐화, 상속, 다형성을 통해 여러 개의 객체 단위로 나누어 작업할 수 있기 때문에 개발자와 협업해 규모가 큰 프로젝트도 무리 없이 진행할 수 있으며 유지 보수도 뛰어나다는 장점이 있다. 하지만 코딩 난이도가 상승하며 객체에 대한 정확한 이해가 필요하여 설계 단계부터 많은 시간이 소요된다.[2][3][4][5]
역사
등장배경
초기 프로그래밍 방식은 절차적 프로그래밍(Procedure Programming) 방식으로 명시된 순서대로 처리한 다음 결과를 도출하는 방식이었다. 하지만 이 방식은 조금만 복잡해지면 순서도로 나타내는 것이 불가능할 정도로 꼬인 '스파게티 코드'를 만들게 되는데 명령어 양이 증가함에 따라 중복 코드 대처가 힘들고, 특정 코드가 어디까지 영향을 미치는지 알 수 없기에 유지 보수가 굉장히 어려웠다. 이러한 문제를 해결하기 위해 에츠허르 데이크스트라(Dijkstra)는 프로그램을 함수(procedure) 단위로 나누고 프로시저(Procedure)끼리 호출을 하는 구조적 프로그래밍(structured programming) 방식을 제안하면서 이러한 위기를 벗어나게 된다. 하지만 함수는 데이터의 처리 방법을 구조화했을 뿐, 데이터 자체는 구조화하지 못했다. 그로 인하여 네임스페이스(Namespace) 포화 문제를 낳게 되며 엉뚱한 데이터가 엉뚱한 함수에 전달돼서 데이터를 오염시키는 문제가 발생하고, 그런 가능성 때문에 프로그래머가 한 함수의 작동에 영향을 받는 변수를 조사해야 할 때 모든 변수를 다 조사해야 하는 어려움에 봉착했다. 또한, 만약 프로그램의 크기가 증가한다면 수많은 변수가 생기며 함수가 접근할 수 있는 데이터의 범위에 명시적인 제한을 걸어야 하는 상황이었다. 이를 극복하기 위한 대안으로 객체지향 언어의 시초인 1960년 노위지안 컴퓨팅 센터의 조한 달과 크리스틴이 발표한 시뮬라67이다.[6][7][8] 한편 네임스페이스는 개체(entity)를 구분할 수 있는 범위를 나타내는 말로 일반적으로 하나의 이름 공간에서는 하나의 이름이 단 하나의 개체만을 가리키게 된다.[9]
발전
객체지향 언어는 당시에 기존 절차적 프로그래밍과 매우 이질적이고, 컴퓨터 처리 능력이 별로 좋지 않아서 큰 주목을 받지 못하였지만 향후에 프로그래밍 언어가 많은 지원을 받으면서 스몰토크, 에이다 같은 프로그램이 등장하며 객체지향에 대한 연구가 활발하게 진행되었다. C++, 델파이, 폭스프로(FoxPro)와 같은 프로그램들은 객체지향 언어에 가장 큰 영향을 미쳤던 GUI의 발전에 따라 점점 향상되었다. 화면에 떠 있는 여러 개의 창은 각자의 실행 콘텍스트(context)를 가지는데 콘텍스트의 현재 상태(활성화, 비활성화, 최소화 등)에 따라 같은 명령에도 다른 결과를 내보내야 했으며 사용자 상호작용을 위해 이벤트 처리도 수행해야 했다. 특히 이벤트 처리는 비동기적인 속성 때문에 기존 절차적 프로그래밍에서는 일종의 횡단 관심사가 되어 버려 코드 전체에 이벤트 처리 코드가 흩어져 있게 되는 문제가 있었다. 그래서 객체지향 프로그래밍를 도입하여 이벤트를 받았을 때 수행되는 기능(이벤트 핸들러/콜백)을 구현할 수 있는 단일 인터페이스를 정의하고, 프로그래머들은 이를 필요한 형태로 알아서 구현하며, 특정 이벤트가 일어났을 때 실행되어야 하는 기능들을 등록한 다음, 운영체제나 응용프로그램이 실제로 해당 이벤트가 발생했을 때 해당 이벤트에 등록된 이벤트 핸들러/콜백을 주욱 실행하기만 하면 되는 구조가 본격적으로 확산되면서 객체지향 프로그래밍 또한 빠르게 확산되었다.[6][7][8]
구성 요소
객체
객체(Object)는 실세계에 존재하거나 생각할 수 있는 것을 객체(object)라고 한다. 흔히 볼 수 있는 책상, 의자, 전화기 같은 사물은 물론이고 강의, 수강 신청 같은 개념으로 존재하는 것도 모두 객체이다. 다시 말해 사전에 나와 있는 명사뿐 아니라 동사의 명사형까지도 모두 객체인 것이다. 그리고 더 넓게 보면 인간이 생각하고 표현할 수 있는 모든 것이 객체이다. 이런 객체는 관점에 따라 여러 개념으로 이해된다. 모델링의 관점에서 객체는 명확한 의미를 담고 있는 대상 또는 개념이다. 따라서 현실 세계의 개체를 객체로 설계하는 것을 객체 모델링(Object Modeling)이라고 하며, 객체 모델링은 현실 개체의 속성과 행동을 추상화하여 객체를 정의하는 과정이라 할 수 있다.[10][8] 프로그래머의 관점에서 객체는 클래스에서 생성된 변수이다. 더 발전해서 소프트웨어 개발 관점에서 객체는 소프트웨어 개발 대상으로, 어떤 한 시점에 객체 상태를 나타내는 데이터와 해당 데이터를 처리하고 참조하는 동작을 의미하는 메서드(함수)를 모아놓은 데이터+메서드 형태의 소프트웨어 모듈이다. 소프트웨어 개발 관점에서 객체의 특성은 네 가지가 있다.
- 식별자 존재: 객체를 구별하는 유일한 식별자를 갖는다.
- 상태 존재: 자료구조에 해당하는 상태를 갖는다.
- 메서드 존재: 연산을 수행할 수 있는 행위에 해당하는, 잘 정의된 메서드를 갖는다.
- 클래스로 선언 및 사용: 객체지향 프로그램에서 객체는 비슷한 객체의 구조와 행위가 클래스로 선언되어 사용된다.
이렇듯 객체지향 프로그램 관점에서 객체는 비슷한 객체의 구조와 행위가 클래스로 선언되어 사용되는데, 이 관점에서 객체는 데이터와 함수를 속성과 메서드 용어로 구현한다.
클래스
클래스(Class)는 객체와 관련지어 생각하면 쉽게 이해할 수 있다. 아반떼, 그랜저, 소나타, SM5, K7을 객체라고 한다면, 승용차는 이들 객체의 클래스가 된다. 또 승용차, RV, 버스, 트럭이 객체라면, 자동차는 이들의 클래스이다. 이처럼 클래스는 공통되는 것들을 묶어서 대표적인 이름을 붙인 것이다. 공통된 특성을 가진 객체를 추상화하고 집단화하여 나타낸 것으로, 클래스가 개념적이라면 객체는 구체적이라 할 수 있다. 클래스는 객체 타입(Object Type)을 의미하며, 객체들이 갖는 객체의 변수(valiable) , 메소드(method)의 집합이다. 한 클래스를 기준으로 상위클래스를 슈퍼클래스(부모클래스)라고 하며, 하위 클래스를 서브 클래스(자식 클래스)라고 한다. 클래스로부터 생성된 새로운 객체를 인스턴스(Instance)이다.[8][11] 클래스는 데이터뿐 아니라 이 데이터에서 수행되는 메서드까지 포함해서 묶어놓은 것이라는 특징이 있다.
인스턴스
인스턴스(instance)는 같은 클래스에 속하는 개개의 객체로, 하나의 클래스에서 생성된 객체를 말한다. 즉 클래스가 구체화되어, 클래스에서 정의된 속성과 성질을 가진 실제적인 객체로 표현된 것을 의미한다. 예를 들어, 사용자(user)라는 클래스를 정의하고 홍길동(hong)이라는 객체를 생성할 경우, hong이라는 객체는 user라는 클래스의 인스턴스가 된다. 하나의 클래스를 사용하여 유사한 성질을 가진 수많은 인스턴스를 생성할 수 있다. 이 때 추상적인 개념인 클래스에서 실제 객체를 생성하는 것을 인스턴스화(instantiation)한다고 말한다.
메소드
메소드(Method)는 객체지향 시스템이 갖는 전통적인 시스템 함수 또는 프로시저에 해당하는 연산기능, 즉 객체를 실행할 수 있도록 하는 연산의 집합이다.[8] 메소드는 클래스 내부에서 특정한 작업을 처리하는 역할을 한다. 입력값이 있을 때 그 값을 받아서 처리한 후 결과 값이 있으면 되돌려준다. 클래스 내부에 정의되어 있는 메소드는 객체 내에 저장된 데이터에 접근하고, 객체 간의 통신을 가능하게 한다. 접근 제어자는 해당 메소드에 접근할 수 있는 범위를 명시한다. 반환타입은 메소드가 모든 작업을 마치고 반환하는 데이터의 타입을 명시한다. 메소드 이름은 메소드를 호출하기 위한 이름을 명시한다. 매개변수 목록(parameters)은 메소드 호출 시 전달되는 인수의 값을 저장할 변수들을 명시한다. 구현부는 메소드의 고유 기능을 수행하는 명령문의 집합이다. 메소드의 선언부에 명시되는 매개변수의 리스트를 가리리는 것을 메소드 시그니처(method signature)라고 한다. 두 메소드가 매개변수의 개수와 타입, 순서까지 같다면 두 메소드의 시그니처는 같다고 할 수 있다.
메시지
메시지(Message)는 객체들 간의 상호작용을 하는데 사용하는 수단이며 객체에 명령을 내리는 것이라고 할 수 있다.[8]
원칙
소프트웨어의 유지 보수나 확장이 쉽고, 유연하게 설계하기 위해 2000년 초에 로버트 마틴(Robert Martin)이 명명한 객체지향 프로그래밍의 다섯 가지 기본 원칙을 마이클 페더스(Michael Feathers)가 그 원칙의 앞 글자들을 따서 솔리드(SOLID)라는 이름으로 소개했다.[12][13]
단일책임의 원칙
단일책임의 원칙(SRP, Single Responsibility Principle)은 하나의 클래스는 각 하나의 목적 즉, 하나의 기능만 가지는 의미이다. 해당 클래스에서 제공하는 모든 서비스는 단 하나의 책임을 수행하는 데 집중되어야 한다는 원칙이다. 이는 책임 영역이 명확해지고 책임 변경에 있어 다른 책임의 변경으로 인한 연쇄 작용을 최소화하여 코드의 가독성 및 유지 보수에 있어서 유리하게 된다.[12][14]
개방폐쇄의 원칙
개방폐쇄의 원칙(OCP, Open Close Principle)은 소프트웨어의 모든 구성요소(컴포넌트, 클래스, 모듈, 함수)는 확장에는 열려있고, 변경에는 닫혀있어야 한다는 원칙이다. 즉, 요구 사항의 변경이나 추가사항의 발생에 기존 구성요소는 수정이 일어나지 말아야 하며 쉽게 확장이 가능하여 재사용할 수 있어야 한다는 원칙이다. 이는 재사용 코드를 만드는 기반이며 추상화와 다형성 객체지향의 장점을 극대화하는 중요한 원리가 된다.[12][14]
리스코브 치환의 원칙
리스코브 치환의 원칙(LSP, The Liskov Substitution)은 부모 클래스를 가리키는 포인터에 해당 클래스를 상속하는 자식 클래스를 할당하더라도 모든 기능이 정상적으로 작동해야 하며 자식 클래스의 상세 내부를 부모 클래스는 알 필요가 없다는 뜻이다. 부모 클래스와 자식 클래스의 서로 간의 영향을 최소화하여 자식 클래스는 언제나 자신의 부모 클래스를 대체하게끔 한다. 즉, 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 계획대로 잘 작동해야 한다는 것이다.[12][14]
인터페이스 분리의 원칙
인터페이스 분리의 원칙(ISP, Interface Segregation Principle)은 사용하지 않은 인터페이스의 구현을 하지 않고, 최소한의 인터페이스만을 사용해야 한다는 원칙이다. 인터페이스를 구체적이고 작은 단위들로 분리시켜 사용하게 끔하여 인터페이스 크기를 축소시켜 책임을 최소화하게 된다.[12][14]
의존성 역전의 원칙
의존성 역전의 원칙(DIP, Dependency Inversion Principle)은 클래스 사이에서의 의존관계가 존재하되, 구체적인 클래스에 의존하지 말고 추상화된 클래스에 의존하게 하는 원칙이다. 상위와 하위 객체는 모두 추상화에 의존해야 상위계층과 하위계층의 독립이 유지될 수 있다.[12][14]
특징
객체지향의 특징으로는 크게 캡슐화, 정보 은닉, 추상화, 상속성, 다형성이 있으며, 이 중 구조적 기법과 차별되는 개념은 캡슐화, 상속성, 다형성이 있다. 추가적으로 동적 바인딩이 있다.[15]
캡슐화
캡슐화(Encapsulation)란 데이터(속성)와 데이터를 처리하는 함수로 외부에서 쉽게 접근하지 못하게 하는 것이 핵심이다. 객체에 직접적인 접근을 막고 외부에서 내부에 정보를 직접접근하여 변경할 수 없으며, 객체가 제공하는 필드와 메소드를 통해서만 접근이 가능해진다. 이는 유지 보수나 확장 시 오류의 범위를 최소화하고 객체 내 정보 손상, 오용 방지, 조작법이 바뀌어도 사용방법 자체는 바뀌지 않고, 데이터가 변경되어도 다른 객체에 영향을 주지 못하기 때문에 독립성이 좋다. 객체를 모듈화할 수 있어 이식성이 좋다.[16] 구체적으로 객체지향에서 캡슐화는 사용자들에게 해당 객체의 기능(서비스)과 사용법만 제공하고 내부는 감추어 쉽게 사용할 수 있게 하는 개념이다. 소프트웨어 모듈인 객체 내부에 서로 관련된 데이터와 그 데이터를 조작할 수 있는 메서드를 같이 포장하는 방식으로, 그 안에 포함된 메서드만 사용하여 데이터 값을 변경할 수 있는 구조이다. 이러한 캡슐화는 클래스를 사용하여 정의하는데, 일종의 '블랙박스'와 같다. 즉 캡슐화는 클래스를 사용하여 서로 관련된 정보와 처리 방식을 같이 묶고, 외부에는 감추어두는 것이다. 객체지향 방식은 사용자가 모듈의 내부 구조를 알 필요도 없고 변경할 수도 없다. 어떤 기능을 하고, 어떻게 사용하는지만 알면 된다. 따라서 캡슐화를 통해 다음과 같은 장점을 얻을 수 있다.
- 데이터 보호 : 이용자가 데이터에 직접 접근하는 것을 차단하므로 객체 내 데이터 및 코드의 손상과 오용을 막고 안전하게 보호할 수 있다.
- 추상화 용이 : 추상화를 통해 프로그래밍 문제를 쉽게 개념화할 수 있다.
- 제공자와 이용자를 명확히 분리 : 객체 제공자와 객체 이용자(외부 객체)의 분담을 명확히 할 수 있다.
- 이용자에게 편리성 제공 : 메서드의 구현 방법이 바뀌어도 이를 사용하는 데 어려움이 없다.
- 사용법이 쉬움 : 세탁기 버튼의 기능만 알면 사용할 수 있는 것처럼, 메서드의 기능만 알면 객체를 사용할 수 있다.
- 변화에 대한 국지적 영향 : 객체 내의 데이터 구조가 바뀌어도 다른 객체에는 영향을 주지 않는다.
- 객체 간의 독립성 보장 : 캡슐화(데이터+메서드)로 인해 객체 사이의 독립성이 구조적으로 보장된다.
- 변경 용이성과 재사용성 증대 : 설계의 변경 용이성과 재사용성을 높여준다.
정보은닉
정보은닉(Information Hiding)은 캡슐화에서 가장 중요한 개념으로, 다른 객체에 자신의 정보를 숨기고 자신의 연산만을 통하여 접근을 허용하는 것이다.[15] 정보은닉은 외부(다른 객체)에서 객체의 내부(데이터)를 들여다볼 수 없다는 개념이다. 다른 객체가 한 객체 내의 데이터 값을 직접 참조하거나 접근할 수 없으므로 메서드를 통해 객체에 요청해서 값을 넘겨받아야 한다. 캡슐화는 소프트웨어 모듈인 객체 내부의 관련된 데이터와 메서드를 함께 포장하는 방식으로, 캡슐 내부와 외부를 구별 짓는다. 그러나 캡슐화했다고 해서 그 자체로 내부의 정보가 외부에 숨겨지지는 않는다. 이것을 해결할 수 있는 방법이 정보은닉의 원리이다. 정보은닉은 한 모듈에서 인터페이스와 구현을 명확히 분리하여 각 모듈의 내부 항목에 관한 정보는 감추고, 인터페이스를 통해서만 메시지를 전달함으로써 다른 모듈을 변경하지 못하도록 한다. 즉 모듈 안에 있는 자료구조와 메서드에 사용된 알고리즘은 외부에서 그 값을 직접 변경할 수 없고, 공개 인터페이스로 정의된 메서드를 통해서만 접근할 수 있다. 공개 인터페이스는 외부 객체와 정보를 주고받기 위한 통로로, 다른 객체에 무엇을 서비스해줄 수 있는지 알려준다. 정보은닉은 프로그래밍 언어별로 표기하는 방법이 다르다.
프로그래밍 언어별 정보은닉의 표기 방법 구분 UML C++ 자바 공개 + public public 부분 공개 # protected protected 은닉 - private private
상속성
일반적으로 어떤 개념을 계층화하여 분류하면 전체 그림이 그려져 더 쉽게 이해를 할 수 있다. 소프트웨어 개발자들도 클래스 간의 관계를 계층화하고 분류하는데 이런 개념이 바로 상속(inheritance)이다. 상속성(Inheritance)은 이미 정의된 상위 클래스의 모든 속성과 연산을 하위 클래스가 물려받는 것을 의미하므로 하위 클래스는 상위 클래스의 모든 속성과 연산을 자신의 클래스 내에서 다시 정의하지 않고서도 즉시 자신의 속성으로 사용할 수 있게 된다. 이때 물려주는 클래스를 상위 클래스 또는 부모 클래스라고 하고, 물려받는 클래스를 하위 클래스 또는 자식 클래스라고 한다. 또한, 물려받은 속성과 연산 외에 새로운 속성과 연산을 추가하여 사용할 수 있다. 상위 클래스와 하위 클래스가 서로 공유할 수 있기에 객체와 클래스의 재사용이 증대되는 중요한 개념이다. 한편 다중상속(Multiple inheritance)은 한 개의 클래스가 두 개 이상의 상위 클래스로부터 속성과 연산을 상속받는 것을 말한다.[15] 상속은 다음과 같은 장점을 제공한다.
- 이해 용이 : 개별 클래스를 상속 관계로 묶음으로써 클래스 간의 체계화된 전체 구조를 파악하기 쉽다.
- 재사용성 증대 : 데이터와 메서드의 오버로딩을 피하고 기존 클래스에 있는 것을 재사용할 수 있다.
- 확장 용이 : 새로운 클래스, 데이터, 메서드를 추가하기가 쉽다.
- 유지보수 용이 : 데이터와 메서드를 변경할 때 상위에 있는 것만 수정하여 전체적으로 일관성을 유지할 수 있다.
- 추상화 가능 : 일반화(generalization), 특수화(specialization)의 관계를 통해 추상화 단계를 표현할 수 있다.
다형성
다형성(Polymorphism)은 메시지에 의해 개체(클래스)가 연산을 수행하게 될 때 하나의 메시지에 대해 각 객체가 가지고 있는 고유한 특성으로 다른 여러 형태로 재구성되는 것을 말한다. 하나의 행위가 결과를 여러 개 만들어낸다. 이는 프로그램 측면에서 같은 메시지에 대해 이 메시지를 수신하는 객체마다 다르게 행동하는 것을 의미한다. 그리고 똑같은 + 기호가 다른 용도로 사용되는 것처럼 동일한 메서드 이름을 사용하지만 메서드에 대해 클래스마다 모두 다르게 구현되는 개념이 다형성이다. 자바의 오버로드(Overload) 또는 오버라이드(Override)이 다형성의 대표적인 예라 할 수 있고, 이것을 구현하는 걸 오버로딩(Overloading)과 오버라이딩(Overriding)이라고 한다.[17]
- 오버로딩(overloading) : 한 클래스에 이름이 동일한 메서드가 중복 정의되어 있는 경우를 의미한다. 메서드명이 같을 때는 매개변수를 다르게 하여 구별한다. 이름이 동일한 메서드가 호출되었을 때 이를 구별할 수 있는 매개변수 타입이나 개수 같은 요소를 시그니처(signature)라 한다. 문자열을 연결하는 연결자로도 사용할 수 있다. 연산자 하나를 다른 용도로 다시 중복 정의하여 사용하는 것인데, 이를 연산자 오버로딩이라고 한다. 상속 구조에서 메서드 오버로딩은 한 클래스 안의 메서드 오버로딩과 사용 형태가 다르다. 한 클래스에서는 매개변수의 타입과 개수로 구별했지만 상속 구조에서는 메서드명뿐 아니라 매개변수의 타입과 개수까지 같다. 이때는 조건이 하나 붙는데, 상위(부모) 클래스가 추상 클래스(abstract class)여야 하고, 추상 클래스 내의 메서드도 추상 메서드(abstract method)여야 한다. 상위 클래스인 도형이 추상 클래스이고, area()도 추상 메서드이다. 따라서 area()에 대한 구현 부분이 없다. 그러므로 하위(자식) 클래스인 삼각형, 사각형, 원에서는 각 면적을 구하는 공식을 사용해 다르게 구현하면 된다. 그리고 면적 구하는 area() 메서드가 하위 클래스마다 다르게 구현되므로 특정 객체의 면적 구하는 메서드는 프로그램의 실행 시간에 호출된다. 이러한 의미에서 다형성을 동적 바인딩(dynamic binding) 또는 늦은 바인딩(late binding)이라고도 한다.
- 오버라이딩(overriding) : 메서드 오버로딩처럼 상속 구조에서 발생한다. 메서드 오버로딩이 추상 클래스와 추상 메서드만 사용할 수 있는 반면, 메서드 오버라이딩은 추상 클래스와 일반 클래스를 모두 다 사용할 수 있다. 또한 상위 클래스에서 정의한 일반 메서드의 구현을 하위 클래스에서 모두 무시하고 다시 재정의해서 사용할 수 있다. 그러므로 상위 클래스에 정의된 메서드와 하위 클래스에서 사용된 이 메서드는 이름은 같지만 구현이 전혀 다르다. 메서드를 오버라이딩하면 상위 클래스의 메서드는 은닉(무시)되고, 하위 클래스의 메서드가 사용된다.
추상화
추상화(Abstraction)는 불필요한 부분을 생략하고 객체 속성 중 공통적이고 중요한 것에만 중점을 두어 개략화, 즉 모델화하는 것이다. 객체들의 공통적 특성을 파악하여 필요 없는 특성을 제거하는 과정을 가리킨다. 이 과정은 복잡한 문제를 해결하기 위한 가장 기본방법이며 완전한 시스템 구축을 하기 전에 시스템 구조 및 구성을 가시적으로 볼 수 있고, 그 시스템과 유사한 모델을 만들어 여러 가지 요인을 테스트할 수 있다.[15][17]
특징
장점
- 재사용 및 생산성: 남이 만든 클래스를 가져와 이용할 수 있고 상속을 통하여 확장 사용이 가능하다. 즉, 프로그래밍 코드의 재사용을 극대화하여 한 프로그램 내에서 하위 클레스들이 상위 클래스의 속성을 표현한 코드를 재사용하며, 새로운 프로그램 개발 시 기존 프로그램이 갖고 있는 클래스 상속 구조에서 많은 클래스들을 소프트웨어 IC로 재사용하여 생산성 또한 높일 수 있다.[18][19]
- 유지 보수: 상속을 통한 수정, 추가가 용이하며 캡슐화로 그 함수의 세부정보가 은폐되어 있어 주변에 미치는 영향을 최소화한다. 독립성의 증대는 객체지향 프로그래밍에서 수정해야 할 부분이 클래스 내부에 멤버 변수나 메서드로 존재하기 때문에 해당 부분만 수정할 수 있게 된다.[18][19]
- 대형 프로젝트에 적합: 객체지향 프로그래밍의 특성 덕분에 면밀한 자료분석, 개발 시간 단축, 좀 더 복잡한 코딩이 가능하고 클래스 단위로 모듈화를 시켜 개발할 수 있으므로 업무 분담이 쉬워 대형 프로젝트일수록 적합한 장점을 가지고 있다.[6][18]
단점
- 복잡성: 다중 상속으로 인하여 클래스의 상속관계에 혼란을 야기한다면 코드의 난이도가 급상승할 수 있다. 이 상태를 상태는 '라자냐 코드'라고 불리는 편이다. 그래서 대다수의 객체지향 프로그래밍 언어들은 다중 상속을 지원하지 않았고 실제 구현이 전혀 없는 껍데기인 인터페이스만 추가로 상속할 수 있게 했는데, 이 또한 코드의 재 사용성을 현저하게 떨어뜨리는 문제가 있어 최근엔 믹스인(mixin)이나 트레이트(trait) 같이 다중 상속을 할 수 있는 방법을 찾고 있다.[6]
- 캡슐화와 격리 구조 설계로 인한 성능 하락: 거의 대부분의 객체지향 언어에서 기능을 묶으면 결국 함수 호출이 추가로 들어가거나 계산식 중간에 포인터 연산 등이 필요해지며, 멤버 함수 같은 경우 어느 객체의 함수인지 지정해야 하기 때문에 추가 포인터 크기와 연산 비용이 들어간다. 인라인 함수와 컴파일러 최적화, 특히 RVO(Return Value Optimization) 등의 방법으로 어느 정도는 격차를 줄여주나 역시 그냥 절차적 프로그래밍보다는 무거워지게 되어 느린 실행 속도를 가지게 된다. 또한 객체 하나하나를 따로 나누게 되는 것을 주력하다 보니 비슷한 처리를 하는 코드도 독립성에 의해 서로를 건드릴 수 없게 되었고 이를 해결하기 위해 'getter'(접근자: 값을 반환하는 메소드), 'setter'(설정자: 필드에 값을 저장하는 메소드)사용이 너무 많아졌다. 이 과정에서 캡슐화가 깨짐으로 정보 은닉 특성 또한 약해져 의미가 퇴색되었고, 다른 프로그래밍 패러다임이 필요해졌다.[6]
- 성능 격차: 객체 하나하나를 따로 캡슐화시키고 상속시 부모만 같으면 자식의 종류를 신경 쓰지 않다 보니 각자의 메모리 크기가 달라지며, 결국 고정된 연속 메모리에 담을 수가 없게 된다. 메모리 할당을 배열로 하지 못하게 되니 따로따로 생성하게 되고 이렇게 각각의 객체의 생성과 파괴가 반복되면 메모리 단편화라는 문제가 생기게 된다. 가비지 컬렉션 기능이 만들어진 이유 중 하나이기도 하다. 또 연속 메모리를 쓰기 힘들어진다는 건 캐시의 효율적 사용에 큰 문제가 생긴다는 뜻이기도 해서 성능 격차는 더 벌어지게 된다.[6]
지원 언어
객체지향 지원 언어는 다음과 같다.
활용
- 객체지향 언어(object-oriented language) : 객체 중심 프로그래밍을 위해 사용되는 언어로 연산문들의 집합으로 이루어진다. 객체는 자료와 프로그램의 추상화로써 구현되는데, 연산하고자 하는 여러 가지 객체들 속에서 그 연산들의 정의가 나타나며 동시에 객체에 대한 정의는 그들 연산의 여러 가지 측면에서 나타난다.
- 객체지향 설계(object oriented design) : 객체지향 기술(object oriented technology)을 적용하여 실세계를 분석하는 것으로 사물이나 현상을 객체지향 프로그래밍이 가능하도록 객체로 표현하는 데 필요한 기술과 기호 그리고 적용 방법론이다. 객체지향 설계는 클래스, 객체의 구조와 연관 관계를 기술한 객체 모델을 논리적 시각으로 생성한 분석 단계의 객체 모델을 구현의 고려 사항을 포함하여 재정의하는 것이다. 객체지향 설계는 실세계의 시스템을 분석하는 것으로 많은 객체를 포함하는 모델을 결과물로 얻으며, 모델에 표시된 각각의 객체는 실세계에 존재하는 객체들과 하나씩 대응된다. 객체지향 설계를 통해 문제의 도메인에서 모델의 도메인으로 변환시키는 과정을 통해 분석이 이루어진다.
- 객체지향 질의모델 : 관계 데이터베이스에서는 질의 대상과 결과가 모두 릴레이션이지만, 객체지향 데이터베이스에서는 질의 대상이 클래스이고 질의 결과는 클래스에 속하는 객체 집합이다. 객체지향 데이터베이스에서는 객체지향 개념을 기반으로 클래스, 속성, 메소드, 객체 등을 이용해 질의를 표현한다. 객체지향 데이터베이스에서 클래스 하나 또는 클래스 하나와 해당 클래스의 하위클래스 전체를 대상으로 하는 질의를 단일 오퍼랜드(single operand) 질의라 한다. 그리고 여러 클래스를 대상으로 하는 질의를 다중 오퍼랜드(multiple operand) 질의라고 한다. 관계 데이터베이스와 달리 객체지향 데이터베이스의 데이터 모델과 질의어는 표준화되지 못했다. 특히 객체지향의 개념을 완벽하게 표현하면서도 쉽게 사용할 수 있는 질의어가 개발되지 않아, 널리 사용되지 못하고 특수한 몇몇 분야에서만 사용되고 있다.
- 객체지향 그래픽스(object-oriented graphics) : 직선, 곡선, 원, 직사각형과 같은 구조적인 도형 요소(graphics primitive)를 기본 요소로 사용하는 구조화된 컴퓨터 그래픽스이다. 컴퓨터 지원 설계(CAD)나 도면 작성과 같은 애플리케이션에 사용되며, 이미지를 구성하는 객체를 생성하기 위한 일련의 명령 집합에 의해 이미지를 수학적으로 그려 내므로 계층화, 회전 및 확대가 비교적 쉽다. 객체지향 그래픽스에서는 객체를 각각 완전한 단위로 조작하는 데 비해, 비트맵 그래픽스에서는 일정한 패턴으로 배열된 흑백 또는 컬러 도트로 그래픽이 표현되므로 선 또는 원형의 도트를 다시 페인트할 필요가 있다.
- 객체지향 데이터모델 : 객체지향 데이터 모델은 객체와 객체 식별자, 속성과 메소드, 클래스, 클래스 계층 및 상속, 복합 객체 등을 지원하는 객체지향 개념에 기반을 둔 데이터 모델이다. 객체지향 모델은 다양한 응용 분야의 데이터 모델링을 위한 새로운 요구 사항을 지원할 뿐만 아니라, 의미적으로 관계가 있는 데이터베이스 구조를 표현하기 위한 강력한 설계 기능을 제공한다.
- 객체지향 인터페이스 : 사용자 인터페이스의 하나로, 시스템의 구성 요소가 아이콘과 같은 화면상에 표시되는 가시적 실체에 의해 표현되는 것이다. 예를 들면, 매킨토시 파인더는 파일 시스템에 대한 객체지향 인터페이스를 문서, 파일 폴더, 디스크 드라이브 등의 이미지를 화면에 표시함으로써 제공한다. 객체지향 인터페이스는 반드시 객체지향 프로그래밍(OOP)과의 어떤 관계를 의미하는 것은 아니다.
- 객체지향 데이터베이스 : 일반적으로 많이 사용되는 관계 데이터베이스는 현실 세계의 데이터를 관계 데이터 모델의 구조적 특성을 만족하면서, 정규화 규칙을 따르는 릴레이션으로 저장하고 관리한다. 사용자는 SQL을 사용해 관계 데이터베이스를 정의하거나 조작 및 제어할 수 있다. 하지만 관계 데이터베이스는 관계 데이터 모델의 기능적 제약조건과 SQL의 표현력 한계로 인해 CAD, CAM, CAE, CASE 등의 다양한 응용 분야에 부적합하다는 문제가 제기되었다. 이런 이유로 1980년대 초반부터 관계 데이터베이스와 다른 형태의 데이터베이스를 구축하기 위한 새로운 데이터 모델에 대한 연구가 진행되어 왔는데, 이 중 하나가 객체지향 데이터 모델이다.
각주
- ↑ 이수호, 〈객체 지향〉, 《인코뎀》, 2020-10-21
- ↑ 〈객체지향 언어의 장점과 단점, 개념, 종류, 절차지향 언어와의 비교〉, 《티스토리》, 2020-10-28
- ↑ 〈객체지향〉, 《생활코딩》, 2014-04-21
- ↑ 재희 jaiyah, 〈객체지향 프로그래밍이란?〉, 《티스토리》
- ↑ 〈Object Oriented〉, 《네이버 지식백과》
- ↑ 6.0 6.1 6.2 6.3 6.4 6.5 〈객체 지향 프로그래밍〉, 《나무위키》
- ↑ 7.0 7.1 DLGNDUD, 〈객체지향의 역사와 이해〉, 《세다트리스 인공지능연구소》, 2020-08-29
- ↑ 8.0 8.1 8.2 8.3 8.4 8.5 〈객체 지향 프로그래밍〉, 《위키백과》
- ↑ 〈이름공간〉, 《위키백과》
- ↑ 개발자를 꿈꾸는 프로그래머, 〈Java - (5) 객체란? 객체 지향 프로그래밍의 특징〉, 《티스토리》, 2016-05-04
- ↑ 현승, 〈객체 지향 기법의 구성 요소〉, 《네이버 블로그》, 2011-08-20
- ↑ 12.0 12.1 12.2 12.3 12.4 12.5 allocProc, 〈객체지향 5원칙 : SOLID〉, 《medium》, 2020-05-28
- ↑ 〈객체지향 개발 5대 원리: SOLID〉, 《넥스트리》, 2021-06-06
- ↑ 14.0 14.1 14.2 14.3 14.4 TonyChoi Ms_Tony, 〈객체지향의 3요소 5원칙〉, 《티스토리》, 2017-12-07
- ↑ 15.0 15.1 15.2 15.3 코딩팩토리 〈(C++) 객체지향 언어의 5가지 특징〉, 《티스토리》, 2019-03-01
- ↑ radait, 〈자바(Java) 캡슐화(Encapsulation)란? 무엇인가?〉, 《티스토리》, 2019-05-21
- ↑ 17.0 17.1 radait, 〈객체지향언어란? (특징, 장점, 단점, 종류)〉, 《티스토리》, 2019-05-20
- ↑ 18.0 18.1 18.2 koyo, 〈객체 지향 프로그래밍이 뭔가요?〉, 《velog》, 2020-11-26
- ↑ 19.0 19.1 sesok808, 〈객체지향 언어의 개념 및 특징, 장단점〉, 《티스토리》, 2014-03-26
참고 자료
- 이수호, 〈객체 지향〉, 《인코뎀》, 2020-10-21
- 〈객체지향 언어의 장점과 단점, 개념, 종류, 절차지향 언어와의 비교〉, 《티스토리》, 2020-10-28
- 〈객체지향〉, 《생활코딩》, 2014-04-21
- 재희 jaiyah, 〈객체지향 프로그래밍이란?〉, 《티스토리》
- 〈객체 지향 프로그래밍〉, 《나무위키》
- DLGNDUD, 〈객체지향의 역사와 이해〉, 《세다트리스 인공지능연구소》, 2020-08-29
- 〈이름공간〉, 《위키백과》
- 개발자를 꿈꾸는 프로그래머, 〈Java - (5) 객체란? 객체 지향 프로그래밍의 특징〉, 《티스토리》, 2016-05-04
- 현승, 〈객체 지향 기법의 구성 요소〉, 《네이버 블로그》, 2011-08-20
- allocProc, 〈객체지향 5원칙 : SOLID〉, 《medium》, 2020-05-28
- 〈객체지향 개발 5대 원리: SOLID〉, 《넥스트리》, 2021-06-06
- TonyChoi Ms_Tony, 〈객체지향의 3요소 5원칙〉, 《티스토리》, 2017-12-07
- 코딩팩토리 〈(C++) 객체지향 언어의 5가지 특징〉, 《티스토리》, 2019-03-01
- radait, 〈자바(Java) 캡슐화(Encapsulation)란? 무엇인가?〉, 《티스토리》, 2019-05-21
- radait, 〈객체지향언어란? (특징, 장점, 단점, 종류)〉, 《티스토리》, 2019-05-20
- ammff, 〈(언어기초) 동적/정적 바인딩이란? (쉬움주의)〉, 《티스토리》, 2016-05-22
- koyo, 〈객체 지향 프로그래밍이 뭔가요?〉, 《velog》, 2020-11-26
- sesok808, 〈객체지향 언어의 개념 및 특징, 장단점〉, 《티스토리》, 2014-03-26
- 〈Object Oriented〉, 《네이버 지식백과》
같이 보기