[Spring] IoC (Inversion of Control) 제어의 역전

yeonjiyooo·2025년 9월 29일
0

Spring

목록 보기
1/2

Spring과 첫 만남...🫠 IoC에 대해 공부해보자!

1. IoC란?

객체 생성과 의존성 주입과 같은 과정을 개발자가 직접 하지 않고, 그 제어를 외부(프레임워크, 컨테이너)에 위임하는 것을 의미합니다. 개발자는 객체의 제어를 직접 할 필요가 없으므로 복잡한 요소들을 신경쓰지 않고 비지니스 로직에만 집중할 수 있게 됩니다.

과거에는 개발자들이 직접 코드 안에서 new 키워드를 사용해서 객체를 생성
→ 어떤 객체가 어떤 객체를 사용할 지 의존 관계 설정 필요

OrderService orderService = new OrderService();
PaymentService paymentService = new PaymentService();
orderService.setPaymentService(paymentService);

IoC 를 사용하게 되면 객체 생성과 의존성 주입을 IoC 컨테이너가 대신 수행

@Service
public class OrderService {
	//OrderService와 PaymentService는 의존 관계
	private final PaymentService paymentService;
	
	@Autowired
	public OrderService(PaymentService paymentService) {
		this.paymentService = paymentService;
	}
}

🔼 코드 실행 과정

  • 스프링이 @Service 가 붙은 OrderService를 Bean으로 등록하려고 함
  • 이 때, OrderService는 PaymentService 라는 의존성이 필요
  • 스프링이 컨테이너에서 PaymentService 타입의 Bean을 찾아 생성자의 파라미터로 넣어줌

⇒ OrderService는 스스로 new PaymentService() 하지 않고도 정상적으로 동작!

2. IoC 사용 이유

  1. 객체 간 결합도 감소: 개발자가 직접 new 키워드를 통해 객체를 생성하지 않고 IoC 컨테이너가 객체 생성과 연결을 외부에서 처리해주기 때문에 객체 간 결합이 느슨해집니다.

    OrderServicePaymentService 라는 추상 타입에만 의존
    구체적인 구현체 (ex. kakaoPay, TossPay) 에는 의존하지 않음

    따라서 구현체가 바뀌어도 (ex. kakaoPayTossPay) OrderService 수정 필요 X
    ⇒ 객체지향의 OCP 원칙과도 연결 🔗

    OPEN 확장에는 열려있음: 새로운 구현체 추가 및 변경 가능
    CLOSED 수정에는 닫혀있음: OrderService는 건들이지 않음

  1. 지속가능성 및 확장성: 어플리케이션의 새로운 요구사항이나 기능에도 수정해야 하는 코드를 최소화하고 보다 간단하게 처리할 수 있게 됩니다. 이런 유연성이 지속 가능성을 보장하고 시스템이 커져도 확장성을 확보할 수 있게 해줍니다.

  2. 테스트 용이성: 진짜 객체 대신 Mock 객체를 쉽게 주입할 수 있어 테스트가 용이해집니다.

    진짜 객체 대신 테스트용 mock 객체 주입 가능
    mock 객체: 실제 객체처럼 동작하지만, 테스트 목적에 맞게 단순화, 제어된 동작만 수행하는 객체

    → DB 연결, 외부 API 호출 같은 무거운 동작 없이 빠르게 테스트 가능

    PaymentService mockPaymentService = Mockito.mock(PaymentService.class);
    OrderService orderService = new OrderService(mockPaymentService);

+) @Controller @Service @Repository + @Component

스프링은 어플리케이션 실행 시 IoC 컨테이너를 만들고 그 안에 관리할 객체 = Bean 등록
→ 일일히 XML이나 @Bean 으로 등록할 수 도 있음 BUT 번거로움

Component Scan 컴포넌트 스캔 기능

특정 패키지를 탐색하여 @Component 계열 annotaion이 붙은 클래스를 찾아 자동으로 Bean 등록
@Component @Controller @Service @Repository 모두 스캔 대상

@Component : 생성한 class를 Bean 으로 등록할 때 사용하는 가장 기본적인 annotaion

  • @Controller : 웹 계층에서의 Controller 역할(ex. HTTP 요청 처리)을 위한 객체
  • @Service : 비지니스 로직 계층에서 사용 비지니스 로직을 담당하는 서비스 클래스라는 의미
  • @Repository : 데이터 접근 계층에서 사용하고 DB와 연동하는 코드에 붙임

사실 전부 @Component 로 써도 Bean 등록은 됨
하지만 가독성을 향상시키고, 부가 기능을 적용하기 위해 상황에 맞는 annotation 선택

profile
1 ^ 365 = 1 이지만 1.01 ^ 365 = 37쩜 어쩌고... 이다!

0개의 댓글