섹션 2. 객체 지향 설계와 스프링
- 스프링이란?
스프링 --> 여러 기술의 모음
스프링 프레임워크 --> 스프링의 핵심
스프링부트 --> 스프링을 더 쉽게
스프링 데이터 --> RDB 의 CRUD는 비슷함. 이를 편리하게 쓰게 하기 위한 것. 스프링 데이터 JPA가 제일 많이 쓰임
스프링 프레임워크가 제일 중요!
이 안에는 핵심 기술, 웹 기술, 데이터 접근 기술 등이 들어있음
스프링부트 --> 스프링을 편리하게 사용할수 있도록 지원
- Tomcat 웹 서버 내장
- starter 종속성 : jpa, aop 등의 라이브러리를 쓸 때 하나만 가져오면 나머지를 가져오게 됨
- 스프링과 3rd party 라이브러리 자동 구성
- 관례에 의한 간결한 설정
스프링이라는 단어는 문맥에 따라 다르게 사용됨
- 스프링 DI 컨테이너 기술
- 스프링 프레임워크
- 스프링부트, 스프링 프레임워크 모두 포함한 스프링 생태계
스프링의 핵심?
- 스프링은 자바 언어 기반의 프레임워크
- 자바? 객체지향 언어
- 스프링은 객체지향 언어가 가진 강력한 특징을 살려내는 프레임워크
- 스프링은 좋은 객체지향 어플리케이션을 개발할 수 있게 도와주는 프레임워크
- 좋은 객체 지향 프로그래밍이란?
객체지향 프로그래밍?
- 컴퓨터 프로그램을 "객체" 들의 모임으로 파악하고자 하는 것.
- 각각의 객체는 메시지를 주고받고, 데이터를 처리
- 객체지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 함. - 레고블럭 조립하듯이, 컴퓨터 부품 교체하듯이
다형성?
- 예를 들어, 자동차가 여러 가지 있는데, 운전자가 자동차를 바꿔도 자동차의 역할은 변하지 않는다.
- 클라이언트에 영향을 주지 않고 새로운 기능을 제공 가능하다.
역할-구현 구분
- 클라이언트는 대상의 역할(인터페이스)만 알면됨
- 클라이언트는 구현 대상의 내부 구조를 몰라도 됨
- 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향받지 않음
- 클라이언트는 구현 대상 자체를 변경해도 영향받지 않음
역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스, 구현 객체
구현 < 인터페이스
다형성의 본질
- 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경 가능
- 다형성의 본질을 이해하려면 협력이라는 객체사이의 관계에서 시작해야 함
- 클라이언트 변경 없이 서버의 구현 기능을 유연하게 변경 가능
결론
- 인터페이스를 안정적으로 잘 설계하는 것이 중요
- 무조건 역할-구현 분리가 좋진 않다. 인터페이스 자체가 변하면?
스프링과 객체 지향
- 다형성이 제일 중요
- 스프링은 다형성을 극대화해서 이용할 수 있게 지원
- 스프링의 IoC(제어의 역전) DI(의존관계 주입) 은 다형성을 활용해 역할-구현을 편하게 다룰 수 있도록 지원
- 스프링 사용 시 구현을 편리하게 변경 가능
- 좋은 객체 지향 설계의 5가지 원칙(SOLID)
SOLID란? 클린코드로 유명한 로버트 마틴이 좋은 객체지향 설계의 5가지 원칙을 정리
1. SRP - 단일 책임 원칙
- 하나의 클래스는 하나의 책임
- 그러나 책임이 모호함 : 책임이 클수도, 작을수도 있고, 문맥과 상황에 따라 다르다.
- 중요한 기준은 변경임 - 변경이 있을 때 파급 효과가 적으면 SRP를 잘 따른 것
- 책임의 범위를 적절히 정하는 것도 중요함.
2. OCP - 개방-폐쇄 원칙
- 제일 중요한 원칙, 소프트웨어 요소는 확장에는 열려있고, 변경에는 닫혀 있어야 한다.
- 이해가 안 된다면, 다형성을 생각해 보자. 인터페이스를 구현한 클래스를 만드는 것은 확장이다. (기존 코드 변경 없음)
- 문제점? 클라이언트가 구현 클래스를 직접 선택 --> 구현 객체 변경 시 클라이언트 코드를 변경해야 함
- 이는 다형성을 사용했지만, OCP 원칙에는 위배된다.
- 객체를 생성, 연관관계 맺어주는 별도의 설정자 필요 --> 스프링이 이를 담당
3. LSP - 리스코프 치환 원칙
- 프로그램의 객체는 프로그램의 정확성을 깨트리지 않아야 함 --> 자동차 인터페이스의 엑셀은 앞으로 가는 기능인데, 뒤로 가게 구현하면 LSP 위반이다.
4. ISP - 인터페이스 분리 원칙
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 자동차 인터페이스만 있다면 너무 큼 --> 이를 운전 인터페이스와 정비 인터페이스로 분리한다.
- 사용자 클라이언트는 운전자 클라이언트와 정비사 클라이언트로 분리
- 정비 인터페이스가 바뀌어도 운전자 클라이언트에 영향 없음
5. DIP - 의존관계 역전 원칙
- 이것도 중요한 원칙 중 하나
- 구현 클래스에 의존하지 말고, 인터페이스에 의존해야 함. 즉, 구체화에 의존하지 말고, 추상화에 의존해야 함.
- 다형성에 의해 DIP 위반함.
다형성이 객체지향의 핵심이지만, 이것 만으로는 OCP와 DIP를 지킬 수 없다.
- 객체 지향 설계와 스프링
- 스프링에 객체지향 얘기가 왜 나왔냐?
- 스프링은 다형성 + OCP + DIP를 가능하게 지원
- DI(Dependency Injection) : 의존성 주입
- DI 컨테이너 제공
- 인터페이스를 먼저 설계하고 구현체로 구현하자!
- 다만, 인터페이스 도입 시 추상화라는 비용 발생
섹션 3. 스프링 핵심 원리 이해1 - 예제 만들기
- 비즈니스 요구사항과 설계
회원 도메인 설계?
- 회원 도메인 요구사항
1. 회원가입 및 조회
2. 회원은 일반과 VIP등급
3. 회원 데이터는 자체 DB 혹은 외부시스템과 연동 가능(미확정)
* 회원 서비스 : MemberServiceImpl
주문/할인정책?
1. 회원은 상품 주문 가능
2. 회원 등급에 따른 할인정책 적용 가능
3. 할인 정책은 모든 VIP는 1000원 할인 (변경될수도)
4. 할인 정책은 변경가능성 높음. 미확정
- 회원 도메인 개발
- Interface
MemberRepository.java | MemberService.java |
- 구현체
Member.java | MemberServiceImpl.java | MemoryMemberRepository.java |
- 회원 도메인 실행과 테스트
현재 이 코드는 순수 java만을 이용해서 테스트 코드를 만들었다.
이번엔 JUnit을 이용해서 만들어보도록 하자.
given / when / then 패턴으로 junit 테스트 코드를 짠 다음에 실행해 주면 된다.
회원 도메인 설계에서...
DIP를 위배하지 않았는가..? --> 위배했다.
- 주문과 할인 도메인 설계
클라이언트 -> 주문 서비스 역할 -> 할인 정책역할
-> 회원 저장소 역할
주문 도메인 객체 다이어그램
클라이언트 -> 주문 서비스 구현체 -> 메모리 회원 저장소
-> 정액 할인 정책
*정률 할인 정책을 바꿔도 구현체만 바꾸면 됨
주문 도메인 객체 다이어그램 2
클라이언트 -> 주문 서비스 구현체 -> DB 회원 저장소
-> 정률 할인 정책
- 주문과 할인 도메인 개발
- 멤버 등급에 따른 할인 구현
(Interface)DiscountPolicy.java | (Class)FixDiscountPolicy.java |
- 주문
(Class)Order.java | (Interface)OrderService.java |
(Class)OrderServiceImpl.java |
|
생성자, getter, setter생성, 할인 있는 경우 할인가 포함해 가격 리턴 | 각각 인터페이스와 구현체 작성 |
- 주문과 할인 도메인 실행과 테스트
java로만 테스트 | junit테스트 |
'WINK-(Web & App) > Spring Boot 스터디' 카테고리의 다른 글
[2024-2 SprintBoot 스터디] 김아리 #4주차 (1) | 2024.11.20 |
---|---|
[2024-2 SpringBoot 스터디] 정호용 #4주차 섹션 4~5 (0) | 2024.11.19 |
[2024-2 SpringBoot 스터디] 윤성욱 #3주차 (1) | 2024.11.14 |
[2024-2 SpringBoot 스터디] 조상혁 #3주차 (2) | 2024.11.13 |
[2024-2 SpringBoot 스터디] 탁태현 #2주차 (0) | 2024.11.07 |