[인프런] 스프링 핵심원리 기본편-핵심 원리 이해2

경운·2025년 7월 27일
0

스프링 핵심원리

목록 보기
3/7
post-thumbnail

※ 본 게시글은 인프런 스프링 핵심 원리 - 기본편 강의를 바탕으로 작성하였습니다.
강의 내용을 참고하여 개인적으로 정리한 글입니다.


🐣 새로운 할인 정책 개발

기존 할인 정책은 VIP에게 무조건 1,000원 할인(FixDiscountPolicy)
기획자가 10,000원 주문 시 1,000원 할인, 20,000원 주문 시 2,000원 할인을 원한다..

  • 정률 할인 (VIP는 10%)로 변경을 원한다
    → 우리는 새로운 구현체 RateDiscountPolicy 만들어보자

  • RateDiscountPolicy 클래스

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class RateDiscountPolicy implements DiscountPolicy {

    private int discountPercent = 10;

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return price * discountPercent / 100;
        } else {
            return 0;
        }
    }
}

🐣 정률 할인 정책 적용과 문제점

public class OrderServiceImpl implements OrderService{
 // private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
  • ``OrderServiceImpl가 인터페이스 DiscountPolicy만 의존 하는 것 같나?
  • 그렇지 않다. 자세히 보면 FixDiscountPolicyRateDiscountPolicy직접 new를 사용하고 있다


FixDiscountPolicyRateDiscountPolicy로 변경하는 순간 OrderServiceImpl의 코드도 함께 변경해야하는 경우가 발생한다

따라서 위 코드는 객체 지향 설계 원칙인 DIP 위반, OCP 위반

위 문제를 어떻게 해결을 하면 좋을까??


🐣 AppConfig 등장 - 관심사 분리

객체 생성과 연결을 담당하는 별도 클래스 AppConfig 생성
비유하자면 AppConfig는 공연 기획자, OrderService는 배우

  • AppConfig 클래스
package hello.core;

import hello.core.Order.OrderService;
import hello.core.Order.OrderServiceImpl;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MembrServiceImpl;
import hello.core.member.MemoryMemberRepository;

public class AppConfig {

    public MemberService memberService(){
        return new MembrServiceImpl(new MemoryMemberRepository());
    }

    public OrderService orderService(){
        return new OrderServiceImpl(
        			new MemoryMemberRepository(),
        			new FixDiscountPolicy());  //쉽게 교체 가능
    }
}
  • AppConfig는 실제 동작에 필요한 구현 객체 생성

    • MembrServiceImpl, MemoryMemberRepository, OrderSerivceImpl, FixDiscountPolicy
  • AppConfig는 생성한 객체 인스턴스의 참조를 생성자를 통해서 주입(연결)

번외로 테스트 코드를 작성할 때 @BeforeEach를 사용하면 각 테스트를 실행하기 전에 호출

따라서 MembrServiceImpl, OrderSerivceImpl실행에만 집중하면 된다


🐣 AppConfig 리팩터링

현재 AppConfig 클래스는 중복 있고, 역할에 따른 구현이 명확하게 안보인다

  • 중복이 제거되고, 역할이 명확하게 보이도록 함수를 분리해보자
package hello.core;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//실제 동작에 필요한 "구현 객체를 생성"
//생성한 객체 인스턴스의 참조를 "생성자를 통해서 주입(연결)"
//전체 구성이 어떻게 되어있는지 빠르게 파악 가능

@Configuration //설정 정보
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        //return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}
//@Bean을 사용하면 해당 코드들이 "스프링 컨테이너"에 등록

💡드디어 스프링 등장!
AppConfig@Configuration + @Bean을 추가하면 스프링 컨테이너에서 getBean으로 주입 받는다

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

🐣 객체 지향 설계 원칙 적용

원칙설명
SRPOrderSerivceImpl은 할인 정책까지 신경쓰지 않아도 된다
DIPDiscountPolicy 인터페이스에만 의존한다
OCP할인 정책 변경 시 AppConfig만 수정하면 된다

🐣 IoC, DI?

IoC - 제어의 역전과 DI - 의존성 주입은 해당 링크에 들어가면 설명이 있습니다

[인프런] 스프링 핵심원리 기본편-객체지향 설계와 스프링


AppConfig를 통해서 객체 지향 설계 원칙을 적용하고, 스프링이 없이도 DI를 구현할 수 있음을 경험하였다 다음 포스팅은 이제 스프링 컨테이너와 스프링 빈을 활용하는 것으로 오겠습니다~

개발 잫하고 싶다,.,

0개의 댓글