[Spring] 자바 프로젝트 생성 - 인터페이스와 구현의 구분, DIP / OCP 규칙 위반 예시
비즈니스 요구사항과 설계회원회원 가입, 회원 조회 기능일반 / VIP 등급회원 데이터: 자체 DB 구축 or 외부 시스템과 연동(미확정)주문과 할인 정책회원은 상품 주문 가능회원 등급에 따라 할
jelliclesu.tistory.com
AppConfig 생성
AppConfig.java
- 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스
- 사용 영역과, 객체를 생성하고 구성(Configuration)하는 영역으로 분리
- 구현 객체 생성
- MemberServiceImpl
- MemberRepository
- OrderServiceImpl
- DiscountPolicy
- 생성자를 통한 주입(연결) - 인스턴스의 참조(레퍼런스)
- MemberServiceImpl ➡︎ MemoryMemberRepository
- OrderServiceImpl ➡︎ MemoryMemberRepository, DiscountPolicy
생성자 주입
- 생성자를 통해 어떤 구현 객체가 들어올지(주입될지)는 알 수 없음 - 오직 외부(AppConfig)에서 결정
- MemeberServiceImpl.java
- MemoryMemberRepository 를 의존하지 않고, MemberRepository 인터페이스만 의존 ➡️ DIP 준수
- OrderServiceImpl.java
- FixDiscountPolicy 를 의존하지 않고, DiscountPolicy 인터페이스만 의존 ➡️ DIP 준수
- MemoryMemberRepository, DiscountPolicy 객체의 의존관계가 주입
할인 정책 수정
- 구성 역할을 담당하는 AppConfig만 변경하면 됨 - OrderServiceImpl 를 포함해서 사용 영역의 어떤 코드도 변경 X
클래스 다이어그램

- 객체의 생성과 연결은 AppConfig 가 담당
- DIP 준수: MemberServiceImp 은 MemberRepository 인 추상에만 의존
- 관심사의 분리: 객체를 생성하고 연결하는 역할과 실행하는 역할이 명확히 분리
회원 객체 인스턴스 다이어그램

- appConfig 객체는 memoryMemberRepository 객체를 생성, 그 참조값을 memberServiceImpl 을 생성하면서 생성자로 전달
- 클라이언트인 memberServiceImpl 입장에서 보면 의존관계를 마치 외부에서 주입 - DI(Dependency Injection: 의존성 주입)
AppConfig 실행
- MemberApp.java / OrderApp.java 에 AppConfig 적용
AppConfig appConfig = new AppConfig();
MemberService memberService = appConfig.memberService();
OrderService orderService = appConfig.orderService();
AppConfig 리팩터링
리팩터링 전
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderSerive orderSerive() {
return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy()
);
}
}
- 중복이 있으며, 역할에 따른 구현이 잘 보이지 않음
리팩터링 후
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
private MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public OrderSerive orderSerive() {
return new OrderServiceImpl(memberRepository(), discountPolicy()
);
}
private DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
- new MemoryMemberRepository() 중복 제거
- 역할과 구현 클래스가 한눈에 들어와 애플리케이션 전체 구성이 어떻게 되어있는지 빠르게 파악 가능
'Spring' 카테고리의 다른 글
[Spring] 스프링 컨테이너(Container)와 스프링 빈(Bean) (1) | 2024.09.23 |
---|---|
[Spring] 좋은 객체 지향 설계 / IoC(Inversion of Control) / DI(Dependency Injection) (2) | 2024.09.21 |
[Spring] 자바 프로젝트 생성 - 인터페이스와 구현의 구분, DIP / OCP 규칙 위반 예시 (0) | 2024.09.21 |
[Spring] 객체 지향 설계, 다형성, SOLID (2) | 2024.09.20 |
[Spring] AOP(Aspect Oriented Programming) (0) | 2024.09.12 |