- 이번 포스팅에서는 객체 지향 프로그래밍이 무엇인지, 이에 대한 4대 원칙들과 객체 지향의 핵심인 다형성(Polymorphism)을 위한 예시, 다형성을 통해 얻을 수 있는 여러 가지 장점에 대해 공부한 내용을 정리해 보고자 합니다.
1. 객체 지향 프로그래밍(Object Oriented Programming)이란 무엇인가?
1-1. 객체 지향 프로그래밍의 정의
- 객체 지향 프로그래밍(Object Oriented Programming)이란 컴퓨터 프로그램을 명령어의 목록에서 보는 시각에서 벗어나 여러 개의 독립된 단위인 객체들의 모임과 이들 간의 상호작용으로 바라보고자 하는 프로그래밍 패러다임 중 하나로써 이러한 객체들은 각각의 상호작용을 통해 메시지나 데이터를 주고받으면서 여러 가지 작업을 처리할 수 있습니다.
- 이러한 객체 지향 프로그래밍 기법은 프로그램을 유연하고 변경이 용이하게 설계할 수 있기 때문에 대규모 프로젝트나 서비스 개발에서 많이 사용되는 프로그래밍 패러다임입니다.
1-2. 객체 지향 프로그래밍의 4대 핵심 원칙
(1) 추상화(Abstraction)
- 구현되는 객체들의 핵심을 강조하기 위해 불필요한 내용은 제거하고 본질적이고 중심이 되는 부분만 추출하여 표현하는 것으로써, OOP의 관점에서는 객체의 핵심이 되는 속성과 기능을 따로 추출하여 정의해 두는 것을 의미합니다.
(2) 캡슐화(Encapsulation)
- 객체의 속성(데이터 필드 - 변수)과 다양한 기능(메서드)을 하나로 묶고 실제 기능들의 구현 방법을 외부로부터 감추는 것을 의미합니다.
(3) 상속(Inheritance)
- OOP에서 상속이란 객체들 간의 관계를 만들어주는 방법으로써, 특정 클래스들을 부모와 자식 클래스 관계로 맺어주는 작업을 통해 부모 클래스의 속성과 기능을 자식 클래스가 물려받는 것을 의미합니다.
(4) 다형성(Polymorphism)
- OOP에서 다형성이란 특정 객체의 속성이나 기능이 상황에 따라 여러 가지의 형태를 가질 수 있는 것을 의미합니다.
- 특정 객체가 여러 가지 타입을 가질 수 있는 것을 의미하며,부모(조상) 클래스 타입의 참조변수로 자식 클래스 타입의 객체를 다룰 수 있는 것을 의미하기도 합니다.
2. 유연하고 변경에 용이하다는 것은?
- 위에서 잠시 언급된 "유연하고 변경에 용이하다"는 내용은 실세계에 비유해보면, 레고 블럭을 조립하듯이, 키보드 마우스를 바꾸고 싶은 장비로 교체하듯이, 컴퓨터 부품을 다른 부품으로 갈아 끼우듯이, 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법을 의미하며 이 방법을 유지하기 위해 객체 지향 설계의 핵심인 다형성(Polymorphism)을 이해해야 합니다.
3. 다형성(Polymorphism)을 실세계에 비유해서 이해하면?
3-1. 첫 번째 예시
- 위처럼 운전자의 역할과 자동차의 역할이 존재합니다.
- 해당 자동차라는 역할을 K3, 아반떼, 테슬라 모델3로 직접 구현한 상황입니다.
- 운전자는 K3를 타다가 아반떼로 자동차가 바뀌어도 운전하는데 문제가 발생하지 않습니다. 그 이유는, 자동차라는 역할은 동일하고 구현체만 변경되었기 때문에 운전자한테는 영향을 주지 않기 때문입니다.
- 이를 통해 자동차가 다른 기종으로 바뀌어도 운전자는 면허만 있다면 운전자의 역할을 충분히 수행할 수 있다는 사실을 알 수 있습니다.
- 운전자는 자동차의 역할의 인터페이스를 따라 각각의 자동차를 구현했기 때문에 자동차의 역할(인터페이스)에만 의존하게 됩니다.
- 이렇게 자동차라는 역할을 만들고 구현체들(각각의 자동차)을 분리한 것은 운전자(클라이언트)를 위해서 설계된 방법이며 운전자는 이러한 자동차들이 어떻게 설계되었는지 아키텍쳐를 전혀 몰라도 운전이 가능한 상황이며 구현체들의 아키텍쳐가 변경되더라도 운전자에게 영향이 없기에 운전자는 본인의 역할(운전 역할)을 충분히 수행할 수 있습니다.
(휘발유로 가는 자동차에서 전기를 동력으로 하는 자동차를 줘도 운전자는 무리없이 운전이 가능함.)
- 이러한 실생활에서의 다형성의 개념은 다른 대상으로 변환이 가능하고 완전히 새로운 기종의 차가 나오더라도 운전자에게 영향을 주지 않으며 자동차의 세상을 무한히 확장(Extend)할 수 있습니다. 즉, 클라이언트에게 영향을 주지 않고, 새로운 기능을 제공할 수 있게 되는데 이게 가능했던 이유는 세상을 역할과 구현으로 분리했기 때문입니다.
3-2. 두 번째 예시
- 유연하고 변경이 용이하다는 것을 위와 같은 예시로 들어보겠습니다.
- 로미오 역할을 둘 중 누가 수행하던지, 줄리엣 역할을 둘 중 아무나 맡아서 공연을 진행한다고 해도 로미오와 줄리엣의 역할에서는 각 설정에 맞는 대본만 읽고 공연을 진행하면 되기 때문에 문제가 발생하지 않습니다. 이를 통해 줄리엣 역할을 수행하는 구현체가 바뀐다고 해도 로미오 역할을 수행하는 사람에겐 문제가 없다는 것을 알 수 있으며, 다른 대상으로 언제든지 대체가 가능합니다. (유연하고 변경에 용이)
4. 역할과 구현을 분리하게 됨 (정리, 한계점)
- 역할과 구현으로 구분하면 세상이 단순해지고 유연해지며 변경이 용이해짐에 따라 아래와 같은 장점을 얻을 수 있습니다.
4-1. 이로 인한 장점들
(1) 클라이언트는 대상의 역할(인터페이스)만 알면 된다.
(2) 클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
(3) 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.
(4) 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
4-2. Java 언어에 역할과 구현을 분리한 것은?
(1) 자바 언어의 다형성을 활용
(2) 역할 = 인터페이스(Interface)
(3) 구현 = 인터페이스를 구현(Implement)한 클래스들, 구현 객체들
(4) 객체를 설계할 때 역할과 구현을 명확히 분리하여 설계
(5) 객체를 설계 시, 인터페이스를 먼저 분리하고 그 역할을 수행하는 구현 객체를 설계합니다.
4-3. 다형성의 본질
(1) 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있다.
(2) 다형성의 본질을 이해하려면, 객체들은 협력 관계에 있다는 것을 이해하고 있어야 함
(3) 클라이언트를 변경하지 않고 서버의 구현 기능을 유연하게 변경할 수 있게 됩니다.
4-4. 역할과 구현을 분리 - 정리
(1) 실제 세계의 역할과 구현이라는 편리한 컨셉을 다형성을 통해 객체 세계로 가져올 수 있음.
(2) 유연하고 변경이 용이한 코드 설계 가능
(3) 확장 가능한 설계 가능
(4) 클라이언트에 영향을 주지 않는 변경이 가능하며 인터페이스를 안정적으로 설계하는 것이 가장 중요합니다.
4-5. 역할을 구현을 분리했을 때의 한계점
(1) 역할(인터페이스) 자체가 변하면 클라이언트, 서버에게 모두 큰 변경과 영향을 주게 됩니다.
(2) 결론 : 이에 따라 인터페이스를 안정적으로 설계하는 것이 가장 중요합니다.
5. 스프링 프레임워크와 객체 지향
(1) 다형성과 인터페이스의 개념이 가장 중요합니다.
(2) 스프링은 이러한 다형성의 개념을 극대화해서 이용할 수 있게 도와줍니다.
(3) 스프링에서의 제어의 역전(IoC), 의존성 주입(DI)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원해 줍니다.
========================================================================
※ 해당 포스팅은 InFlearn에서 현재 우아한형제들, 배달의 민족 서비스 개발팀장(기술이사)으로 재직 중이신 김영한님의 "Spring 핵심 원리 - 기본편" 강의를 듣고 공부한 내용을 정리하였습니다.
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.
개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 지적해 주시면 감사하겠습니다.
댓글