본문 바로가기
언어공부/JAVA&SPRING

객체 지향 프로그래밍이란?

by hobbiz 2020. 7. 8.
반응형

 

 

 

객체 지향 프로그래밍이란?

 

객체 지향 프로그래밍(영어: Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍 패러다임 중 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.

객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다. 또한 프로그래밍을 더 배우기 쉽게 하고 소프트웨어 개발과 보수를 간편하게 하며, 보다 직관적인 코드 분석을 가능하게 하는 장점을 갖고 있다. 그러나 지나친 프로그램의 객체화 경향은 실제 세계의 모습을 그대로 반영하지 못한다는 비판을 받기도 한다.

프로그램 설계방법론이자 개념의 일종.

프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아니라, 프로그램을 수많은 '객체'라는 기본 단위로 나누고 이 객체들의 상호작용으로 서술하는 방식이다. 객체란 하나의 역할을 수행하는 '메소드와 변수(데이터)'의 묶음으로 봐야 한다.

서술의 편의상 객체지향을 Java 위주로 소개하고 있고 class나 public 같은 용어를 사용했다. 이 경우만 객체지향에 해당하는 것으로 오해하지 않게 주의해야 한다. 모든 언어가 class나 접근 제한자(public이나 private)를 사용하지는 않는다. 대표적인 예로 JavaScript는 프로토타입 객체지향을 사용하고 있고 Python의 경우에는 접근제한자가 없다. 객체지향은 특정 언어가 아니라 개념이다. class는 객체이며 struct는 객체가 아닌 데이터의 집합이라는 설명 역시 틀렸고, 특정 언어가 객체지향 언어라는 말도 완전히 틀린 표현이다.

 

 

객체 지향 프로그래밍의 역사

초기 프로그래밍 방식은 절차적 프로그래밍 방식이었다. 학교대사전 고등학생 알고리즘처럼 입력을 받아 명시된 순서대로 처리한 다음, 그 결과를 내는 것뿐이라는 생각이 지배적이었다. 프로그램을 명령어의 모음으로 인식한 것이다. 또한 프로그래밍이란 어떻게 어떤 논리를 어떤 순서대로 써나가는 것인가로 간주되었다. 즉, 프로그램 자체가 가지는 기능에 대해서만 신경을 썼지, 이 프로그램이 대체 어떤 데이터를 취급하는 것인가에는 그다지 관심이 없었던 것이다.

그러나, 이 방식은 간단한 알고리즘이면 모를까 조금만 복잡해지면 순서도로 나타내는 것이 불가능할 정도로 꼬인 "스파게티 코드"를 만들게 된다. 간단히 말해서 스타크래프트를 위의 순서도로 그려야 된다고 생각해봐라! 이렇게 꼬여버린 코드는 다른 사람이 보고 이해하는 것이 거의 불가능할 뿐더러 심지어는 작성한 본인조차도 유지보수에 어려움을 겪게 된다. 명령어의 양이 많아지는 것은 기본이고, 특정 코드 부분은 어디에 사용되는 코드고 해당 코드 부분은 어디까지 이어지는지의 흐름을 파악하기도 힘들어지며, 중복 코드 대처도 매우 골치아프다. OOP를 사용하면 코드의 중복을 어느 정도 줄일 수 있고 입력 코드, 계산 코드와 결과 출력 코드 등 코드의 역할 분담을 좀 더 확실하게 할 수 있어서 가독성이 높아질 수 있다.

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


하지만 함수는 데이터의 처리 방법을 구조화했을뿐, 데이터 자체는 구조화하지 못했다. 이는 전역 네임스페이스 포화 문제(변수 이름을 다 써서 이름 짓기도 힘든 상황(...))를 낳게 되었다.[1] 게다가 실행 콘텍스트를 저장할 마땅한 방법이 없어지는 문제가 생겼다. 실행 콘텍스트는 특히 GUI에서 중요해지는데 어떤 창의 현재 상태에 따라 함수가 실행해야 하는 동작 방식이 달라지기 때문이다. 또한 엉뚱한 데이터가 엉뚱한 함수에 전달돼서 데이터를 오염시키는 문제가 발생하고 그런 가능성 때문에 프로그래머가 한 함수의 작동에 영향을 받는 변수를 조사해야 할 때 모든 변수를 다 조사해야 하는 어려움에 봉착했다. 변수의 갯수가 수백 개 이하인 코드에서야 이게 사람의 힘으로 가능했지 코드의 덩치가 커지면서 함수가 접근할 수 있는 데이터의 범위에 명시적인 제한을 걸어야 하는 상황이 도래했다. 이를 지역 변수나 구조체(struct) 등으로 어찌 제어하고 있기는 했지만 더 근본적인 해결책이 필요했다.

이를 극복하기 위한 대안으로 등장한 것이 바로 객체 지향 프로그래밍이다. 큰 문제를 작게 쪼개는 것이 아니라, 먼저 작은 문제들을 해결할 수 있는 객체들을 만든 뒤, 이 객체들을 조합해서 큰 문제를 해결하는 상향식(Bottom-up) 해결법을 도입한 것이다. 이 객체란 것을 일단 한번 독립성/신뢰성이 높게 만들어 놓기만 하면 그 이후엔 그 객체를 수정 없이 재사용할 수 있으므로 개발 기간과 비용이 대폭 줄어들게 된다.

객체 지향 프로그래밍은 등장 당시에는 기존의 절차적 프로그래밍과 비교해 매우 이질적이고, 당시 컴퓨터의 처리능력이 별로 좋지 않아서 별 주목을 받지 못하였다. 그러다가 GUI가 등장하면서 객체 지향 프로그래밍이 급부상하게 된다. 화면에 떠 있는 여러 개의 창은 각자의 실행 콘텍스트를 가지는데 콘텍스트의 현재 상태(활성화, 비활성화, 최소화 등)에 따라 같은 명령에도 다른 결과를 내보내야 했으며 사용자 상호작용을 위해 이벤트 처리도 수행해야 했다. 특히 이벤트 처리는 비동기적인 속성 때문에 기존 절차적 프로그래밍에서는 일종의 횡단 관심사가 되어 버려 코드 전체에 이벤트 처리 코드가 흩어져 있게 되는 문제가 있었다. 그래서 OOP를 도입하여 이벤트를 받았을 때 수행되는 기능(Event Handler, Callback)을 구현할 수 있는 단일 인터페이스를 정의하고, 프로그래머들은 이를 필요한 형태로 알아서 구현하며, 특정 이벤트가 일어났을 때 실행되어야 하는 기능들을 등록한 다음, 운영체제나 응용프로그램이 실제로 해당 이벤트가 발생했을 때 해당 이벤트에 등록된 이벤트 핸들러/콜백을 주욱 실행하기만 하면 되는 구조가 본격적으로 확산되면서 OOP 또한 빠르게 확산되었다.

단, 이벤트 드리븐 방식은 객체 지향 프로그래밍과 별개의 개념이다. 사실 이벤트 드리븐 방식은 객체 지향보다 함수형 프로그래밍 언어에서 훨씬 더 잘 지원한다. 그 예시로, 같은 일을 하는 Java와 Scala 코드의 GUI 로직을 보면 Scala 쪽이 압도적으로 단순하다는 것을 알 수 있다. 다만 기존 절차형 프로그래밍 언어가 함수를 일급 객체로 지원하지 않아 콜백 구현이 어려운 문제가 있었고(절차형인 C언어에서는 함수 포인터를 사용한다) 마침 등장한 객체 지향 언어가 인터페이스라는 개념을 제공했기에 이벤트 드리븐 방식에 좀 더 어울렸을 뿐이다. 객체 지향 프로그래밍 개념이 나올 당시에도 LISP 등 함수형 언어가 있긴 했으나 기존 프로그래머가 사용하기에는 너무 고수준의 개념을 다루고 있었고 성능도 너무 낮았기 때문에 당시에는 주목받지 못했다. 당장 for 루프로 리스트 처리가 가능한데 리스트 해석이니 map/reduce니 떠들어봤자 현업 프로그래머의 귀에 들어갈 리가 없었다. 물론 지금은 고차 함수나 클로저 같은 개념까지 도입해야 할 정도로 프로그램의 복잡도가 증가했기 때문에 관심을 보이고 있다. 현대에 만들어지는 프로그램은 그 정도로 복잡해졌다.

객체 지향 프로그램이 복잡해지면서 이를 간결하게 정리할 필요성이 생긴 관계로 '디자인 패턴'이라는 것이 생겼다. 프로그래밍 형식을 정하는 일종의 약속으로, 이는 특히 협업을 전제로 한 환경에서 특히 강조되고 있다

 

 

GUI란?

Graphical User Interface의 약자다. 현재 OS는 물론이고 온갖 게임이나 유틸리티 등에서도 모두 이용되고 있는 이른바 세계의 대세. 기존의 직접 문자를 입력하는 인터페이스는 CLI(Command-line Interface) 또는 CUI(Character User Interface)라고 부른다. UNIX 콘솔이나 도스 시리즈가 CLI의 대표적인 예.

CUI와 GUI의 차이를 알기 쉽게 설명하면, CUI는 음식을 주문할 때 점원에게 말 또는 글로 주문하는 것이고 단, 주문하려는 메뉴의 이름을 정확하게 알고 있어야 하며, 한 글자라도 틀리는 경우 주문을 거부한다(...) 심각한 경우 대소문자 하나 잘못 써도 주문을 해주지 않는다, GUI는 점원에게 음식이 그려진 메뉴판에서 원하는 것을 가리키며 달라고 하는 것과 같다.

장점 역시 이와 같은데, GUI는 일단 눈에 확 띄어서 뭘 하는지 잘 보인다는 점과 쉽고 직관적인 조작 방식이 있다. 따라서 컴퓨터 언어를 몰라도 조작이 가능한데, 비유를 하면 외국 식당에 가서 주문을 넣을 때, 해당 지역의 언어를 구사할 줄 몰라도 단순히 메뉴판의 그림을 가리키는 것만으로도 주문이 가능한 것과 같다. 그밖에 CUI는 추상적인 명령어를 입력해야 했고, 명령을 입력해서 이게 잘 되나 안 되나 직접 눈으로 보는 것도 힘들었지만 GUI는 알기 쉽게 그래픽으로 다 표현해준다. 조작도 명령어 입력 이런 거 없고 그냥 마우스 커서 갖다 대서 클릭만 하면 다 된다.[1]

 

 

<참고 자료>

 

https://ko.wikipedia.org/wiki/%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

https://ko.wikipedia.org/wiki/%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

https://namu.wiki/w/GUI

 

 

반응형

댓글