객체지향 프로그래밍
- 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉
객체
들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. - 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.
객체지향에 대한 자세한 내용은 다음 포스팅을 참고하자.
https://sasca37.tistory.com/133?category=1223547
객체지향 특징
다형성
객체지향프로그래밍에서는 다형성이 가장 중요하다. 다음 운전자와 자동차의 예시를 보자.
K3를 타는 운전자가 아반테로 차를 바꿔도 운전할 수 있다. 즉, 현실 세계에서는 눈에 보이지 않지만 역할과 구현을 분리하고 있다. 프로그래밍의 관점에서도 역할과 구현을 분리하여 설계하여야 프로그램이 유연하고 변경이 용이해진다.
운전자는 차를 바꿔도 운전을 할 수 있다. 즉, 자동차가 바뀌어도 운전자에게 영향을 주지 않는다.
운전자는 자동차 운전하는 방법(자동차 역할)에만 집중할 수 있도록 설계하는 것이 중요하다.
역할과 구현의 분리
여기서 클라이언트는 위의 예시에서 운전자가 된다.
- 클라이언트는 대상의 역할(인터페이스)만 알면 된다.
- 클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
- 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.
- 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
자바 언어에서는 이러한 역할과 구현의 분리를 다형성을 활용해서 적용한다.
역할은 인터페이스를, 구현은 인터페이스를 구현한 클래스, 구현 객체를 사용한다.
객체 설계 시 역할(인터페이스)을 먼저 부여하고, 그 역할을 수행하는 구현 객체를 만들어서 설계한다.
- 다음 예시를 보자.
MemberService
는MemberRepository
를 의존 관계로 갖는다. 즉, 클라이언트는 인터페이스만 알고 있고 인터페이스의 구현체인 역할을 타입 다형성을 통해 유연하게 변경할 수 있도록 개발하는 것이다. 스프링에서는 다형성을 통해IoC
,DI
기능을 제공하여 역할과 구현을 편리하게 다룰 수 있도록 지원한다.
객체지향 설계 5원칙 (SOLID)
- 객체지향에 대해서 깊게 알기 위해선 다형성과 로버트 마틴이 정의한
SOLID
5원칙에 대해 알고 있어야 한다.
SRP (단일 책임 원칙)
- 한 클래스는 하나의 책임만 가져야 한다. 즉, 하나의 클래스는 하나의 지점만 고칠 수 있어야 한다.
- 상황에 따라 다를 수 있으므로 중요한 판단의 기준은 변경이 있는 상황이다. 변경을 통한 파급 효과가 적으면 SRP를 잘 준수 했다고 볼 수 있다.
OCP (개방-폐쇄 원칙)
- 소프트웨어 요소는 다형성을 활용해서 확장에는 열려있으나 변경에는 닫혀있어야 한다. 이게 무슨 말인가 싶을 것이다. 다음 예시를 보자.
public class MemberService {
//private MemberRepository memberRepository = new MemoryMemberRepository();
privtae MemberRepository memberRepository = new JdbcMemberRepository();
}
MemberService
가 의존하는MemberRepository
인터페이스에서new
연산자를 통해 구현체를 변경하는 예시를 보자. 기존의 코드를 변경해야 되기 때문에 타입 다형성을 사용했지만ocp
원칙을 지킬 수 없다.
확장을 하려면 다형성을 사용해도 당연히 기존 코드를 변경해야한다. 객체지향설계의 관점에서 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다. 이 기능을 스프링에서 DI, IoC가 해결해준다.
LSP (리스코프 치환 원칙)
- 객체는 정확성을 깨뜨리지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야한다.
- 자동차 인터페이스의 엑셀은 앞으로 간다는 기능이라면, 구현체에서 뒤로 가게 구현하면 규칙을 위반한다. 즉, 속도가 느리더라고 무조건 앞으로 가는 기능을 구현해야한다.
ISP (인터페이스 분리 원칙)
- 특정 클라이언트를 위한 여러 인터페이스가 범용 인터페이스 하나 보다 낫다.
- 자동차 인터페이스가 있다면, 이 인터페이스를 운전 인터페이스, 정비 인터페이스로 분리하는 것이 인터페이스가 명확해지고, 대체 가능성이 높아진다.
DIP (의존관계 역전 원칙)
- 프로그래머는 구현 클래스에 의존하지 않고 인터페이스에 의존해야된다. 구현체에 의존하게 되면 변경이 아주 어려워진다. 즉, 객체지향의 설계원칙과 동일한 의미이다.
public class MemberService {
//private MemberRepository memberRepository = new MemoryMemberRepository();
privtae MemberRepository memberRepository = new JdbcMemberRepository();
}
MemberService
는 인터페이스 뿐아니라new
연산자로 구현체에도 현재 의존하고 있다.
다형성만으로는 OCP, DIP를 지킬 수 없다는 결론이 나온다. 외부에서 의존 관계를 주입해주는 DI와 IoC와 같은 설정이 있어야만 해결이 가능하다.
본 포스팅은 인프런 김영한님 강의(스프링 핵심원리 - 기본편)를 토대로 정리한 내용입니다.
OCP와 DIP에 대해서 자세한 정리는 다음 포스팅을 참고하자.
https://sasca37.tistory.com/161