스프링의 IoC/DI, AOP의 개념

🗓️

  • 본격적으로 스프링에서 사용되는 코드 패턴과 개념에 대해서 파고 들어간다.

IoC/DI

IoC; Inversion of Control

  • 제어의 역전
  • 객체를 직접 생성하지 않고 외부에서 구현체를 넣어줌으로써 제어권을 거꾸로 가지고 가는 현상
  • IoC는 즉, 설계의 패턴이다.
  • 실체에 의존할 것인가 추상화에 의존할 것인가

DI; Dependency Injection

  • 의존성 주입
  • 외부에서 의존성을 받는 행동. 즉, 외부에서 new로 생성된 객체를 받는다.
  • DI는 즉, 동작 그 자체다.
  • 의존성을 어떻게 가질 것인가?

IoC/DI

  • 관계를 짧고 쉽게 정리하자면 → DI를 하면 IoC가 일어난다.
  • 객체의 생성, 소멸, 작동의 주도권(즉, 제어권)이 객체 자신에게 있지 않고 외부의 컨테이너에 있다.

AOP

Aspect-Oriented Programming

  • 관점 지향적인 프로그래밍 (굳이 해석하자면)
  • 공통적인 코드들 (cross-cutting concern)을 묶어서 관리한다.

자바에서의 AOP

  • 컴파일 (AspectJ) JAVA----(AOP)----> Class
  • 바이트코드 조작(AspectJ) JAVA ---- Class ---- (AOP) ---> 메모리
  • 프록시 객체를 생성하는 디자인 패턴 → 스프링의 AOP방식

런타임에 프록시 객체를 생성해 기능을 삽입하는 패턴

스프링에서의 AOP

  1. 스프링AOP는 로직 주입이라고 볼 수 있다.
  2. 프록시 패턴을 활용한다.

Proxy pattern

Before: 프록시를 사용하지 않는 코드

// Service.java
public class Service {
    public String doSomething(){
        return "Work it!";
    }
}
// ClientWithDirect.java
public class ClientWithDirect {
    public static void main(){
        Service service = new Service();
        sout(service.doSomething());
    }
}

일반적인 객체 사용 방법이다.

After: 프록시를 사용하도록 변경

//ServiceInterface.java
public interface ServiceInterface {
    String doSomething()
}
//Service.java
public class Service implements ServiceInterface{
    public String doSomething(){
        return "Work it!";
    }
}
//Proxy.java
public class Proxy implements ServiceInterface {
    ServiceInterface service; // ← DIP 가능

    public String doSomething(){
        sout("Service가 실행되기 전에 뭔갈 넣을수도 있고");
        service = new Service();
        sout("생성자 뒤에도 가능하지.");
        return service.doSomething();   
    }
}
//ClientWithProxy.java
public class ClientWithProxy{
    public static void main(){
        ServiceInterface proxy = new Proxy(); // ← OCP
        sout(proxy.doSomething());
    }
}

이렇게하면 다른 서비스를 구현하더라도 프록시 코드를 통해 영향을 받지 않을 수 있다.

  • 프록시 패턴의 객체를 사용할때 최상위 객체를 불러오는게 아니라 비즈니스 로직의 구현체를 타입으로 지정한다. ServiceInterface proxy
  • 생성자는 프록시 구현체를 지정한다 new Proxy()