[스프링 핵심원리] - 2.스프링 핵심 원리 이해2(객체지향 원리 적용) (6)

Chooooo·2022년 10월 6일
0
post-thumbnail

이 글은 강의 : 김영한님의 - "스프링 핵심원리 - 기본편"을 듣고 정리한 내용입니다. 😁😁


스프링으로 전환하기

지금까지 순수 자바 코드만으로 DI를 적용했다면 이제 스프링을 사용해보기.

AppConfig 스프링 기반으로 변경

package hello.core;

import hello.core.discount.DiscountPolicy;
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 {
    // MemberService 역할 스프링 빈 등록
    @Bean
    public MemberService memberService() {
        // 생성자 주입
        return new MemberServiceImpl(memberRepository());
    }

    // MemberRepository 역할 스프링 빈 등록
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();    // 메모리 회원 저장소로
    }

    // OrderService 역할 스프링 빈 등록
    @Bean
    public OrderService orderService() {
        // 생성자 주입
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    // DiscountPolicy 역할 스프링 빈 등록
    @Bean
    public DiscountPolicy discountPolicy() {
        //return new FixDiscountPolicy();     // 고정 할인 정책으로
        return new RateDiscountPolicy();    // 정률 할인 정책으로 변경
    }
}
  • @Configuration: 설정 파일을 만들기 위한 어노테이션
  • @Bean: 스프링 빈으로 등록

변경된 것을 보면 AppConfig 에 @Configuration이 붙은 것을 알 수 있다. 구성을 한다는 뜻인데, 이 클래스가 설정을 구성해준다라고 Spring 에 알려주는 역할이라고 보면 된다.
각 메서드에는 @Bean이 붙어있다. 이러면 해당 클래스가 스프링 컨테이너에 스프링 빈으로 등록이 된다는 뜻.

MemberApp에 스프링 컨테이너 적용

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MemberApp {

    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();
        // AppConfig에 있는 설정 정보를 토대로 스프링 컨테이너에 넣어서 관리
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        // 스프링 컨테이너를 통해 memberService를 찾음(이름=메서드명, 타입)
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

        Member member = new Member(1L, "memberA", Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println("new member = " + member.getName());
        System.out.println("findMember = " + findMember.getName());
    }
}

기존에는 주석처리된 2줄처럼 AppConfig 객체를 생성하고 appConfig의 memberService() 메서드를 호출해 memeberService 객체를 직접 조회했다.
이제 스프링 컨테이너를 적용하면...
AppConfig의 설정 정보를 갖고 스프링 빈스프링 컨테이너에 넣어서 관리한다.
스프링 컨테이너를 통해 스프링 빈(memberService)를 조회해서 사용한다.

OrderApp에 스프링 컨테이너 적용

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.order.Order;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class OrderApp {
    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();
//        OrderService orderService = appConfig.orderService();
        // AppConfig에 있는 설정 정보를 토대로 스프링 컨테이너에 넣어서 관리
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        // 스프링 컨테이너를 통해 memberService, orderService를 찾음(이름=메서드명, 타입)
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);

        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "itemA", 20000);

        System.out.println("order = " + order); // order.toString() 출력됨
        //System.out.println("order.calculatePrice = " + order.calculatePrice()); // 할인된 최종 가격
    }
}

기존에는 주석처리된 3줄처럼 AppConfig 객체를 생성하고 appConfig의 memberService(), OrderService()메서드를 호출해 memberService, orderService 객체를 직접 조회했다.

이제 스프링 컨테이너를 적용하면...
AppConfig의 설정 정보를 갖고 스프링 빈스프링 컨테이너에 넣어서 관리.
스프링 컨테이너를 통해 스프링 빈(memberService, orderService)를 조회해서 사용한다.

스프링 컨테이너

코드에 있는 ApplicationContext를 스프링 컨테이너라고 한다.
기존에는 우리가 직접 AppConfig를 만들어서 객체를 생성하고 DI를 했지만, 이제부터는 스프링 컨테이너를 통해서 사용을 하게 된다.
스프링 컨테이너는 @Configuration 이 붙어있는 AppConfig를 설정(구성) 정보로 사용한다. 여기에서 @Bean 이라 적힌 메서드를 모두 호출해서 반환되는 객체(구현 객체)를 스프링 컨테이너에 등록하는 과정을 거친다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다.
스프링 빈은 @Bean 이 붙은 메서드의 이름을 스프링 빈의 이름으로 사용한다. 위의 코드에서 예를 들자면 memberService, orderService 가 되겠다.
스프링으로 전환하기 전에 개발자가 필요한 객체를 AppConfig를 사용해서 직접 조회했는데, 이제는 스프링 컨테이너를 통해서 필요한 스프링 빈(객체)를 찾아야한다. 스프링 빈은 applicationContext.getBean() 메서드를 사용해서 찾을 수 있다.
기존에는 개발자가 직접 자바코드로 모든것을 했다면 이제부터는 스프링 컨테이너에 객체를 스프링 빈으로 등록하고 스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경이 된 것이다.

  • ApplicationContext: 스프링 컨테이너
  • applicaiotn.getBean(): 스프링 컨테이너에서 해당 (이름, 타입)인 스프링 빈을 조회

스프링 빈은 default로 @Bean이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다(memberService, orderService)

// @Bean이 붙은 메서드명 = memberService
@Bean
public MemberService memberService() {
    // 생성자 주입
    return new MemberServiceImpl(memberRepository());
}

// 스프링 빈의 이름 = memberService
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

그리고 getBean 메서드로 스프링 컨테이너를 통해 필요한 스프링 빈(객체)를 조회.

즉, 지금까지 순수 자바 코드로는 AppConfig를 사용해 직접 객체를 생성하고 DI했지만 스프링 컨테이너에 객체를 스프링 빈으로 등록하고 스프링 컨테이너에서 스프링 빈을 찾아 사용하도록 변경하였다.

아직 이해가 되지 않지만... 스프링을 쓰는 이유는 강의를 들을수록 더 명확해진다고 하니 계속 이해하면서 가보자.

profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글