스프링

IoC & DI

inle 2024. 2. 25. 19:52

IoC

IoC는 Inversion of Control, 즉 제어의 역전이다.

  • 기존의 프로그래밍 방식에서는 개발자가 프로그램의 제어 흐름을 직접 제어한다. 예를 들어, 객체를 생성하고 의존성을 해결하는 등의 작업은 개발자가 직접 수행한다.
  • IOC에서는 제어 흐름의 일부가 라이브러리나 프레임워크에 의해 제어된다. 즉, 개발자는 제어의 흐름을 역전시킨다. 
  • IOC는 객체의 생성, 생명주기 관리, 의존성 해결 등을 담당한다.

 

 

제어의 역전은 다른 객체를 직접 생성하거나 제어하는 것이 아니라 외부에서 관리하는 객체를 가져와 사용하는 것을 말한다.

이전과는 다르게 클래스 B 객체를 직접 생성하는 것이 아니므로, 어딘가에서 받아와서 사용한다. 이처럼 제어의 역전을 적용하면 객체를 외부에서 관리하게 되고, 실제로 사용할 때에는 외부에서 제공해주는 객체를 받아오게 된다. 스프링에서는 제어의 역전 개념을 중요한 컨셉으로 삼고 있으며, 방금까지 설명한 내용에서 외부(=객체를 관리하고 관리하는 주체)를 “스프링 컨테이너”라고 한다.

 

IoC를 쓰는 이유

  1. 느슨한 결합 (Loose Coupling):
    • IOC는 객체 간의 결합도를 낮춘다. 객체가 직접적으로 의존하는 객체를 생성하거나 관리하는 것이 아니라 외부에서 주입받기 때문에, 객체 간의 의존성이 줄어든다. 이는 유지보수성을 향상시키고 코드를 변경할 때 발생하는 부작용을 최소화한다.
  2. 유연성과 재사용성 증가:
    • IOC를 통해 의존성이 외부에서 주입되기 때문에, 객체를 재사용하거나 다른 구현체로 교체하기가 쉬워진다. 새로운 기능을 추가하거나 기존 기능을 변경할 때 유연하게 대응할 수 있습니다.
  3. 테스트 용이성:
    • IOC를 사용하면 의존성을 쉽게 대체할 수 있다. 따라서 유닛 테스트(Unit Test)를 작성할 때 테스트 대상 객체에 대한 의존성을 모의(Mock) 객체 등으로 대체하여 테스트를 더 쉽게 수행할 수 있다.
  4. 제어의 역전:
    • IOC는 제어의 역전 개념을 기반으로 한다. 개발자가 직접 객체의 생성과 생명주기를 관리하는 것이 아니라 프레임워크나 컨테이너가 이를 담당한다. 이는 개발자가 비즈니스 로직에 집중할 수 있도록 해준다.
  5. 코드 중복 최소화:
    • IOC 컨테이너는 객체의 생성과 관리를 중앙에서 처리하기 때문에 코드 중복을 최소화할 수 있다. 예를 들어, 객체의 생성 및 초기화 코드를 여러 곳에 반복해서 작성할 필요가 없다.

이러한 이유들로 IOC를 사용하면 코드의 유지보수성과 확장성을 높일 수 있으며, 테스트와 개발 과정을 보다 효율적으로 수행할 수 있다.

 

DI

  • 의존성이란 객체가 다른 객체에 의존하여 동작하는 것을 말한다. 예를 들어, 클래스 A가 클래스 B의 인스턴스를 사용한다면, A는 B에 의존성을 가진다.
  • DI는 객체 간의 의존성을 외부에서 설정해 주는 디자인 패턴이다. 이는 객체 간의 결합도를 낮추고 재사용성과 유연성을 향상시킨다.
  • 스프링에서는 XML, 어노테이션, 자바 설정 등을 통해 DI를 구현할 수 있다. 스프링 컨테이너는 이러한 설정 정보를 바탕으로 객체 간의 의존성을 관리하고 주입한다.

 

어노테이션 기반 자바 코드 설정

@Configuration
public class AppConfig {

        @Bean
        public MemberService memberService() {
                return new MemberServiceImpl(memberRepository());
        }
}
  • @Configuration : 1개 이상의 빈을 제공하는 클래스의 경우 반드시 명시해야 한다.
  • @Bean : 클래스를 빈으로 등록할 때 사용한다.

 

XML 기반의 스프링 빈 설정

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://
www.springframework.org/schema/beans/spring-beans.xsd">

     <bean id="memberService" class="hello.core.member.MemberServiceImpl">
             <constructor-arg name="memberRepository" ref="memberRepository"/>
     </bean>
</beans>
  • XML 기반의 설정 파일을 보면 자바 코드로 된 설정 파일과 거의 비슷하다는 것을 알 수 있다.
  • XML 기반으로 설정하는 것은 최근에 잘 사용하지 않는다.

 

여기에서 사용하는 @Autowired라는 애너테이션은 스프링 컨테이너에 있는 빈이라는 것을 주입하는 역할을 한다. 빈은 쉽게 말해 스프링 컨테이너에서 관리하는 객체를 말한다.

 

 

DI를 쓰는 이유

  1. 유연성과 재사용성 증가:
    • DI를 통해 객체가 직접 의존하는 객체를 생성하거나 관리하지 않고 외부에서 주입받기 때문에, 객체 간의 결합도가 낮아진다. 이는 객체를 재사용하거나 다른 구현체로 교체할 때 유연하게 대응할 수 있게 된다.
  2. 테스트 용이성:
    • DI를 사용하면 테스트를 위해 가짜 객체(Mock Objects)를 주입하여 테스트를 수행할 수 있다. 이는 유닛 테스트(Unit Test)를 작성할 때 테스트 대상 객체에 대한 의존성을 외부에서 제어할 수 있어 테스트가 더 쉬워진다.
  3. 결합도 감소:
    • DI를 사용하면 객체 간의 의존성을 외부에서 설정하므로, 객체 간의 결합도가 낮아진다. 이는 한 객체의 변경이 다른 객체에 미치는 영향을 최소화하여 유지보수성을 향상시킨다.
  4. 코드 중복 최소화:
    • DI 컨테이너가 객체의 생성과 관리를 중앙에서 처리하기 때문에 코드 중복을 최소화할 수 있다. 객체의 생성 및 초기화 코드를 여러 곳에 반복해서 작성할 필요가 없어진다.
  5. 제어의 역전:
    • DI는 제어의 역전(Inversion of Control) 개념을 기반으로 한다. 개발자가 객체의 생성과 생명주기를 직접 제어하는 것이 아니라 프레임워크나 컨테이너가 이를 담당한다. 이는 개발자가 비즈니스 로직에 집중할 수 있도록 해준다.

 

'스프링' 카테고리의 다른 글

ConcurrentHashMap vs 레코드 락  (0) 2024.10.11
ConcurrentHashMap  (1) 2024.10.11
MVP 단계 트러블 슈팅  (0) 2024.04.12
Mybatis와 JPA  (2) 2024.03.12
스프링컨테이너와 빈  (0) 2024.03.03