객체지향(OOP) 2가지 핵심 포인트
본 포스팅은 인프런 김영한님의 ‘스프링 핵심 원리 - 기본편’ 강의를 듣고 정리한 내용을 바탕으로 복습을 위해 작성하였습니다.
객체지향이 필요한 이유는 '변경'과 '확장'에 유연하게 대응하기 위해서다. (개발자들이 유지보수 하기 편하게 짜자는 얘기)
레고 블럭 갈아끼우듯, 컴퓨터 부품을 갈아 끼우듯 쉽고 유연하게 변경이 가능하도록 만들어진 코드가 최고의 코드다.
→ 이런 코드를 위해 필요한 개념이 다형성 이다.
다형성
아래 예시를 보면, 운전자는 운전 인터페이스를(핸들, 악셀, 브레이크) 알기 때문에 차종이 달라도 바로 운전이 가능하다.
여기에 안전 인터페이스(에어백), 편의 인터페이스(후방 카메라) 등을 레고처럼 조립만 해주면,
개발자는 다양한 차종을 큰 지연없이 찍어낼수(코딩할수) 있다.
→ 즉, 우리는 인터페이스에 집중해야지 미니쿠퍼 같은 실체에 집중할 필요가 없다.

객체지향 SOLID 원칙
2가지만('변경'과 '확장') 기억하라고 했는데 갑자기 5가지를 제시해서 당황하면 안된다. 결국 2가지로 수렴하기 때문이다.
• SRP (single responsibility principle)
한 클래스는 하나의 책임만 가져야 한다.
→ A 클래스의 코드만 변경했는데, 느닷없이 B, C 객체의 기능이 같이 변경되는 민폐를 끼치면 안된다.
즉, 서로 다른 클래스끼리 연관성을 최대한 분리 시켜야 된다.
• OCP (Open/closed principle)
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다
→ 코드를 변경하지 않으면서 확장을 어떻게 해야하는가? 가능한가? 정답은 다형성으로 객체들을 찍어내면 가능하다.
• LSP (Liskov substitution principle)
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다
→ 자동차 인터페이스의 엑셀은 앞으로 가라는 기능이지,
새로운 객체를 확장시 엑셀 기능을 뒤로 가게 구현하면 LSP 위반
• ISP (Interface segregation principle)
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다
→ 왼쪽 코드처럼 운전을 통합하는 driving과 fix처럼 범용적인 인터페이스 두개보다는
오른쪽 코드처럼 작은 단위로 분리하는게 내부 의존성을 약화시켜 리팩토링, 코드 변경, 재배포를 쉽게 한다.

• DIP (Dependency inversion principle)
구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻.
→ 위 예제에서 핸들 기능이 업데이트 됐을때, 테슬라, 미니쿠퍼에 기능을 각각 찾아가 바꾸는 것은 매우 비효율 적이다.
근본인 인터페이스(핸들, 브레이크,,,) 코드만 변경하면 한번에 끝날 것을,,,
위 법칙들을 살펴보니, 결국 쉬운 코드 변경과 확장을 돕기 위해 만들어진 법칙들이니 쫄 필요는 없을것 같다.
그러나, SOLID 법칙에는 문제점이 있다.
의존관계 역전 원칙(DIP)에서는 인터페이스에 의존하고 구현체에 의존하지 말라고했는데, OCP쪽을 보면 직접 구현클래스를 대입 해주면서 구현체에 의존성을 가지는 것을 볼 수 있다.
다형성 만으로는 부품을 쉽게 갈아치울수 없고, 구현 객체 변경시 클라이언트 코드도 같이 변경되는 것을 볼 수 있다.
즉, 다형성만으로는 OCP, DIP원칙을 위배할 수밖에 없다.
Java 진영에서는 이를 보완 해주는 프레임워크를 만들어 냈다.
객체지향과 스프링
바로 위 섹션에서 객체지향 설계의 5가지 원칙중 OCP, DIP가 다형성만으로는 위배된다고 했는데,
이를 해결하기 위한 프레임워크가 바로 스프링이다.
결국, 스프링은 옛날 Java 개발자들이 객체지향 설계 5가지 원칙 (SOLID)을 모두 지키면서 개발을 하려다보니 위와 같이 위반되는 항목을(OCP, DIP) 해결하는 일을 매번 추가로 했었고, 궁극적으로 이를 보완하는 프레임워크를 만들었는데 그게 스프링이다. (정확히는 DI 컨테이너)
추천 도서
• 객체지향 책 추천: 객체지향의 사실과 오해
• 스프링 책 추천: 토비의 스프링