다들 설 명절은 가족과 함께 행복하게 보내셨나요?
저번 포스팅에 이어서 객체 지향 설계의 5가지 원칙의 진짜 의미와 자바의 다형성만으로 해결하지 못하는 문제를 스프링은 어떻게 도와주는 지에 대해서 열심히 적어볼게요.
함께 가시죵 ㅎㅎ 🙃
SOLID가 뭐야 ?
SOLID는 클린코드의 밥아저씨로 유명한 로버트 마틴이 객체지향 프로그래밍을 설계하기 위해서 필요한 5가지 원칙을 소개했는데 앞글자 만 따서 SOLID라고 불리게 되었어요.
말그대로 시간이 지나도 유지보수와 확장이 쉽게 만들게 하기 위한 원칙이에요.
기술면접 하게되면 간혹 물어볼 수도 있는데, 내용을 완전히 이해하지 못햇다면 어? 그거 아는데 뭐였지 하는 바로 그거에요. ㅎㅎ 위키백과에서 써져있는 그대로 옮겨 볼게요.
SRP (Single responsibility principle) - 단일 책임 원칙
한 클래스는 하나의 책임만을 가져야 한다.
OCP (Open/Closed principle) - 개방 폐쇄 원칙
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
LSP (Liskov substitution principle) - 리스코프 치환 원칙
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
ISP (Interface segregation principle) - 인터페이스 분리 원칙
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
DIP (Dependency inversion principle) - 의존관계 역전 원칙
프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.
이것 만으로는 뭔말인지 모르겟어요... 저는... ㅎㅎ
그럼 하나 하나 따져 봅시다. !!
첫번째는 SRP - 단일 책임 원칙
한 클래스가 하나의 책임만 가져야한다.?
뭔가 그럴싸하게 들리지만 어디까지가 하나의 책임인거지? 모호하지 않나요? ㅎㅎ
클래스의 책임이란 클래스를 사용하는 주체가 바라보는 관점이에요.
예를 들어 여자라는 클래스가 있다고 가정하면, 여자는 남자친구한테는 여자친구라는 역할을 가지고 있고, 어머니한테는 딸, 회사한테도 또다른 역할을 가지고 있겠죠? 그런데 이걸 한 클래스에 모두 모아논다면 나중에 변경하기에 여간 어렵지 않겠어요? 그래서 여자친구, 딸, 직장인 요런식으로 각각의 역할 별로 나누자 라는 이야기에요.
그러면 나중에 해당하는 역할을 가진 클래스만 변경하면 되니깐, 유지보수가 쉽겠죠? 핵심은 변경의 최소화입니다.
두번째는 OCP - 개방 폐쇄 원칙
OCP도 변경을 최소화하라는 것과 비슷한데요.
변경하지 말고 확장을 하자 라는게 핵심이에요.
기존의 역할을 가진 클래스를 새로운 기능으로 변경된 클래스로 바꾸고 싶을때? 기존 클래스를 모두 바꿔야 할까요? 기존의 클래스를 사용하는 코드도 있을테고, 또 나중에 사용할 수 도 있자나요? 그래서 변경을 할꺼면 자바의 인터페이스를 구현한 새로운 클래스를 만들어서 갈아끼우기만 하자.!! 확장하자.!! 요렇게 이해하시면 좋을 것 같네요.
세번째는 LSP - 리스코프 치환
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
이거는 이름만 어렵지 내용은 쉽습니다. 다형성에서 인터페이스를 구현한 구현체는 인터페이스의 규약을 지켜야 한다는 것이에요. 만약 자동차라는 인터페이스에서 출발하는 go()라는 기능이 있는데, 자동차 인터페이스를 구현한 테슬라의 go()가 멈추는 기능이라면? 해당하는 구현체를 믿고 사용할 수 없겠죠?
네번째는 ISP - 인터페이스 분리 원칙
ISP는 인터페이스도 역할을 잘게 나누라는 이야기 입니다. 예를들어 자동차 인터페이스에서 운전, 정비 인터페이스로 분리하고 이를 사용하는 주체도 운전자, 정비사로 분리한다면? 정비 인터페이스가 변경되어도 이를 사용하는 정비사에만 영향을 미치니깐 역할이 명확해지고 관리하기 쉬울 것 같네요.
마지막은 DIP - 의존관계 역전 원칙
쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻이에요.
이전 글에서 역할과 구현의 분리에 대해서 이야기 했었는데, 클라이언트가 역할만 의존해서 유연하게 구현체를 변경하는 것을 말해요. 만약 에 개발자가 Mac만 사용할 수 있다고 해볼게요. Window를 써야할 때 어떻게 사용하는지 모른다면? Window운영체제에서는 개발을 할 수 없을 거에요. 개발자는 컴퓨터의 기능을 가진 역할을 다룰줄 안다면, mac 컴퓨터든 window 컴퓨터든 개발을 할 수 있는 거에요. 인터페이스를 의존해야 유연하게 다룰수 있다. 이것이 핵심입니다.
이해가 조금 되셨을까요?
객체 지향의 핵심은 다형성이라 특징을 잘 활용해서 역할과 구현을 분리하는 것이라고 제가 이야기 했었는데,
자바의 다형성만으로 해결하지 못하는 문제가 있어요.
자바의 다형성만으로 해결을 못한다고 ?
다형성이 객체지향의 핵심이라면서요... 이거 가지고 안돼요?
우선 어떤 문제가 있는지 살펴 볼게요. 예를 들어 멤버의 비즈니스로직을 관리하는 MemberService에서 메모리에 데이터를 저장하는 것을 DB에 저장하는 로직으로 변경하려고 한다고 할게요. 멤버를 저장하는 역할을 가진 MemberRepository를 불러와야 겠죠?
MemberRepository m = new MemoryMemberRepository(); // 기존 코드
MemberRepository m = new JdbcMemberRepository(); // 변경 코드
분명 MemberRepository 인터페이스를 사용했고, 다형성으로 Memory, Jdbc 구현체로 만들었고, 구현체를 변경하고 싶은데 MemberService의 클라이언트 코드를 고쳐야 하네요? 이러면 클라이언트 코드를 변경을 하게 되니깐 OCP원칙에 위반 또한 MemberService가 구현 클래스를 직접 선택하는 코드가 되네요? DIP원칙도 위반하게 됩니다.
뭔가가 더 있으면 완벽하게 좋은 객체 지향 설계를 할 수 있을텐데 말이죠.
스프링이 자바의 객체 지향의 특징을 잘 살려낼 수 있도록 도와주는 프레임워크라고 했었죠? ㅎㅎ
글이 늘어져서 한번 더 포스팅을 나눠야 할 것 같네요.
이제 정말로 Spring이 왜 생겨났는지, 조금씩 알게되는 것 같지 않으신가요? 😝
또 스프링이 자바를 어떻게 도와줄지 궁금하시지 않으신가요? ㅎㅎ
바로 이어서 써보도록 할게요. 끝까지 함께하면 좋겠습니다.
부족한 글 읽어 주셔서 감사합니다. 또한 잘못된 내용 있으면 지적해주시면 감사하겠습니다. 🙏
Reference
https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84) - SOLID 객체지향 설계 위키백과
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8 - 스프링 핵심원리 - 기본편 (김영한)
하얀종이개발자
'Spring' 카테고리의 다른 글
JPA n+1 문제는 왜 생기는걸까? (0) | 2023.05.06 |
---|---|
서블릿(Servlet)이 뭔지 궁금해? (0) | 2023.03.09 |
의존관계주입 or 의존성주입 with spring #3 (0) | 2023.01.24 |
좋은 객체 지향 설계란? with spring #1 (0) | 2023.01.15 |
Spring Boot에서 GraphQL 활용법 (1) | 2022.05.22 |