이번 편에서는 이전에 만들었던 회원/주문 예제에 객체 지향 원칙을 적용하면서 구조적으로 어떤 문제가 있었는지를 확인해본다.
특히 DIP(의존 역전 원칙) 과 OCP(개방-폐쇄 원칙)을 위반한 부분을 짚고, 이후 개선 방향까지 함께 살펴본다.
할인 정책 교체 시 발생하는 문제
기존 구조에서는 할인 정책을 다음과 같이 고정해서 사용하고 있었다.
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
이 경우 새로운 할인 정책(RateDiscountPolicy)으로 교체하려면 코드를 직접 수정해야 한다.
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
이는 OCP 위반이다.
코드 확장에는 닫혀 있어야 하지만, 구현체 변경 시 클래스 자체를 수정해야 하기 때문이다.
또한 OrderServiceImpl은 DiscountPolicy라는 인터페이스뿐 아니라 구체 클래스에도 의존하고 있다.
이는 DIP 위반이다.
추상화(인터페이스)에만 의존해야 하지만, 구체화에도 함께 의존하고 있기 때문이다.
개선 방향
의존 대상을 인터페이스(추상화)로만 설정하고, 구체 객체는 외부에서 주입 받도록 구조를 바꿔야 한다.
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
이 구조는 DIP를 만족시키지만, 의존 객체를 누군가 대신 생성하고 주입해줘야 한다는 새로운 과제를 만든다.
관심사의 분리 필요성
비유를 하자면, 연극에서 배우들은 대본대로 연기만 하면 되고, 어떤 배우를 무대에 세울지는 **기획자(연출자)**가 결정한다.
개발에서도 마찬가지다.
서비스 구현체는 자신의 역할에만 집중하고, 어떤 구현체를 사용할지는 별도의 설정 클래스에서 결정해야 한다.
이 설정 역할을 담당할 객체가 바로 AppConfig이다.
다음 편에서는 AppConfig를 통해 의존 객체를 주입받는 구조로 개선하면서
어떻게 OCP와 DIP를 모두 지키는 객체 지향 구조를 만들 수 있는지 확인해본다.
'Spring' 카테고리의 다른 글
[Spring 완전 정복 시리즈] 9편 - 스프링으로 전환하고 의존관계 주입 자동화하기 (1) | 2025.07.26 |
---|---|
[Spring 완전 정복 시리즈] 8편 - AppConfig로 객체 지향 설계 완성하기 (0) | 2025.07.26 |
[Spring 완전 정복 시리즈] 6편 - 예제 만들기: 역할과 구현 분리의 시작 (1) | 2025.07.26 |
[Spring 완전 정복 시리즈] 5편 - 객체 지향 설계와 스프링: DI가 왜 중요한가? (0) | 2025.07.23 |
[Spring 완전 정복 시리즈] 4편 - 좋은 객체 지향 설계의 5가지 원칙 (SOLID) (0) | 2025.07.23 |