절차적 프로그래밍
객체 지향 프로그래밍(OOP)의 등장 이전의 프로그래밍 패러다임은 절차적 프로그래밍이었다.
흔히들 OOP의 반대가 절차적 프로그래밍이라고 생각을 하는데, 이는 틀린 사실이다. 절차적 프로그래밍의 프로시저가 OOP의 메서드로 확장된 것에 가깝기에, 완전히 일치한다고 볼 수는 없어도 서로 공유하는 부분이 차이보다는 더 많다.
그럼에도 불구하고 왜 OOP가 등장하였냐 하면, 절차적 프로그래밍은 데이터를 구조화 하지 못하는 한계가 있었기 때문이다.
절차적 프로그래밍에서는 데이터가 종종 전역 변수로 선언되어 사용되었는데, 이는 다양한 함수들이 동일한 데이터에 접근하고 수정할 수 있음을 의미했다. OOP의 관점에서 보면, "메서드1" 에서 사용되는 전역 변수 "변수1" 이 아무 관련도 없는 생뚱맞은 "메서드51223" 에서 사용될 수 있다는 것과 같다.
이는 데이터의 무결성을 해치고, 해당 데이터를 변경할 때 이를 의존하는 모든 함수를 찾아내 함께 수정해야 하고, 의도치 않게 하나의 함수가 전역 데이터를 변경하면 이 데이터를 사용하는 다른 함수들에도 사이드 이펙트를 미치게 할 수 있다는 것을 의미했다.
이를 방지하기 위해서 같은 값을 지닌 수많은 변수들을 어떤 함수에 쓸 지 정하고 만들어야 했으니, 전역 네임스페이스 포화 문제가 일어났던 게 과장은 아닌 셈이다.
객체 지향 프로그래밍의 등장
1960년대 후반, 소프트웨어의 복잡성과 크기가 증가함에 따라, 전통적인 절차적 프로그래밍으로는 대규모 시스템의 개발과 유지보수가 점점 어려워졌다. 이 문제를 해결하기 위해 새로운 접근법의 필요성이 부각됐고, 절차적 프로그래밍의 이러한 한계를 극복하기 위해 객체 지향 프로그래밍이 새로운 프로그래밍 패러다임으로 떠올랐다.
객체 지향 프로그램은 크게 3개의 요소와 5개의 원칙을 가지고 있다.
요소
원칙
SRP(Single Responsibility Principle) : 단일 책임 원칙
OCP(Open-Closed Principle) : 개방-폐쇄 원칙
LSP(Liskov Substitution Principle) : 리스코프 치환 원칙
ISP(Interface Segregation Principle) : 인터페이스 분리 원칙
DIP(Dependency Inversion Principle) : 의존성 역전 원칙
+ 객체 지향은 정말로 현실 세계의 모방인가? (객체 지향의 사실과 오해)
흔히들 객체 지향 프로그래밍을 설명할 때, "현실 세계를 모방해 소프트웨어 내부로 옮겨오는 것" 이라고들 설명 한다. (특히 이 때 가장 많이 쓰이는 예시로 자동차가 쓰인다.)
틀린 설명은 아니다. 하지만 이렇게 현실 세계를 가져오는 설명은 실용적인 관점에서 객체 지향을 분석하고 설계를 설명하기에는 적합하지 않다. 애플리케이션을 개발하면서 객체에 정말 직접적으로 대응되는 실세계의 사물이 얼마나 있을까?
객체 지향을 처음 설명할 때 가장 많이 쓰이는 예시가 자동차이다. 자동차의 여러 부품들의 작동은 메서드로, 속력과 연료 잔량 등은 상태로 표현이 된다.
그러나, 자동차가 물로만 이동한다고 해서 문제될 것이 있는가? 현실 세계의 자동차가 도로로만 이동한다고 해서 소프트웨어의 자동차 또한 도로로만 이동해야 할까? 비유의 적절성을 떠나 소프트웨어 자동차와 도로의 자동차 사이의 의미적 거리만큼이나 소프트웨어 객체와 현실 세계의 사물 사이에 존재하는 연관성은 희미하다.
객체 지향의 목표는 현실 세계를 모방하는 것 보다는, 오히려 새로운 세계를 창조하는 것에 가깝다. 개발자의 역할은 단순히 실세계의 서비스를 소프트웨어 안으로 옮겨 담는 것이 아니라, 사용자를 만족시킬 수 있는 최상의 신세계를 창조하는 것이다.
그럼에도 불구하고 여전히 현실 세계의 객체와 소프트웨어 객체를 대응시키는 이유는, 그 비유가 객체 지향의 측면들을 학습하는 데 매우 효과적이기 때문이다.
"소프트웨어 시스템이 해결하려고 하는 실재는 잘해봐야 먼 친척밖에는 되지 않는다. [Meyer 2000]
- 버드란트 마이어(Bertrand Meyer)
살아있는 객체
예를 들어 객체를 스스로 생각하고 스스로 결정하는 현실 세계의 생명체에 비유하는 것은 객체의 '상태' 와 '행위' 를 '캡슐화' 하는 소프트웨어 객체의 '자율성' 을 설명하는 데 효과적이다. 하나의 기능을 구현하기 위해 스스로가 가진 역할과 책임을 수행하며 서로 협력하는 객체들은, 서로의 요청에 협력적으로 응답하되, 응답하는 방식과 심지어 응답 여부 조차도 스스로가 결정한다. 서로의 정보를 알 수 없지만(정보 은닉), 하나의 기능을 구현하기 위해 자신의 역할을 수행해서 적절히 응답한다.
(살아있는 객체, 객체간의 역할-책임-협력에 관해서는 다음 포스팅에 쓸 예정이다.)
'이론 > OOP' 카테고리의 다른 글
[객체 지향] 다형성(polymorphism) (0) | 2024.01.02 |
---|---|
[객체 지향] 상속(inheritance) (0) | 2024.01.02 |
[객체 지향] 캡슐화(encapsulation) (0) | 2024.01.02 |