soominkim Study
article thumbnail
Published 2022. 12. 5. 22:31
[Java] OOP(ObejectOrientedProgramming) Java
728x90

 

해당 글은 나무 위키의 객체 지향 프로그래밍을 정리했습니다.

 

객체 지향 프로그래밍 - 나무위키

프로그램의 세부 구현을 외부로 드러나지 않도록 특정 모듈 내부로 감추는 것이다. 내부의 구현은 감추고 모듈 내에서의 응집도를 높이며, 외부로의 노출을 최소화하여 모듈 간의 결합도를 떨

namu.wiki

 

OOP(Object-Oriented-Programmin) 

프로그램 설계 방법론이자 개념의 일종으로, 명령형 프로그래밍에 속한다. 프로그램은 단순히 데이터와 처리 방법으로 나누는 것이 아니라 프로그램을 수많은 객체(Object)라는 기본 단위로 나누고 이들의 상호작용으로 서술하는 방식이다.

여기서 객체란 하나의 역할을 수행하는 메서드(Method)와 변수(Data)의 묶음으로 봐야 한다.

 

객체지향을 설명할 때 Java 위주로 소개하는 이유는 서술의 편의상이며 Java만이 객체지향 언어에 속하는 것은 아님을 기억해야 한다. 객체지향은 특정 언어를 지칭하는 것이 아닌 개념이라는 것을 기억해야 한다.

 

 

1. OOP의 시작

초기 프로그래밍 방식은 절차적 프로그래밍 방식이었다. 학교 대사전의 고등학생 알고리즘처럼 입력을 받아 명시된 순서대로 처리한 다음 그 결과를 내는 것뿐이라는 생각이 지배적이었고 프로그램을 명령어의 모음으로 인식했다.

또한 프로그래밍이란 어떻게 어떤 논리를 어떤 순서대로 써나가는 것인가로 간주되었고 이는 프로그램 자체가 가지는 기능만을 생각할 뿐 이 프로그램이 대체 어떤 데이터를 취급하는 것인가에는 관심이 없었다.

 

그러나 해당 방식은 간단한 알고리즘이면 괜찮지만 조금만 복잡해지면 순서도로 나타내는 것이 불가능할 정도로 꼬인 스파게티 코드가 되기 일쑤였다.

 

이 문제를 해결하기 위해 에츠허르 다익스트라가 1968년 GOTO문의 해로움이라는 논문에서 프로그램을 프로시저(Procedure) 단위로 나누고 프로시저끼리 호출하는 구조적 프로그래밍 방식을 제안하면서 위기를 벗어나게 된다. 이렇게 타 큰 문제를 해결하기 위해 그것을 몇 개의 작은 문제들로 나누어 해결하는 것을 하향식(Top-down) 방식이라고 한다.

 

하지만 함수는 데이터의 처리 방법을 구조화했을 뿐 데이터 자체는 구조화하지 못했고 이는 전역 네임스페이스 포화 문제를 낳게 되었고 더 나아가 실행 콘텍스트를 저장할 마땅한 방법이 없어지는 문제가 생겼다. 실행 콘텍스트는 GUI에서 중요해지는데 어떤 창의 현재 상태에 따라 함수가 실행해야 하는 동작 방식이 달라지기 때문이었다. 

 

이런 문제를 해결하기 위해 더 근본적인 해결책이 필요했고 해결책으로 등장한 것이 바로 객체지향 프로그래밍이다.

큰 문제를 작게 쪼개는 것이 아니라 먼저 작은 문제들을 해결할 수 있는 객체들을 만든 뒤 이 객체들을 조합해서 큰 문제를 해결하는 상향식(Bottom-up) 해결법을 도입한 것이다.

 

이 객체란 것은 한번 독립성/신뢰성이 높게 만들어 놓기만 하면 그 이후엔 수정 없이 재사용할 수 있으므로 개발기간과 비용이 대폭 줄어들게 된다.

 

객체 지향 프로그래밍은 등장 당시 기존의 절차적 프로그래밍과 비교해 매우 이질적이고 당시 컴퓨터의 처리 능력이 별로 좋지 않아서 큰 주목을 받지 못했다. 그러나 GUI가 등장하면서 객체 지향 프로그래밍은 급부상하였다.

이렇게 주목받은 객체 지향 프로그램은 많은 과정을 거쳐가며 현대에 들어 그 정도가 매우 복잡해졌고 이를 간결하게 정리할 필요성이 생긴 관계로 등장한 것이 바로 디자인 패턴이다.

 

2. 언어 종류

① Smalltalk 언어

     - 앨런 케이가 1972년 팔로 알토 리서치 센터(PARC)에서 만든 언어로 OOP를 최초로 지원했다.

        누구나 쉽게 사용할 수 있는 컴퓨터를 만들려는 목적에 따라 만들어졌다.

② Ruby와 Python

     - Ruby : Smalltalk 계보를 잇는 순수 객체지향 언어로 기존의 C++이나 Java에 비해서 난이도가 쉽다.

     - Python : 순수 객체지향 언어로 Ruby와 비슷한 구조를 가지고 있다.

③ C++과 Objective - C

     - 브레스 콕스와 톰 러브는 스몰토크를 보고 새로운 시각으로 객체지향을 바라보았고 그것은 소스 코드의 수정 없는 재           활용이었다. 그들은 이 개념을 실제로 언에 적용하여 1983년에 객체 처리 방식을 C언어에 추가했다.

       이렇게 표준 언어에 기능을 추가하는 것을 슈퍼셋(Superset)이라 하며 반대로 표준언어의 기능을 축소한 것을 서브셋         (Subset)이라 한다.

     - C++ : 1983년 비아르네 스트로 우스트 루프가 C언어를 확장시킨 언어이다.

     - Objective-C : Mac OS X의 기반이 된 언어이다.

④ 기타 언어(Java, C#, Objective-Pascal)

 

3. 기본 구성 요소

① 클래스(Class) 

 - 같은 종류의 집단에 속하는 속성(Attribute)과 행위(Behavior)를 정의한 것으로 객체지향 프로그램의 기본적인 사용자 정의 데이터형(user defined data type)이라고 할 수 있다. 예를 들어 아이폰 SE가 있다고 생각해보자. 아이폰 SE에는 어떤 것이 들어가고 어떤 기능이 있어야 한다고 우리는 만들기 전 설계라는 것을 할 것이다. 그리고 아이폰 SE를 만들기 위한 설계도가 탄생한다. 클래스는 물건을 만들기 위한 일종의 설계도와 같다.

② 객체(Object)

 - 클래스의 인스턴스로 객체는 자신 고유의 속성(Attribute)을 가지며 클래스에서 정의한 행위(Behavior)를 수행할 수 있다. 객체의 행위는 클래스에 정의된 행위에 대한 정의를 공유함으로써 메모리를 경제적으로 사용한다. 예를 들어 위에서 언급한 아이폰 SE를 생각해보자. 아이폰 SE를 만들기 위한 설계도인 클래스로 우리는 아이폰 SE를 만들 것이다. 그리고 아이폰 SE가 실제 소비자 혹은 나에게 하나의 물건이 되어 돌아온다. 이렇게 클래스를 통해 만들어진 실체화된 물건을 우리는 객체라고 한다.

③ 메서드(Method), 메시지(Message)

 - 클래스로부터 생성된 객체를 사용하는 방법으로 객체에 명령을 내리는 메시지라 할 수 있다.

 

4. 특징

4-1. 추상화(Abstraction)

추상화는 목적과 관련이 없는 부분을 제거하여 필요한 부분만을 표현하기 위한 개념이다.

다시 아이폰 SE를 떠올려보자. 아이폰 SE는 결국은 어떤 폰의 한 종류인가?

바로 아이폰일 것이다. 그럼 아이폰은 우리가 통칭 무엇이라 부르는가?

스마트폰일 것이다. 그렇다면 스마트폰은 다시 무엇이라 부르는가?

휴대전화라고 부를 것이다.

이처럼 상위 개념을 만들어 나아가는 행위 자체를 우리는 추상화(Abstraction)이라 한다.

 

우리가 실생활에 쓰이는 예로 생각하면 추상화는 깊은 고민을 하지 않고 쉽게 도출할 수 있다. 하지만 프로그래밍에서의 추상화는 그리 녹록지 않을 것이다. 추상이란 단어의 뜻을 생각해보자. 추상은 어떠한 존재가 가지고 있는 여러 가지의 속성 중에서 특정한 속성을 가려내어 포착하는 것을 의미한다. 즉 추상화라는 것은 그 존재가 가지고 있는 가장 특징적인 속성을 파악해나가는 것을 의미하며 올바른 상위 개념의 속성은 그 개념의 하위 개념들에게 공통적으로 적용할 수 있는 속성이 된다.

 

4-2. 상속(Inheritance)

상속은 자식 클래스가 부모 클래스의 특성과 기능을 그대로 물려받는 것을 말한다. 예를 들어 이제는 친숙할 아이폰을 떠올려보자. 아이폰의 충전기 단자는 모두 8 핀이며 가운데 동그란 홈버튼 그리고 뒷면의 애플 로고가 박혀있다. 이런 외관적인 모습뿐만 아니라 공통적으로 safari를 탑재하고 있고 기본적으로 다운로드되는 앱과 제공하는 기능들이 똑같다. 이처럼 아이폰이라는 부모 클래스에서 공통된 속성이나 기능을 가지고 파생된 자식 클래스(아이폰 SE, 아이폰 7, 아이폰 14 등)들에게 있는 기능을 프로그래밍에서는 상속이라 말한다.

 

4-3. 캡슐화(Encapsulation)

변수와 함수를 하나의 단위로 묶는 것을 의미하며 데이터의 번들링(Bundling)이라 한다.

어떠한 클래스를 사용할 때 내부 동작이 어떻게 돌아가는지 모르더라도 사용법만 알면 쓸 수 있도록 클래스 내부를 감추는 기법이다. 클래스를 캡슐화 함으로써 클래스를 사용하는 쪽에서는 머리 아프게 클래스의 내부 로직을 파악할 필요가 없어지고 제공하는 쪽에서는 변수나 메소드를 원하는 대로 감출 수 있기 때문에 필요 이상의 변수나 메서드가 클래스 외부로 노출되는 것을 방어하여 보안을 챙길 수 있다. 이렇게 클래스 내부의 데이터를 감추는 것을 정보 은닉(Information Hiding)이라고 하며 Java에서는 접근 제한자가 해당 역할을 수행한다.

 

4-4. 다형성(Polymorphism)

하나의 변수 또는 함수가 상황에 따라 다른 의미로 해석될 수 있는 것을 말한다.

대표적으로 오버로딩(Overloading)과 추상 클래스(Abstract Class) 그리고 인터페이스(Interface)가 있다.

다형성에는 총 4가지가 있으며 종류는 다음과 같다.

 

① 서브타입 다형성(subtype polymorphism / inclusion polymorphism / subtyping)

우리가 일반적으로 접하는 OOP의 그것으로 쉽게 말해 메서드 오버 라이딩(Method Overriding)을 수행한다.

상위 클래스의 참조변수가 어떤 하위 클래스의 객체를 참조하느냐에 따라 호출되는 메서드가 달리 진다.

② 매개변수 다형성(parametric polymorphism)

 - 템플릿(Template) : C++에서 사용하는 개념으로 타입 매개변수를 입력한 타입으로 치환한 코드를 생성하는 방식

 - 제네릭(Generic) : Java와 C#에 도입된 개념으로 지정한 타입 매개변수에 해당하는 타입만을 사용하겠다고 약속하는 방식

③ 임시 다형성(ad hoc polymorphism)

 - 함수 오버 로딩(Function Overloading)

 - 연산자 오버 로딩(Operator Overloading)

④ 강제 다형성(coercion polymorphsim)

 - 묵시적 형 변환(Implicit type coercion)

 - 명시적 형 변환(Explicit type coercion)

 

5. 장단점

5-1. 장점

① 코드 재사용성

     - 모듈화 된 객체를 기반으로 코드가 작성되기 때문에 재사용이 용이하다.

② 간편한 유지보수

     - 객체를 수정할 경우 해당 객체를 사용하는 모든 로직에 일괄적으로 적용되니 중복 코드에 대한 관리가 간단해진다.

③ 큰 규모의 프로그래밍에 유리

     - 객체, 모듈 단위로 구분되는 특징으로 인해 업무 분장이 쉽고 각 모듈의 연관성을 도식하기 용이하다.

 

5-1. 단점

① 비교적 느린 속도

     - 절차 지향과 달리 객체지향은 각 객체의 의존 관계로 인해 대체적으로 속도가 느리다.

② 높은 설계역량 요구

     - 모듈 단위의 상호작용으로 이루어진 방식이기 때문에 정확한 명세와 설계의 중요성이 부각된다.

③ 코드의 잠재적인 복잡성

     - 높은 수준의 설계역량 요구와 더불어 추상 객체, 상속, 인터페이스 등 복잡한 개념과 그 활용은 코드의 구조를 파악하기 어렵게 만든다.

 

 

728x90

'Java' 카테고리의 다른 글

[Java] Arrays.sort  (0) 2023.01.12
[Java] indexOf/lastIndexOF  (0) 2023.01.12
[Java] Array (1)  (0) 2022.11.23
[Java] 메모리 구조 (Static,Stack,Heap)  (0) 2022.11.07
[Java] Class 와 Instance 그리고 Object  (0) 2022.11.07
profile

soominkim Study

@soominkim

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그