러러 2024. 6. 8. 02:40

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

스프링에서는 Java객체를 new로 생성지 않고 Spring Container에가 맡겨 객체를 주입 받는다.
즉, 개발자에서 프레임워크로 제어의 객체 관리의 권한이 넘어 갔음으로 제어의 역전 이라고 한다.

 

Spring Container로부터 객체를 주입받는 것을 DI라고 한다.

DI(Dependenct Injection) : 의존성 주입

DI 장점

- 의존성으로 부터 격리시켜 코드 테스트에 용이하다.
- DI를 통하여, 불가능한 상황을 Mock와 같은 기술을 통하여, 안정적으로 테스트 가능하다.
- 코드를 확장하거나 변경할 때 영향을 최소화 한다.(추상화)
- 순환참조를 막을 수 있다.

 

IoC/ DI 예제 코드

Base64와 Url인코딩하는 로직을 예로 들자

// 인코딩 인터페이스
interface IEncoder {
  String encode(String message);
}

// base64인코딩 구현
class Base64Encoder implements IEncoder {
  @Override
  public String encode(String message) {
    return Base64.getEncoder().encodeToString(message.getBytes());
  }
}

// url인코딩 쿠현
class UrlEncoder implements IEncoder {
  @Override
  public String encode(String message) {
    return URLEncoder.encode(message, StandardCharsets.UTF_8);
  }
}

// 인코딩 사용 부분
public class Encoder {
  private final IEncoder iEncoder;

  // 인코딩 타입 설정
  public Encoder(IEncoder iEncoder) {
    this.iEncoder = iEncoder;
  }

  // 로직 수행
  public String encode(String message) {
    return iEncoder.encode(message);
  }
}

 

위와 같은 클래스들이 있을 때 이 클래스들을  Spring Container에 의해 객체를 주입 받아서 사용하려면

@Bean으로 등록해서 Spring Container에서 관리할 수 있게 만들어 줘야한다.

 

Spring에서  Bean으로 등록할 수 있는 방법에는 여러가지가 있지만 여기에서는 @Component가 아닌 @Bean으로 등록하도록 하겠다.

// 스프링 시작할 때 먼저 읽으면서 Bean등록
@Configuration
public class EncoderConfig {
  @Bean
  public Base64Encoder base64Encoder() {
    return new Base64Encoder();
  }

  @Bean
  public UrlEncoder urlEncoder() {
    return new UrlEncoder();
  }


  @Bean(name = "base64Enc")
  public Encoder base64Enc(Base64Encoder base64Encoder) {
    return new Encoder(base64Encoder);
  }

  @Bean(name = "urlEnc")
  public Encoder urlEnc(UrlEncoder urlEncoder) {
    return new Encoder(urlEncoder);
  }
}

 

이렇게 되면 Spring Container에 객체 전달을 완료한 것이고, 이를 주입 받아서 사용하면 된다.

@SpringBootApplication
public class SpringDiIocApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringDiIocApplication.class, args);
    Encoder encoder = applicationContext.getBean("base64Enc", Encoder.class);
//    Encoder encoder = applicationContext.getBean("urlEnc", Encoder.class);
    String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";

    String result = encoder.encode(url);
    System.out.println("result = " + result);
  }

}

/*
결과:
result = d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==

*/