Spring - 객체지향 프로그래밍의 이해
우선 이 블로그의 내용은 개인적인 공부기록용도 있지만 김영한님의 스프링 기본편을 바탕으로 한점이 있기 때문에
강의한 내용과 정리내용이 거의 비슷한 점이다. 강의를 기록으로 남기는 이유는 필자또한 스프링을 학습하고 프로젝트 등 여러가지를 진행하면서 안다고 생각하지만
공부는 하면 할수록 배울게 많다라는 생각이 들기때문에(결국 다 알지는 못한다는 사실..) 기록을 남기지 않나 생각한다. 그 부분을 참고하고 블로그를 읽으면 될것 같다.
스프링 프레임워크
핵심 기술 : 스프링 DI컨테이너 , AOP, 이벤트, 기타
웹 기술 : 스프링 MVC, 스프링 WebFlux
데이터 접근 기술 : 트랜잭션, JDBC, ORM, XML
기술 통합 : 캐시, 이메일, 원격접근, 스케줄링
테스트: 스프링 기반 테스트 지원
이런것들을 편리하게 사용자 하는것들이 Spring boot의 출현이다.
즉, 스프링과 스프링부트의 차이점이 뭐냐? 물어봤을 때
스프링은 자바를 편리하게 사용하기 위해 나온 프레임워크이며,
스프링부트는 스프링을 편리하게 사용하기 위해 나온 프레임워크이다. 사실 이게 전부이다.
그럼에도 스프링과 스프링부트마다의 차이점이 분명 존재하기 때문에 각자 쓰는것이 아닌가?
스프링부트는 단독으로 스프링 애플리케이션을 생성 할 수 있으며, 외부 구성 같은 프로덕션 준비 기능 제공인데
이건 외부라이브러리를 쉽게 사용할 수 있다는 장점정도가 있을것이다.
단순히 스프링을 한다는 건 개발자의 중요한 업무 중 하나인 API를 이용해서 게시판을 만드는것보다
결국중요한 것은 자바로 만드는 객체 지향 언어를 만들기 위함이 아닐까? 라는 생각이든다.
결국 효율적인 객체 지향적인 코드를 만들기 위해 쓰이는 프레임워크중 하나라고 볼수 있을것이다.
객체지향프로그래밍의 특징
다형성 영어로 Polymorphism 이라고도 한다. 운전자와 자동차가 있다 생각해보자. 자동차는 여러 종류의 모델이 출시가 될것이다.
운전자는 어떤 종류던 차를 운전할 수 있다 가정하여 타게된다면 자동차의 모델이 변경되도 운전자의 역할은 그대로 할 수있게 되는데
운전자를 클라이언트라고 비유를 한다면 직접적인 클라이언트의 개입이 필요없이 자동차의 구현만으로 역할이 가능하게끔한다.
이걸 다형성에서 대표적으로 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미 라고 하는 것과 동일하다.
자바 언어에서 다형성을 활용한다하면 역할은 인터페이스, 구현은 인터페이스를 구현한 클래스, 구현 객체
역할과 구현을 분리한다는 것은 역할과 구현이라는 컨셉을 다형성을 통해 객체 상으로 가져올 수 있다는 점이 있음.
유연하고, 변경이 용이하다는 점, 확장 가능한 설계가 가능하다는 점, 클라이언트에 영향을 주지 않게 변경이 가능
스프링에서는 제어의 역전(Ioc), 의존관계 주입(DI)은 다형성을 활용하여 역할과 구현을 편리하게 다룰 수 있도록 지원
그렇다면 객체 지향을 잘 짜기 위해서 어떤 원칙을 지켜가며 만들어 내야할까?
- 단일 책임 원칙(Single responsibility principle) : SRP
- 개방 폐쇄 원칙(Open/closed principle) : OCP
- 리스코프 치환 원칙(Liskov substitution principle) : LSP
- 인터페이스 분리 원칙(Interface segregation principle) : ISP
- 의존관계 역전 원칙(Dependency inversion principle) : DIP
다형성의 원칙을 지킨 코드
(개방 폐쇠 원칙을 만든 코드)
public class OneService{
private OneRepository oneRepository = new OneMemberRepository();
}
public class OneService{
//private OneRepository oneServiceRepository = new OneMemberRepository();
private OneRepository oneServiceRepository = new TwoMemberRepository();
리스코프 치환 원칙
-> 자동차의 기능 중 액셀을 만드는 기능을 하는데, 상식적으로 액셀의 기능을 만든다면 속도의 한정된 범위내에 앞으로 나아기기 마련인데
조금 특이한 엔지니어(?)의 발상으로 액셀을 뒤로가게 한다면 기능적으로 액셀의 기능은 맞지만 제대로 쓸 수 없을것이다.
그로인해 LSP리스코프 치환 원칙에서는 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다라는 점을 지니고, 액셀은 앞으로 나아가야한다는 원칙이 존재하게 된다.
DIP 의존관계 역전 원칙
-> 클라이언트 코드가 구현코드를 바라보는 것이 아닌, 인터페이스 코드를 바라보는 것
MemberService 가 MemberRepository만 바라보게 할것, 위의 처럼 OneMemberRepository 혹은 TwoMemberRepositroy가 아닌 상태로 말이다.
정리
- 객체 지향의 핵심은 다형성
- 다형성 만으로 구현 객체 변경할때 클라이언트 코드도 같이 변경
- 다형성 만으로 OCP, DIP를 지킬 수 없다는 사실
사실 김영한님 강의를 보기 전까지 스프링을 접하면서 다형성의 개념만 알았지 DIP 의존관계 역전 원칙에 대해서 정확히 몰랐다.
그저 Service는 ServiceImpl 이나 혹은 Repository로 분리는 시키는 정도만 알았지, 정작 중요한 Why(왜)? 위배가 되는지 몰랐다.
당연히 그 DIP원칙을 지킨다면 Service가 그저 Repository만 받게되면 구현코드는 만들수 가 없게 된다.
다음 블로그는 코드도 가져오면서 객체지향의 프로그램을 짜기위해서 어떤식으로 접근해야 좋을지에 대한 기록을 남겨보려한다.
기억보다는 기록 !! 이라는 말이 더 와닿는 요즘.. 블로그도 꾸준히 남기는 습관을 길러야겠다 !!