[Spring] 스프링으로 전환하기

Narcoker·2023년 8월 12일

Spring

목록 보기
5/19

스프링으로 전환하기

[Spring] 객체 지향 설계와 스프링
[Spring] 좋은 객체 지향 설계의 5가지 원칙(SOLID)
[Spring] 객체 지향 원리 적용
[Spring] IoC, DI

위 글에서 작성한 코드들은 스프링을 사용한 코드가 아닌 순수 자바 코드만으로 작성된 것이다.

이제 이 코드에 스프링을 적용해볼 것이다.

AppConfig 스프링 기반 변경

AppConfig에 설정을 구성한다는 뜻의 @Configuration 을 붙여준다.
각 메서드에 @Bean 을 붙여준다. 이렇게 하면 스프링 컨테이너에 스프링 빈으로 등록한다.

이때 key, value 형태로 저장된다.
@Bean(name = "newname") 과 같이 따로 이름을 설정하지 않으면
메서드의 명을 스프링 빈의 key로 사용한다.

주의

이름은 반드시 유일해야한다.
같게 된다면 다른 빈이 무시되거나, 기존 빈을 덮어버리는 등 오류가 발생한다.

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 OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy());
	}
   
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
   
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

MemberApp에 스프링 컨테이너 적용

이전 코드는 필요한 객체를 AppConfig 를 사용해서 직접 조회했지만,
이제부터는 스프링 컨테이너를 통 해서 필요한 스프링 빈(객체)를 찾아야 한다.

스프링 빈은 applicationContext.getBean() 메서드를 사용해서 찾을 수 있다.

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

public class MemberApp {
     public static void main(String[] args) {
    //  수정 전
    //  AppConfig appConfig = new AppConfig();
    //  MemberService memberService = appConfig.memberService();

   	// 수정 후
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        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("find Member = " + findMember.getName());
	} }

OrderApp에 스프링 컨테이너 적용

MemberApp 과 동일하다.

이전 코드는 필요한 객체를 AppConfig 를 사용해서 직접 조회했지만,
이제부터는 스프링 컨테이너를 통 해서 필요한 스프링 빈(객체)를 찾아야 한다.

스프링 빈은 applicationContext.getBean() 메서드를 사용해서 찾을 수 있다.

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.order.Order;
import hello.core.order.OrderService;
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();\
   
   // 수정 후
      ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
      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", 10000);
      System.out.println("order = " + order);
    }
}

스프링 컨테이너

ApplicationContext 를 스프링 컨테이너라 한다.

기존에는 개발자가 AppConfig 를 사용해서 직접 객체를 생성하고 DI를 했지만,
이제부터는 스프링 컨테이너를 통해서 사용한다.

스프링 컨테이너는 @Configuration 이 붙은 AppConfig 를 설정(구성) 정보로 사용한다.

여기서 @Bean 이 라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다.
이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다.
스프링 빈은 @Bean 이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다.
( memberService, orderService )

기존에는 개발자가 직접 자바코드로 모든 것을 했다면
이제부터는 스프링 컨테이너에 객체를 스프링 빈으로 등록하고,
스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다.

스프링 컨테이너를 사용해야하는 이유

코드가 약간 더 복잡해진 것 같은데, 스프링 컨테이너를 사용하면 어떤 장점이 있을까?

chatGPT 내용

제어의 역전 (IoC: Inversion of Control)

개발자가 직접 객체를 생성하고 관리할 필요가 없습니다.
스프링 컨테이너가 대신하여 객체의 생명주기를 관리합니다.
이로 인해 코드는 더 깔끔하고 유지보수가 쉬워집니다.

의존성 주입 (DI: Dependency Injection)

스프링 컨테이너는 빈(Bean) 간의 의존성을 자동으로 주입해줍니다.
이로 인해 각 클래스는 자신의 의존성에 대해 알 필요가 없게 되며,
유연하고 확장성 있는 코드를 작성할 수 있습니다.

단일체(Singleton) 관리

스프링 컨테이너는 기본적으로 빈을 단일체로 관리합니다.
따라서 애플리케이션 전체에서 해당 빈의 인스턴스는 하나만 존재하게 됩니다.

AOP (Aspect-Oriented Programming) 지원

스프링은 AOP를 내장하여 교차 관심사(cross-cutting concerns)를 분리하여 코드 중복을 줄이고,
핵심 비즈니스 로직에만 집중할 수 있게 도와줍니다.

트랜잭션 관리

스프링은 선언적 트랜잭션 관리를 지원하여,
복잡한 트랜잭션 관리 로직 없이도 데이터의 일관성과 안정성을 유지할 수 있습니다.

다양한 모듈 지원

스프링 프레임워크는 웹 MVC, 보안, 데이터 엑세스, 메시징 등 다양한 모듈을 제공합니다.
이러한 모듈들은 잘 통합되어 있어 개발자는 필요한 기능을 효과적으로 사용할 수 있습니다.

테스트 용이성

스프링의 의존성 주입 기능을 활용하면, 유닛 테스트와 통합 테스트를 쉽게 작성하고 실행할 수 있습니다.

경량성

스프링은 경량 프레임워크이므로, 애플리케이션의 부하를 최소화하면서 필요한 기능만을 사용할 수 있습니다.

커뮤니티와 지원

스프링은 크고 활발한 커뮤니티와 광범위한 문서화를 통해 지원받을 수 있습니다.
이로 인해 문제 해결이나 새로운 기능에 대한 학습이 더욱 쉬워집니다.

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글