학습을 시작한 계기가 부끄럽지만, 인터넷을 찾아보며 공부할때 "객체지향" 이라는 개념이 중요하다! 잘 활용해야한다! 라는 말들을 간혹 봤습니다. 객체지향에 관하여 아직 높은 이해도를 가진것이 아니지만, 객체지향에 관해 새롭게 학습하며 알게된 내용들을 공유하고자 합니다.
따라서 지금부터 포스트에 작성할 내용이 절대 정답이라고 할 수 없습니다. 하지만 제가 최근에 혼자 공부해봤던 개념에 대해 얇게라도 정리하며, 혹시 이 글을 읽는 분들에게도 제 생각을 공유하고자 합니다 😁
이론적인 접근방식으로 설게한다면, 매번 잘못된, 편합된 사고를 가지고 이상한 접근방식을 가질 수 있게됩니다. 그 중 하나가 현실세계에 존재하는 물체를 일반화시켜서 프로그래밍에 적용하는 것입니다.
예를들어 기존의 저희는 아래와 같은 접근방식으로 일반화시켜서 프로그래밍을 진행해왔습니다.
심지어 위 내용들은 유명한 출판사 책들에서도 이론적으로 설명하는 내용들입니다. 저희는 이런식으로 접근하지 말자는 것이죠. 객체지향의 세계는 현실세계와 다른 방식으로 접근해야 합니다.
어떻게 현실세계와 다른지 예시를 통해 알아봅시다.
현실세계에서 본인이 자동차를 엑셀을 밟는 상황을 가정해보자. 현실세계에서는 그냥 엑셀을 밟으면 자동차가 속도가 증가해서 앞으로 나가는 상황으로 당연히 받아들여질겁니다. 사람인 내가 자동차에게 엑셀을 밟는 명령, 즉 행위를 시도하면 자동차는 그저 앞으로 나가는 물체에 불과하죠.
그러나 객체지향 세계에서는 아닙니다. 자동차는 엄연히 "살아숨쉬고 있는, 마치 인격이라도 가지고 있는것처럼 보이는 객체" 로 바라보아야 합니다. 객체지향의 세계에서는 본인(사람)도 객체이고, 자동차도 객체입니다. 따라서 사람은 엑셀을 밟아서 속도를 증가시키고 싶다면, 자동차에게 속도를 증가시키겠다는 요청을 보내야합니다.
요청을 받은 자동차는 자율적으로 본인의 의사에따라 속도를 증가시킬지말지는 결정할 수 있는 주체입니다. 따라서 요청을 거부할 수도있고, 반대로 승인할 수도 있는것이에요!
객체는 또 다른 객체를 엄연한 객체로 바라보고, 상호간에 요청과 응답을 주고받으면서 협력해야 하는 사이입니다.
또 객체간의 협력시 역할과 구현을 구분할 수 있어야합니다. 책임이라는 키워드를 앞서 알게 되었는데, 역할과 구현은 또 도대체 뭘까요?
앞선 예제에서, 사람과 자동차만 따로 생각해봅시다. 주유소는 따로 굳이 설명에 포함하지 않아도 충분히 설명가능하기 때문입니다.
만일 사람과 자동차 객체와의 협력 관계에서, 자동차 객체는 엄밀히 따졌을때 다양한 차종으로 구분될 수 있겠죠? 당연한 말이지만 소나타, 스태랙스, 캠핑카와 같은 여러 차종들이 자동차에 해당하는 것입니다.
그런데 여기서, 사람이 선택한 차종이 소나타였는데 스타랙스로 바뀐다고 한들, 전체적인 서비스 흐름에 영향을 끼칠까요? 그건 아닐겁니다. 앞선 예시에서 사람과 자동차에게 부여된 책임들을 다시 살펴본다면, 소나타가 스타랙스로 바뀐다고해서 엑셀을 밟았을때 속도가 증가하는것이 아닌, 엉뚱하게 반대로 속도가 감소해서 후진하는 경우는 없을겁니다.
정리해보자면, 여러 자동차들은 하나의 동일한 역할(=책임의 집합)을 수행하는 자동차로 구분될 것입니다. 각각의 자동차들을 저희는 구현이라고 부루는 것이며, "자동차" 라는 것은 역할로 부르는 것입니다.
조금 더 생각해보면, 아래와 같은 관점을 생각해낼 수 있습니다.
- 책임들은 모여 하나의 역할을 구성한다.
만일 역할이 아닌 구현을 중점으로 객체간에 상호작용한다고 해봅시다. 그러면 자동차가 아닌 소나타로 소통한다고 해보는것이 되겠죠?
이러면 갑자기 서비스를 개발할떄, 다른 차종으로 급하게 바꿔서 개발을 진행해야한다고 해봅시다. 소타나에서 갑자기 스타랙스로 갈아끼워야 하느 상황인거죠. 그렇다면 저희는 자동차가 아닌 소나타라는 구현, 즉 구체화에 의존해있기 때문에 개발 코드를 일일이 새롭게 구현해주고 서비스 설계를 다시 진행해야 할겁니다.
반대로 자동차라는 추상화, 즉 역할을 중점으로 개발했다면 스타랙스로 바뀌더라도 서비스 설계 자체에 거의 지장이 없을겁니다. 이 때문에 구현이 아닌, 역할을 중점으로 상호작용 해야한다고 합니다.
- 구현을 중점으로 객체간에 소통하면, 유연성이 떨어진다.
다음으로 저희는 객체를 자율적인 존재로 인식해야 한다는 것입니다.
객체는 그 본인의 역할만 제대로 수행할 수 있다면 어떤식으로 구현돠어도 무관하다는 것입니다.
즉, 자동차라는 역할을 문제없이 수행하고, 타 객체와의 협력에서 문제가 없다면 소나타로 구현되던, 스타랙스로 구현되던 상관이없다는 것이죠. 그리고 소나타로 구현이 되었을때, 엑셀 기능만 잘 동작하도록 역할만 수행한다면 문제가 없으니까 소나타 내부 엔진이 어떻게 구체적으론 구현되던간에 상관이 없다는것입니다.
그리고 행동이 상태를 결정한다 라는 것을 인지하고 접근하는 사고방식이 객체지향적인 접근입니다.
객체지향적인 설계를 고려하지않은 경우를 가정해봅시다.
만일 Car 클래스를 설게할때 다른 객체들과의 협력관계를 생각하지 않았다면, 무의적으로 어떤 필드가 들어가겠지? 라는 추측을 가지고 설계할겁니다.
getter, setter 가 필요할것같고, 자동차이니까 speed, oil_gage 필드도 필요할 것같아서 마주잡이로 설계하는겁니다.
이 방식은 잘못된, 객체지향을 무시하는 접근입니다. 이 자동차 클래스가 어떻게 서비스가 영향을 미칠줄 알고 설계를 마주잡이로 정의하는 것일까요?
자동차 객체가 또 다른 어떤 객체와 어떤 상호작용을 할지가 정해지고, 역할이 정확히 정해진 후에 그것을 토대로, 상태, 필드, 속성등을 결정하는 것이 올바른 객체지향 접근방식이라고 하네요!
이렇게 포스트를 마쳐보겠습니다. 혹시 이 글을 읽으실분이 있을진 모르겠지만, 저처럼 객체지향이 무엇인지 궁금하여 기초 개념을 학습하는 모든 분들에게 이 포스팅이 도움이 되었으면 하는 바람입니다!! 😆
얼마나 정성스럽게 글을 작성하셧는지 느껴지는글이네요 좋은글 감사합니다!
첫번째로 소개해주신 부분에 대해 더 자세한 의견이 궁금해서 조심스럽게 댓글 남겨봐요 ㅎㅎ
말씀해주신 비유를 보면서, '현실세계와 객체지향 세계 모두 양방향의 상호작용이 일어나는게 아닐까' 하는 생각이 들었어요.
예를들어서 현실세계에서도 자동차에서 엑셀을 밟으면 속도가 10 증가하지만, 만약 연료라는 자산이 없을경우, 엑셀을 아무리 밟아도 차의 속도는 증가하지 않는것처럼요. 또한 속도가 증가한다 도 자동차에서의 한 종류의 응답이라고 생각되요
즉, 현실세계에서도 자동차와 사람 모두 하나의 주체이지만, 예시에서는 사람이 클라이언트(사용자)인 하나의 인터페이스 (밟으면 속도가 증가한다 는 사용방식을 제공하는 엑셀)라고 생각되요.
OOP에 관점에서는 이 인터페이스 하나에 초점을 둔다는 취지로 말씀하신건지 궁금해요 ㅎㅎ
그리고 말씀하신것처럼 단순히 객체지향이 클래스라는 말은 잘못되었다고 생각해요. 관련해서 프로토타입 기반 프로그래밍이라는 OOP의 한 카테고리가 있는데 여기서는 클래스가 없고 객체를 복제하는 방식으로 이루어지니까요.
좋은 글 써주셔서 다시한번 감사드립니다 ㅎㅎ
너무 좋은 포스트 잘 읽었습니다!!
비전공자로서 느낀 점은 객체지향이라는 막연함이 수업에서는 쉬운 이해를 위하다보니 아직 저 포함 프로그래밍에 좁은 시야를 가지는 교육생들은 "클래스 = 객체"라는 생각이 굳어지게 되는 것 같습니다 ㅎㅎ
거시적인 관점으로 잘 설명해주셔서 객체지향을 완전히 다르게 봐야겠다고 생각이 드네요..!
정성스럽게 작성하신 글 잘 봤습니다 ! 잘 안다고 생각하지만, 막상 다른 사람이 충분히 이해할 수 있도록 말하거나 글로 설명하는 건 정말 어려운 것 같습니다.
잘 읽었습니다~~