C++, JAVA와 같은 프로그래밍 언어를 공부하다보면 필수적으로 마주치는 개념이 바로 그 이름도 이상한
'객체지향 프로그래밍(Object-oriented programming)'이다.
자료형과 연산자 공부하고 알고리즘 문제 풀기도 벅찬 상황에 이런 이론적인 부분들까지 공부하게 되면 머리가 상당히 아픈 상황이 연출된다. 프로그래밍을 처음 배우는 사람으로서 OOP라는 프로그래밍 패러다임을 완전히 이해한다는건 매우 어려운 일이다. 특히 OOP가 대체 왜 사용되는지 와 닿아야 완전히 이해하는 사람은 인터넷 여기저기에 널려 있는 자료들만 보다가 머리만 복잡하게 꼬인 상태로 하루를 흘려 보내게 되곤 한다. 이 글에서는 OOP의 기초 개념과 왜 OOP가 중요한지, 왜 사용되는지 등에 대해 간략하게 설명하고자 한다.
What is an Object-oriented programming?
새로운 무언가를 공부할 때는 새로운 용어와 그 정의에 대한 명확한 이해를 내리는 것이 첫 번째이다. 객체지향이라는 아예 새로운 개념을 배울 때 나오는 개념 설명 자체에 새로운 용어들이 마구 등장하다보니 하나하나 새롭게 공부를 해야한다. 여기서는 정의를 잘게 나누어 설명하고 최종적인 정의를 내리는 형태로 학습할 예정이다.
이제부터 '객체지향 프로그래밍(Object-oriented programming, 이하 OOP)'의 정의를 가장 작은 범위에서 큰 범위로 확장시켜 나가며 글을 진행하겠다.
Definition 1.0: '객체지향 프로그래밍(Object-oriented programming, 이하 OOP)'은 일종의 '프로그래밍 패러다임(Programming Paradigm)'이다.
'프로그래밍 패러다임(Programming Paradigm)'은 기계어를 다루는 프로그래밍 언어를 사용하는 방법에 따라 생긴 구분을 말한다. 그 중 OOP는 존재하는 프로그래밍 패러다임 중에서도 중요한 패러다임으로 자리잡았다. 'OOP는 프로그래밍을 위한 특정한 방법론이다.'로 이해하면 쉽다. 이 패러다임의 발전 과정을 알아보면 OOP의 특징이 나온다.
프로그래밍 패러다임을 나누는 큰 틀은 명령형 프로그래밍(Imperative programming)과 선언형 프로그래밍(Declarative Programming)이다. 명령형 프로그래밍은 어떻게(HOW)할 것인지를 '명령'하고, 선언형 프로그래밍은 무엇을(WHAT) 할 것인지에 대해 '선언'하는 방식이다. 특정 주소지로 이동하는 방법으로 예시를 들어보면,
명령형(How): 북쪽으로 1km 움직이고, 동쪽으로 30m 움직인 뒤 파란 대문 집을 찾고 2층으로 올라가라
선언형(What): 서울시 북북길 100-1 2층이다.
이런 형식으로 달라진다. 여기서 명령형은 '알고리즘'이라고 하는 계산규칙이 필요하다. 프로그램을 만들기 위해 기계어를 입력하던 방식에서 벗어나 명령을 통해 변수를 생성하고 복잡한 수식을 계산하는 방법으로 기계어를 통제하는 아이디어는 최초의 프로그래밍 언어인 포트란에서 등장한다. 이후 등장한 대부분은 프로그래밍 언어는 명령형으로 이루어져 있다.
이에 반해 선언형 프로그래밍의 대표주자는 SQL과 HTML이 존재한다. (다만, 완.전.한 선언형인 HTML은 프로그래밍 언어가 아니라고 이야기 하기도 한다.) 다만, 프로그래밍 패러다임은 양립할 수 없는 관계는 아니라는 점을 기억해야한다. 최근의 프로그래밍 언어는 명령형 프로그래밍 패러다임을 차용한 언어일지라도 선언형 프로그래밍 패러다임의 문법도 녹아들어가 있는 경우가 대부분이다.
명령형과 선언형의 차이를 자세히 정리한 글을 추천한다.
https://ui.dev/imperative-vs-declarative-programming
Imperative vs Declarative Programming
A guide to understanding the difference between Imperative and Declarative programming.
ui.dev
Definition 2.0: '객체지향 프로그래밍(Object-oriented programming, 이하 OOP)'은 절차적 프로그래밍(Procedure Programming)에서 발전된 일종의 '프로그래밍 패러다임(Programming Paradigm)'이다.
아직 객체지향 프로그래밍 패러다임에 대해 이야기하려면 하나의 이야기를 더 마치고 가야한다. 앞서 명령형 프로그래밍과 선언형 프로그래밍에 대해 잠깐 이야기를 했는데, 객체지향 프로그래밍은 절차적 프로그래밍의 개념에 포함된 프로그래밍 패러다임이기 때문이다. 절차적 프로그래밍에 대해 알아야만 객체 지향이 나오게 된 이유를 알 수 있다.
앞서 말한 명령형 프로그래밍으로부터 절차적 프로그래밍(Procedural Programming)이 탄생하게 된다. 물론 명령형과 절차적 프로그래밍의 거의 동의어로 쓰일 정도로 유사한 개념이다. 다만 절차적 프로그래밍은 명령을 절차라는 관점으로 바라본 패러다임이라는 것이다. 영문 위키에서는 프로시저 호출(Procedure call)에 기반한 명령형 프로그래밍의 일종으로 설명한다.
중요!
사실, 절차라는 말보다는 프로시저로 읽는 것이 훨씬 이해에 도움이 된다. 절차라는 말이 마치 '순서'라는 의미로 오해해서 읽히기 쉽기 때문이다. 절차적 프로그래밍은 프로시저라는 단위를 기준으로 프로그래밍 하는 것이지 특정 절차나 순서에 따라 프로그래밍하는 것이 아니기 때문이다! 앞으로 절차는 프로시저로 정의를 내려 진행하겠다.
What is a Procedure? - Definition from Techopedia
This definition explains the meaning of Procedure and why it matters.
www.techopedia.com
In computer programming, a procedure is an independent code module that fulfills some concrete task and is referenced within a larger body of source code. This kind of code item can also be called a function or a sub-routine. -Techopedia
프로시저는 '특정한 작업을 수행하며, 더 큰 작업의 범위에 참조될 수 있는 독립적인 코드 뭉치'이다.
예를 들어, 로봇을 만드는 프로그램이 있다고 할 때 '로봇의 발을 만드는 코드 뭉치'를 로봇 프로그램을 구성하는 하나의 프로시저로 정의를 내릴 수 있다,
로봇을 만들기 위한 프로그램을 절차적 프로그래밍으로 제작한다면
1. 로봇을 만들기 위한 '명령'을 특정한 작업을 담당하는 프로시저(ex. 발 만들기, 팔 만들기) 단위로 구분하여 분리 제작한다. 이를 모듈화(modulation)라 한다.
2. 로봇을 만들기 위한 각각의 프로시저를 불러온다. 이를 프로시저 호출(procedure call)이라고 한다.
이해가 되었는가? 쉽게 말해 절차적 프로그래밍은 포드 자동차 공장의 프로세스와 같다. 바퀴를 조립하는 공정, 차 문을 조립하는 공정 등을 나누어 적용하는 방식이다. 이런 공정의 모듈화를 통해 더 쉽고 직관적으로 프로그램을 유지하고 보수할 수 있는 것이다.
이제 프로시저와 절차적 프로그래밍의 정의를 간단하게 정의해보자
프로시저(procedure): 특정한 작업을 수행하며 더 큰 작업에 참조될 수 있는 명령어(소스코드)의 집합
절차적 프로그래밍(procedural programming): 수많은 명령을 프로시저(특정한 작업 수행) 단위로 나누고 이렇게 만들어진 프로시저를 호출하여 전체 프로그램을 구성하는 프로그래밍 방법론
이러한 프로시저는 프로그래밍 언어마다 부르는 말이 다르다. 펑션(function), 메소드(method), 루틴(routine), 서브루틴(subroutine), 서브프로그램(subprogram) 등 다양한 형태로 불린다. 참고로 객체지향언어의 대표격인 JAVA에서는 메소드에 해당하는 단어가 프로시저이다.(이 글 이후에 자바에서의 객체지향에 대해 다뤄볼 예정이다.)
Definition 3.0: '객체지향 프로그래밍(Object-oriented programming, 이하 OOP)'은 객체(Object)를 기본 단위로 하는, 절차적 프로그래밍(Procedure Programming)에서 발전된 일종의 '프로그래밍 패러다임(Programming Paradigm)'이다.
자 이제 하나의 질문이 나온다.
'그렇다면 절차적 프로그래밍에 어떤 문제점이 있어 객체지향 프로그래밍이 나오게 되었는가?'
사실 이 질문은 적절한 질문이 아니다. 왜냐하면 객체지향 프로그래밍이 절대적으로 절차적 프로그래밍에 비해 나은 것이 아니기 때문이다. 다만 절차적 프로그래밍과 객체지향프로그래밍의 분명한 차이점은 존재하며 객체지향은 절차적 프로그래밍이 등장한 이후에 만들어진 패러다임인 것은 사실이다.
질문을 바꿔보자
Why do we use Object-oriented programming?
객체를 지향한다는 새로운 패러다임이 등장한 이유가 뭘까?
가장 간단한 답은 규모가 있는 프로그래밍 프로젝트를 위한 협업 방식을 유려하게 만들기 위해서이다.
여기서 작업을 나누는 모듈화가 주요 이슈로 떠오르게 된다. 앞서 말한 절차적 프로그래밍은 프로그래밍의 작업을 변수, 데이터, 특정 작업을 위한 명령어 뭉치인 프로시저로 나눈다.
절차적 프로그래밍에서 데이터는 전역적(global)인 상태를 가진다. 전역적이라는 말은 '모든 범위'라는 말과 같은데, 모든 함수나 프로시저가 데이터에 접근할 수 있다는 말이다. 예를 들어 로봇의 발을 만들기 위한 데이터가 있다면 여기에 로봇의 머리를 만드는 프로시저가 접근할 수 있다는 말이다!
이는 프로그램의 구조화에 별로 좋지 못한 영향을 끼치는 경우가 많다. 로봇의 머리를 만드는 작업을 담당하는 코드에게 로봇의 발 데이터가 무슨 의미가 있을까? 이렇게 되면 작업(task)과 데이터간의 관계가 보증되지 않는다. 정리하자면 절차적 프로그래밍은 작업 단위가 사람이 이해하는 작업의 단위에 초점을 맞추어 나누어진 것이 아니라 데이터, 코드와 같은 기계의 이해방식에 초점을 맞추어 나누어 진 것이다.
사람들은 프로그래밍 작업의 단위를 기계가 이해하는 방식이 아닌 사람이 이해하는 방식으로 조금 더 추상화(abstract)시키고 싶어했다. 즉, 로봇의 발을 만드는 작업의 단위가 기계가 이해하는 단위로 나누어 '로봇의 발 데이터'와 '로봇의 발을 제작하는 명령 코드'로 나누어진 것이 아니라 '로봇의 발을 만드는 데이터와 명령 코드'로 함께 묶여 있는 것이다.
여기에 더해, 데이터의 전역적인 상태를 묶여 있는 작업의 단위에만 적용되도록 하여 데이터와 코드의 관계를 보증해주고, 다른 작업을 하는 코드에게는 굳이 나의 데이터를 전달하지 않도록 막아주어 오류 발생 가능성을 줄여준다.
이렇게 사람이 이해하기 쉬운 추상화된 방식(컴퓨터 과학에서는 일반적으로 코드를 단순화 시킬수록 추상화된다고 표현한다)으로 프로그래밍의 단위를 설정하도록 시도하여 프로그래밍의 효율성과 생산성을 높인 패러다임이 바로 객체 지향 프로그래밍(OOP)이다. (물론 앞서 말한 장점은 객체지향의 이점 중 일부에 불과하다. 객체지향의 이점과 특징은 이후 글에서 설명)
그리고 데이터와 코드를 묶어 놓은 것을 클래스 기반 OOP에서는 '클래스(Class)'라 부르며 이 자체로 완전한 하나의 작업을 수행한다. 즉, 로봇의 발을 만드는 클래스는 다른 데이터와의 연계 없이 그 자체로 발을 만들어 낼 수 있는 것이다! 그리고 이 로봇의 발을 만드는 클래스가 만드는 '실제 로봇의 발'을 '객체(Object)'로 부른다.
드디어 클래스와 객체가 등장했다. 사람들이 자주 헷갈리는 인스턴스와 객체, 메소드까지 함께 묶어 정의해보면 다음과 같다.
In OOP
클래스(Class): 데이터와 명령코드(메소드, 프로시저와 유사)로 구성된 특정 객체를 만들어 내기 위한 틀
객체(Object): 클래스의 인스턴스(복제품). 클래스에서 정의한 내용을 구현한 실체
인스턴스(Instance): 임의의 메모리에 할당된 객체의 실제 구현물
메소드(Method): 특정한 작업을 위한 명령 코드 뭉치. 절차적 프로그래밍에서는 프로시저라 불린다.
예를 들어 로봇 발을 만드는 방법인 설계도가 클래스라면, 메소드는 클래스에 포함된 세부 설계 방법이다. 로봇의 발이라는 구현물은 객체이고, 실제로 구현된 로봇의 발(임의의 메모리에 할당된)은 인스턴스이다.
인스턴스와 객체의 차이에 대한 링크를 확인해보자
What is the difference between an Instance and an Object?
What is the difference between an Instance and an Object? Is there a difference or not?
stackoverflow.com
이러한 객체 단위로 프로그래밍을 진행 하는 패러다임을 바로 '객체지향형 프로그래밍'이라고 한다.
이제 우리는 다음과 같이 정의를 확장할 수 있다.
Definition 4.0: '객체지향 프로그래밍(Object-oriented programming, 이하 OOP)'은 규모화된 협업 프로그래밍에 적합하도록 고안된 객체(Object)를 기본 단위로 하는, 절차적 프로그래밍(Procedure Programming)에서 발전된 일종의 '프로그래밍 패러다임(Programming Paradigm)'이다.
객체지향형 프로그래밍은 프로그래밍 패러다임의 하나로서 명령형 프로그래밍이자 절차형 프로그래밍 패러다임의 일종이다. 프로시저(특정한 작업을 수행하는 명령문의 집합)를 기본 단위로하는 절차형 프로그래밍이 기계의 이해에 초점을 맞추는 것에 벗어나 사람들의 실제 작업 단위에 맞는 객체를 기본으로 하여 프로그래밍을 하는 패러다임이다.
객체지향형 프로그래밍은 데이터와 명령 코드(메소드)를 모아 클래스를 정의한 뒤 이 클래스를 구현한 객체를 기본 단위로하여 프로그램을 구축한다. 이를 통해 조금 더 구조화된 프로그래밍이 가능해지며 규모가 있는 프로젝트에서 사람이 이해하기 쉬운 작업 단위별로 프로그래밍을 분할하여 작업하기 쉬워진다.
여기까지가 내가 내린 객체지향의 기초 정의이다. 여기에 객체지향형 프로그래밍의 주요 특징이라 할 수 있는 캡슐화(encapsualation), 다형성(polymorphism), 상속(inheritance), 데이터 추상화(data abstraction), 정보은닉(information hiding) 등을 공부하면 객체지향의 철학에 대해서는 어느정도 이해를 할 수 있다. 지금까지의 이해를 바탕으로 객체지향의 특징을 공부하면 훨씬 더 빠르게 이해할 수 있을 것이다.
다음 글에서는 객체지향형 프로그래밍의 이점과 특징을 설명해보겠다.
(아.... 새벽 2시구나...)
총 정리
프로그래밍 패러다임(Programming Paradigm): 기계어를 다루는 프로그래밍 언어를 사용하는 방법에 따라 생긴 구분
- 명령형 프로그래밍(Imperative programming): 명령형 프로그래밍은 기계어에게 어떻게(HOW)할 것인지를 '명령'하는 방식의 프로그래밍 방법론
- 선언형 프로그래밍(Declarative Programming): 선언형 프로그래밍은 무엇을(WHAT) 할 것인지에 대해 '선언'하는 방식인 프로그래밍 방법론
- 절차적 프로그래밍(procedural programming): 수많은 명령을 프로시저(특정한 작업 수행) 단위로 나누고 이렇게 만들어진 프로시저를 호출하여 전체 프로그램을 구성하는 프로그래밍 방법론
- 프로시저(procedure): 특정한 작업을 수행하며 더 큰 작업에 참조될 수 있는 명령어(소스코드)의 집합
- 객체 지향 프로그래밍(Object-oriented programming): '객체지향 프로그래밍은 규모화된 협업 프로그래밍에 적합하도록 고안된 객체(Object)를 기본 단위로 하는, 절차적 프로그래밍(Procedure Programming)에서 발전된 일종의 '프로그래밍 패러다임(Programming Paradigm)'이다.
- 클래스(Class): 데이터와 명령코드(메소드, 프로시저와 유사)로 구성된 특정 객체를 만들어 내기 위한 틀
- 객체(Object): 클래스의 인스턴스(복제품). 클래스에서 정의한 내용을 구현한 실체
- 인스턴스(Instance): 임의의 메모리에 할당된 객체의 실제 구현물
- 메소드(Method): 특정한 작업을 위한 명령 코드 뭉치. 절차적 프로그래밍에서는 프로시저라 불린다.
참고자료
위키백과
나무위키
기타
1. Why was OOP invented? ,Quora
2. A simple Explanation of OOP
'컴퓨터 사이언스' 카테고리의 다른 글
객체지향 프로그래밍, 그 철학에 관하여 - 2 객체 개념 심화, 특징 (0) | 2022.05.16 |
---|---|
프론트엔드와 백엔드가 나눠진 이유? (0) | 2022.05.10 |
프로그램, 프로그래밍(Programming)은 무엇인가? (0) | 2022.05.10 |
컴퓨터(Computer)란 무엇인가? (0) | 2022.05.10 |