🧐 🤔 그거 어떻게 쓰더라 🙄 😙

OOP(객체 지향 프로그래밍)과 서양적 사고방식

2022. 12. 11. Evergood Kim이가 씀

Object-Oriented Programming

Object-Oriented Programming(OOP)는; 객체들의 모임으로서 프로그램을 취급하는 방식이다.

OOP는 흔히 ‘객체지향 프로그래밍’으로 번역된다. 그러나 ‘객체중심 프로그래밍’, ‘객체위주 프로그래밍’이라고 해야 OOP의 개념에 더 부합한다고 본다. ‘지향’은 목적, 목표라는 뜻인데; OOP에서 객체는 끝에 있는 목표라기보단 오히려 시작점, 관점이기 때문에 이는 어색하다. 물론 말은 일단 남들과 통해야 하는 거니까; 내가 지어낸 말을 실제로 쓸 생각은 없다. 아니 근데 진짜~~ 난 객체지향이라는 말 처음 배웠을 때 이게 대체 뭔가 했다니까~~~ OOP는 그러니까 말 그대로 객체 중심의 관점에서 프로그램을 보는 것이다.

OOP는 절차지향적이던 기존 프로그래밍의 패러다임을 바꿨으며, 코드의 재사용성이 높고, 유지보수가 쉽고, 사람의 사고방식과 가깝다는 특징을 가졌다고 한다. 그런데 이렇게만 설명하면; 그 ‘객체’란 무엇인지, 절차지향의 한계를 왜 하필 이 방식으로 극복했는지, 그 사고방식이란 구체적으로 어떤 사고방식인지 등이 설명되지 않는다.

예전에 「생각의 지도」라는 책을 봤다. 이 책 아주 재밌습니다. 동서양의 사고방식 차이를 연구해서 설명해주는 책. 그 땐 몰랐지만 이제와서 생각해보니 왠지 여기서 나오는 서양인의 사고방식이 OOP와 아주 닮았다고 느껴진다. 그러니까 이 사고방식이 바로 OOP의 근간이 되는 것일 테고; 따라서 이 사고방식을 이해하면 그 응용인 OOP 역시 자연스럽게 이해될 것이다. 뇌피셜이다. 이렇게 생각하는 사람 본 적 없음.

서양적 사고방식

여기서 설명하는 동서양의 사고방식 대부분은 그 책에서 나오는 내용이다. 물론 서양인들은 다 이렇게만 생각하고 동양인은 다 저렇게만 생각하고 그런 건 아니다. 어디까지나 평균을 놓고 봤을 때 상대적으로 그런 경향이 있다는 거다.

독립적 요소

동양에서는 무언가를 인식하면 그것과 그 주변의 관계에 관심을 가졌다. 그에 비해 서양에서는 무언가를 인식하면 주변을 배제하고 그 사물 자체에만 관심을 기울였다. 즉 사물/인물을 독립적인 존재로서 보았다.

예를 들어 동양적 사고방식에서는 나의 아버지는 회사에서는 회사원이고 누군가에겐 친구인 반면에; 서양적 사고방식에서는 철수는 집에서도 철수이고, 회사에서도 철수, 언제 어디서든 철수는 철수이다.

그래서 동양에서는 전체를 조화로운 것으로 여기는 반면; 서양에서는 이런 독립적 요소들의 단순합으로서 전체를 보는 경향이 있다.

null

요소의 속성

주변을 배제했으므로; 사건이 일어날 경우 그 사물/인물의 내부에서 원인을 찾게 된다. 그것이 바로 그 사물/인물의 속성이 된다. 예를 들어; 똑같이 높은 데에서 떨어져도 유리는 깨지고 스펀지는 안 깨지는 이유는 유리와 스펀지의 속성이 다르기 때문이다. 아리스토텔레스의 사원소설에 따르면 불이 위로 가는 이유는 불의 속성이 가벼움이기 때문이다.

반면에 동양에서는 맥락과 관계에서 원인을 찾는 경향이 있다. 예를 들어 누군가 묻지마 살인 사건을 일으켰다면 그 이유로 사회 부적응을 드는 것이 좀더 동양적, 원래 그 사람의 본성이 포악하기 때문으로 보는 쪽이 더 서양적이다.

null

공통속성의 범주

세상 사물들의 속성들을 파악하고 나면; 같은 속성을 가진 것들이 있음을 알게 된다. 그것들을 묶어 범주를 만들고 계통도를 그린다.

예를 들어; 팬더, 원숭이, 대나무, 바나나를 둘둘씩 엮을 때; 동양인들은 대체로 서로 연관된 것끼리 팬더-대나무, 원숭이-바나나로 짝짓는 반면; 서양인은 대체로 같은 범주에 속하는 것끼리 동물[팬더, 원숭이], 식물[대나무, 바나나]로 묶는다. 팬더와 원숭이는 둘 다 털가죽, 팔다리, 눈코입 등이 있고 움직일 수 있다는 공통점이 있기 때문에 같은 범주에 속한다.

null

범주 기반 법칙

범주에 기반한 규칙을 세우고, 이 규칙으로써 사물들의 움직임을 설명한다. 이것이 세상의 법칙이 된다.

그래서 동양에서는 전혀 다른 곳에서 공통적으로 나타나는 패턴에 주목하여 만물의 연관성을 발견하려는 데에 비해; 서양에서는 분야가 다르면 별개의 것으로 본다. 예를 들어 인간사회에는 인간사회의 규칙이 있고, 원자세계에는 원자들의 규칙이 있고, 우주에는 천체들의 규칙이 있다.

프로그래밍에 적용

컴퓨터의 시작인 2진법은 원래 인간적이다. 비트는 원래 [참/거짓], [맞다/아니다], [있음/없음]을 표현하는 것이고 이런 생각은 인간적이기 때문이다. 하지만 2진법이 그보다 더 크고 복잡한 수를 표현하기 시작할 때 그것은 비인간적이게 되었다. 인간은 큰 수를 다룰 때 10진법이라는 다른 방식을 쓰기 때문이다.

절차지향 프로그래밍은 원래 인간적이다. 우리가 사는 1차원 시간 속에서 일은 순차적으로 진행되기 때문이다. 하지만 그보다 더 크고 복잡한 일을 하는 프로그램을 만들어야 할 때 절차지향은 비인간적이게 되었다. 프로그램의 규모가 커질 수록 프로그래밍은 단순히 명령어 나열이 아니라 우리의 이성적 생각을 기계에 이식하는 일이 된다. 그러니까 조금 더 복잡한 시스템을 표현하고자 할 땐 조금 더 복잡한 인간의 생각을 따라해야 하고; 현대 대부분의 학문의 주축인 서양인들의 사고방식이 그 기준이 된 건 자연스러운 일이지 않을까? 딱히 근거는 없고 그냥 내 뇌피셜이다. 혹은; 서양적 사고방식이 동양적 사고방식보다는 세상을 좀 더 단순하게 바라보기 때문에; 절차지향보다는 복잡하지만 더 미래에 있을 무언가보단 단순한 것이 현재에 있어서는 더 알맞는 것일까? 음… “현재”? 라기엔 OOP 나온 지도 오래 됐는데.

어쨌든 앞서 소개한 그 사고방식을 프로그래밍에 적용해보자.

캡슐화

프로그램을 구성하는 많은 요소들 중 서로 연관이 깊은―즉 독립적이지 않은 요소들을 모아서 독립적인 요소―객체로 만든다. 달리 말하자면; 독립적이지 않은 것은 독립적인 무언가의 속성인 것으로 취급한다. 이를 캡슐화라 한다. 이로써 프로그램은 독립적인 요소들의 모임이 된다.

여기서 ‘독립적’이란; 그 자체로 의미를 가졌음을 뜻한다. 예를 들어 어떤 전화번호는 "누군가의" 전화번호일 때에야 의미가 있으므로 독립적이지 않다. 영희는 철수가 있든 없든 영희이므로 독립적이다.

캡슐화를 하면 무엇과 무엇이 연관있는지 명확해지고, 의미적으로 독립적인 단위는 따로 떼어 생각하기 쉽기 때문에; 프로그램 일부를 수정할 경우 그 영향을 파악하고 제한하기 쉬워진다. 따라서 유지보수가 쉬워진다.

null

상속

공통 속성을 가진 객체들끼리 묶어 범주화하고 계통을 만든다. 그래서 하위 범주는 상위 범주의 속성을 모두 가지는데; 이를 상속이라 한다.

공통적인 것을 모아서 하나로 표현했으므로 코드의 재사용이 된다. 그러나 코드의 재사용이 곧 상속인 것은 아니다. 그건 앞뒤가 바뀌는 거다. IS-A, HAS-A 관계에 굳이 설명씩이나 필요한 건 아마 이 앞뒤를 헷갈려서 그런 거겠지.

null
클래스
여기서 객체의 범주라는 개념은 많은 언어에서 ‘클래스’라고 일컬어진다.
프로토타입
범주의 역할을 겸하는 객체. 어떤 언어에선 추상화를 통해 범주를 만들기보다, 그 범주의 가장 대표적·전형적인 특징을 가진 객체 하나를 범주의 표본 즉 프로토타입으로 삼음으로써 상속을 구현한다.

다형성

프로그램이라는 세계에서 요소의 범주란 곧 자료형이고, 요소들이 따르는 법칙은 곧 실행할 명령에 해당한다. 그러므로 “범주에 기반한 법칙”을 프로그래밍에 적용하면 “자료형에 기반한 실행제어”가 된다. 이를 다형성이라 한다.

오버로딩
인자의 자료형에 따라 다른 메서드를 호출 즉 다른 명령을 실행시키기.
오버라이딩
공통된 상위범주의 메서드를 실제 객체의 범주에 따라 달리 실현시키기.

이상의 세 가지 개념(캡슐화, 상속, 다형성)은 OOP의 대표적인 특징으로 일컬어진다.

OOP를 설명할 때 가장 예시로 많이 들리는 언어는 Java이다. 이는 Java가 유명하기 때문이기도 하지만 아마 Java가 OOP (혹은 이 오랜 서양철학)의 이상형에 가장 가깝기 때문인 것도 같다.(뇌피셜)

아… 아!! 엿같다!!! 저 정적이고 꽉 닫힌 세계를 봐. 객체지향이 프로그램을 유연하게 만든다고? 진짜 말도 안 되는 소리야. 옛날양놈 사고방식? 저렇게 생각하던 사람들은 우주가 영원불변하고 직선적인 줄 알았던 사람들인데! 그런 사고방식을 가지고 만든 무언가가 어떻게 유연한 것일 수 있지? (물론 절차지향은 그보다도 더 직선적이고 정적임). 그러니까 새로운 개념들 나오는 거 봐라. 맨날 하는 소리가 유연함이 장점이랜다. 애초에 그게 있었으면 왜 그게 장점인 새로운 개념이 자꾸 나오겠냐? 애초에 모두가 불변이라는 가정에서 출발해놓고는; 아 사실 이거는 바뀜, 아 사실 이것도 바뀜 이러면서 온갖 똥꼬쇼 하는 게 소프트웨어 개발 방법의 발전이네.

내가 Apple 상속해서 FineApple 만들면 뭐함??? 그거 누가 취급해줘? 아무도!! 아무도 취급 안 해줘!!!!!!!! 끽해야 FineApple에게 Apple인 척하기를 시킬 수 있을 뿐이야. FineApple이 FineApple이려면 애초부터 FineApple이 들어간 꽉닫힌 세계를 만들었어야 하지. 그러고 솦웨 개발자로서 내가 하는 일은 또 FineApple이 포함된 꽉닫힌 세계를 만드는 것이고. 상속은 코드를 확장하는 기능이 아니고 ^^ 그냥 그 꽉닫힌 세계‐ 사실 완벽이란 없지만 코딩할 당시에는 마치 그게 프로그래머의 꿈나라처럼 완벽하다고 생각되어서 더이상 수정이 필요없을 거 같은 그런 완벽한 세계를 만들 때 그 중에 요약을 나타내는 방법일 뿐인데~ 자꾸 착각하게 되는군! 엿같은!! 그런데 요약이란 원래 구체적인 것이 이미 있는 다음에야 나타나는 게 자연스러운데; 이 놈의 세계에선 구체적인 것(내가 이제 만들 것)보다 요약(기존 클래스)이 더 먼저 존재하고 있으니까 똥꼬쇼를 해야 할 수밖에 없잖아.

교체 가능한 건 객체. 우리집 바둑이는 태어나고 죽을 수 있지만 개라는 추상적 개념은 영원불변, 개는 멍멍 짖는다는 법칙도 영원불변. 바둑이는 객체지만 클래스나 메서드는 객체가 아니다. 우리가 세상 바깥에 서서 세상 모든 것을 객관적으로 보고 모든 것을 다 알고있는 그런 존재라면 이런 방식으로도 완벽하게 세상을 파악하고 완벽한 시스템을 만들 수 있겠지. 그런데 실상은 우리는 세상에 속해있을 뿐이잖아. 그 바깥에 무슨일이 일어날지를 보려면 그 변화의 요소와 함께 시스템을 밖에서 바라보아; 시스템 자체가 또다시 대상이 되어야만 한다. 그래서 이제는 클래스도 객체, 메서드도 객체.

SOLID 원칙을 봐: 객체지향의 시스템은 잘 고정된 것을 지키는 원칙을 따라야 여전히 바람직한 객체지향 시스템일 수 있다는데?

MyService에서 Time 객체를 다룬다 치고; 만약 시간 형식을 바꾸고 싶으면; 그 동작은 누구의 행위이냐? MyService.convert(Time)이냐, Time.convert()이냐? 아니면 제3자의 TimeUtil.convert(Time)이냐? 객체지향 설명하면서 dog.bark() 이러는 거 봐 ㅋㅋㅋㅋ 애초에 게터와 세터를 제외하면; 현상이 꼭 누군가의 행위라고 딱잘라 말할 수가 있나?

참고

Richard Nisbett (2003) 생각의 지도 떼잉~ 이것도 벌써 거의 20년이나 지난 책이 되어버렸군~ 이 때도 점점 그러긴 했지만 이젠 정말 그보다 더 서양적이니 동양적이니 구별이 더더더 의미없어진 거 같기도 해….

728x90

카테고리 다른 글