1. 객체 지향의 특징
객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록이 아닌 여러 개의 독립된 단위인 "객체"들의 모임으로 취급하는 것이다. 각 객체는 메시지를 주고받거나, 데이터를 처리할 수 있다. 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들어주기 때문에 대규모 소프트웨어 개발에 사용된다고 한다. 이때 유연하고 변경이 용이하다는 것이 객체 지향의 중요한 특징 중 하나인 다형성이다. 일단 객체 지향의 주요 특징은 아래와 같은 것들이 있다.
- 추상화: 추상이란 사전적 의미로 "사물이나 표상을 어떤 성질, 공통성, 본질에 착안하여 그것을 추출하여 파악하는 것"이다. 객체 지향에서도 비슷 맥락으로 추상화란 객체의 공통적인 속성과 기능을 추출하여 정의하는 것을 말한다. 예를 들어, 강아지와 고양이는 모두 동물에 속하며 걷거나 우는 등의 공통된 행위를 한다. 이때 강아지와 고양이와 같은 것들을 하위 클래스(sub-class)라고 부르며 동물은 상위 클래스(super class)라고 부른다. 이런 추상화를 위해서 자바에서는 추상 클래스(abstract class)와 인터페이스(interface)를 지원한다.
- 캡슐화: 캡슐화란 클래스 안에 연관있는 속성과 기능들을 하나의 캡슈로 만들어 외부로부터 데이터를 보호하는 것을 말한다. 자바에서 캡슐화를 하는 이유는 데이터 보호(data protection)와 데이터 은닉(data hiding)을 위해서다. 즉, 클래스에 정의된 속성과 기능들을 보호하고, 필요한 부분만 노출하여 객체를 안전하게 지키고자 함이 목적이다. 이를 위해 자바에서는 접근제어자(access modifiers)와 getter/setter 메서드를 사용할 수 있다.
- 상속: 상속이란 기존 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소를 말한다. 우리는 상속을 활용해 상위 클래스로부터 확장된 하위 클래스들이 상위 클래스의 속성과 기능을 사용할 수 있다.
- 다형성: 다형성이란 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 의미한다. 나는 누군가의 친구, 아들, 부모일 수 있다. 즉, 상황과 환경에 따라 나의 역할은 변한다. 다형성을 위해서는 오버라이딩과 오버로딩을 사용할 수 있다. 오버로딩은 파라미터 수, 타입 등을 다르게 하여 동일 클래스에서 같은 이름의 메서드를 중복하여 선언하는 방식이고 오버라이딩은 부모 클래스의 메소드를 자식 클래스에서 재정의하는 방법이다.
2. 다형성이란?
운전자가 있고, 자동차가 있다. 자동차에는 A, B, C 세 가지 종류의 차량이 있다고 하자. 이때 A, B, C 중 어떤 것을 사용하든 "자동차"의 역할은 모두 수행하므로 운전자에게는 영향을 주지 않는다. 위에서 유연하고 변경이 용이하다는 말을 했었다. 이것이 다형성 덕분이다. A에서 B로 바꾸든, C에서 B로 바꾸든 아무런 상관이 없다. 만약 새로운 모델의 자동차가 나와도 클라이언트(고객)은 새로운 것을 배울 필요가 없다. 이때 우리는 "자동차"와 같은 것을 인터페이스로 구현하는데 이를 "역할"로 볼 수 있고 A, B, C와 같은 모델을 "구현"으로 볼 수 있다.
위와 같이 실생활을 "역할"과 "구현"으로 다루는 다른 예시를 살펴보자. 공연에서 A역할과 B역할이 필요하다. A를 누가하든, B를 누가하든 배우는 대체가 가능하다. 즉, 유연하고 변경이 용이하다. 이때 A와 B는 "역할"이고 배우들은 일종의 "구현"으로 볼 수 있다.
이와 같이 역할과 구현으로 세상을 구분하면 세상이 단순해지고, 유연해지고, 변경도 편해진다. 이때 핵심은 클라이언트다. 클라이언트는 대상의 역할(인터페이스)만 알면 된다. (자동차는 브레이크를 밟으면 멈추고, 핸들을 돌리면 회전하는 등의 기능만 알면된다.) 구현 대상의 내부 구조는 몰라도 되고, 내부 구조가 변경되어도 영향을 받지 않는다. 또한 구현 대상 자체를 변경해도 영향을 받지 않는다.
프로그래밍에서도 이러한 개념을 도입한 것이 다형성이다. 이때 역할은 인터페이스, 구현은 인터페이스를 구현한 클래스나 구현 객체로 보면된다. 따라서 객체를 설계할 때 역할과 구현을 명확히 분리해야 한다. 다형성의 본질은 다음과 같다.
- 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있다.
- 다형성의 본질을 이해하려면 협력이라는 객체 사이의 관계에서 시작해야 한다.
- 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다. (어떤 객체를 사용하든 인터페이스는 동일하기 때문이다.)
단, 이와 같이 역할과 구현으로 실생활을 구별하는 것의 한계는 역할 자체가 변하면 클라이언트, 서버 모두 큰 변경이 발생하다는 점이다. 이전의 예시에서 자동차를 비행기로 변경한다던가, 공연의 역할을 A역할이 아닌 새로운 C역할로 변경하는 등의 문제가 발생하면 큰 변경이 필요할 것이다. 따라서 인터페이스를 안정적으로 잘 설계하는 것이 중요하다.
3. 스프링과 객체 지향
객체 지향의 꽃은 다형성이다. 스프링은 이 다형성을 극대화해서 이용할 수 있게 도와준다. 제어의 역전(IoC), 의존관계 주입(DI)와 같은 것들은 다형성을 활용해 역할과 구현을 편리하게 다루도록 지원하는 기능이다. 따라서 스프링을 사용하면 구현을 편리하게 변경할 수 있다.
'BackEnd > Spring' 카테고리의 다른 글
[Spring] test 코드 작성 기초 (0) | 2023.08.18 |
---|---|
[Spring] 좋은 객체 지향 설계의 5가지 원칙 (SOLID) (0) | 2023.08.17 |
[Spring] 스프링이란? (0) | 2023.08.08 |
[Spring] 스프링 탄생 배경 (0) | 2023.08.07 |
[Spring] ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed (0) | 2023.05.14 |