객체지향이 무엇이냐는 질문에 대해 "여러 블로그에 서술된 식"의 설명이 아닌 자기만의 방식으로 설명할 수 있는 사람이 얼마나 있을까 ?
객체지향이란 무엇이에요 ? 라는 새내기의 질문에 내가 잘 대답할 수 있을까 ?
객체지향이란 무엇인지, '다른 블로그에서 하는 흔한 말'이 아니라 본질에 대한 고민을 해보고, 이를 글로 정리하고자 한다.
내가 졸업한 대학교에서는 1학년 전공 필수로 객체지향 프로그래밍이라는 과목이 있다.
객체지향 프로그래밍, 이 9글자의(공백 포함 10글자) 과목명만 보고 처음에는 대체 이게 뭐 하는 과목인가 ... 하는 생각이 들었다(C++을 통해 OOP라는 개념에 대해 배우긴 했다).
솔직히 말하자면, 불과 얼마 전까지만 해도 '객체지향 프로그래밍이 뭐에요 ?' 라는 질문을 받았을 때 나는 "절차지향 프로그래밍과는 다른 ... 객체 간의 상호작용을 통해 ... 유지보수가 쉽다는 장점이 있는 ... 추상화 캡슐화 상속 다형성 이라는 4가지 특징이 ..." 이런 대답이 틀에 박힌 것처럼 튀어나오곤 했다.
그런데 이게 면접이었고, 면접관이 당연히 객체지향에 대한 지식이 있기 때문에 저렇게 말해도 얼추 넘어갔던 것 같다는 생각이 든다.
만약 새내기(이제는 무려 6살이나 차이가 난다 ... 격세지감이다 ...)가 "선배님 객체지향 이란 무엇인지요 ?" 라고 묻는다면, 나는 아무런 지식이 없는 새하얀 도화지 같은 이 친구에게 어떻게 객체지향을 설명해줘야 할까 ?
면접관에게 답변했던 것처럼 답변했다가는 도저히 이 친구가 이해를 못 할 것 같다는 생각을 했다.
그래서 객체지향이란 무엇인지에 대해, 내가 스스로 깊게 이해해보고 이를 쉬운 말로 풀어써보고자 한다.
보통 다양한 책들이나, 블로그들은 객체지향 프로그래밍이라는 개념을 설명하면서 항상 절차지향 프로그래밍 언급을 하곤 한다.
객체지향 프로그래밍을 알기 위해서 꼭 절차지향 프로그래밍을 알아야 할 이유는 없지만, 그래도 가벼운 배경 지식으로 알면 나쁘지 않아 매우 간략하게 언급해보고자 한다.
내가 이해한 바로는, 결국 순차적 / 절차적 / 객체지향 프로그래밍 이라는 이 개념은 다 "문제를 어떻게 해석하고 해결할 것인가" 에 대한 방법론이다.
(근데 별로 알고싶지 않다면, 그냥 아래 2개 (순차적 프로그래밍, 절차지향 프로그래밍) 건너뛰고 바로 객체지향 프로그래밍을 읽어도 된다.)
순차적 프로그래밍은 문제를 "순서대로" 풀겠다는 방식이다.
프로그램의 기능 흐름에 따라 순서대로 코드를 작성하는 방식이고, 따라서 프로그램의 동작을 한 눈에 알아볼 수 있다.
매우 단순한 기능이라면 문제가 없지만, 조금이라도 기능이 복잡해진다면 개발자의 머리도 복잡해진다.
A - B - C 순서로 동작하는 기능이 있다면, 순차적 프로그래밍은 A - B - C 순서로 코드를 작성한다.
그런데 만일 C의 실행을 마치고 어떤 조건 하에 있다면, A로 돌아간다는 기능이 추가되었다(아 복잡하다)고 하자.
그러면 C의 실행을 마치고 조건문을 걸어 goto 문을 작성해야 한다.
이런 식으로 goto 문이 많아진다면, 개발자는 그야말로 코드 속에서 미로찾기를 해야한다.
프로그램의 동작을 한 눈에 알아보는 게 아니라 한 100개 정도의 눈을 가지고 ... 코드를 트래킹해야 하는 상황인 것이다.
절차적 프로그래밍은 문제를 "동작 단위로 분할해서" 풀겠다는 방식이다.
순차적 프로그래밍에서는 무분별한 goto 때문에 개발자의 머리가 복잡해질 수 있다고 했다.
절차적 프로그래밍은 이런 문제점을 함수, 프로시저 형태로 해결하고자 한다.
특정한 동작이 반복된다면 이를 함수로 분리(모듈화)하고, 이를 재사용하는 방식이다.
객체지향 프로그래밍을 공부하면서 장점으로 "높은 재사용성" 이라는 것이 언급되는데, 이게 바로 내가 헷갈렸던 포인트였기도 하다.
어라 ... 절차적 프로그래밍도 함수를 분리해서 재사용하는데, 그럼 절차적 프로그래밍은 재사용성이 낮은 것인가 ?
이에 대해 내가 내린 결론은, '재사용성이 객체지향 / 절차지향을 구분짓는 기준이 아니다' 라는 것이다.
(어라 ... 이상하다 ? 다른 블로그들에서는 객체지향은 재사용성이 높다고 장점이라고 했는데 ... 이 사람 글 읽으니까 내 개념이 더 어지러워지는 기분이다 ... ?)
객체지향 프로그래밍은 문제를 "상태와 동작을 묶은 객체 단위로 분할해서" 풀겠다는 방식이다.
절차적 프로그래밍은 문제를 동작 단위로 분할해서 푼다는 개념이라면, 객체지향에서는 동작과 상태를 묶어 객체 단위로 문제를 푼다.
절차적 프로그래밍에서는 동작에 대한 분리는 이뤄지지만, 상태에 대한 분리는 이뤄지지 않는다.
문제를 해결하기 위한 어떤 자료형이 있고, 이 자료형을 활용해 동작하는 함수가 있다면 이 자료형과 함수는 어떤 연관성을 가지는 것이 아니라 각각 독립적인 것이다.
객체지향에서는 객체를 통해 문제를 해결하고자 한다.
더 자세히 말하자면, 객체 간의 상호작용을 통해 문제를 해결하고자 한다.
한 객체가 문제를 통으로 전부 해결하는 것이 아니라, 문제를 잘게 쪼개어서 여러 객체들이 그 쪼개어진 문제를 나누어 분담하는 것이다.
객체란, 쉽게 생각해보면 "특정 문제를 해결하는 개체" 라고 생각할 수 있다.
음악 플레이어를 생각해보자.
음악 플레이어는 '오디오 파일을 재생한다' 라는 문제를 해결하는 객체라고 할 수 있다.
그렇다면 이 음악 플레이어가 오디오 파일을 재생하는 문제를 통으로 해결할까 ?
그렇지 않다.
이 음악 플레이어는 '오디오 파일을 재생한다' 라는 하나의 큰 문제를 여러 작은 부분 문제(Sub-problems)로 나눌 수 있다.
압축된 오디오 파일을 가져와 음악 플레이어의 입력 파일(재생할 음원 파일)로 전달하는 입력부 문제,
압축된 오디오 파일을 디코딩해 재생할 수 있는 압축 해제된 원시 데이터로 변환하는 처리부 문제,
압축 해제된 원시 데이터를 음악 플레이어의 출력 디바이스로 전달해 소리를 출력하는 출력부 문제로 나눌 수 있는 것처럼 말이다.
그렇다면 음악 플레이어 안에서는 입력부를 담당하는 객체, 처리부를 담당하는 객체, 출력부를 담당하는 객체가 존재할 수 있으며, 이 3개의 객체가 서로 상호작용하며 오디오 파일을 재생한다 라는 음악 플레이어가 담당한 문제를 해결해나가는 것이다.
항상 개발자는 "왜 ?" 에 대해 의문을 품어야 한다고 생각한다.
객체란 무엇인가 (오늘 설명이 너무 두루뭉술한 것 같다. 블로그 주인장 약팔이인가) ? 객체지향을 왜 사용할까 ? 어떤 장점이 있을까 ? 하나의 큰 문제를 작은 부분 문제로 풀었을 때 얻을 수 있는 이점은 무엇일까 ?
이번 글 (1편) 에서는 객체지향 프로그래밍이라는 개념에 대해 매우 간략하게 "객체지향 프로그래밍이란 이런 것입니다" 정도만 설명했다.
사실 길게길게 쓸 수도 있지만, 꾸준히 ... 글을 쓰고 싶다는 욕구가 있는데 한 편마다 긴 글을 쓰게 되면 ... 쓰는 내가 힘들 것 같아서 이렇게 분할해서 올리는 방식을 선택했다.
다음 편 (2편) 에서는 객체란 무엇인지, 객체지향을 왜 사용하는지, 즉 객체지향의 장점이 무엇인지와 하나의 큰 문제를 작은 서브 프라블럼으로 분할해 푸는 것의 장점에 대해 쉬운 말로 설명해보도록 하겠다.