Spring Boot

IoC, DI

운동하는 주니어개발자 2023. 4. 22. 02:05

오늘 공부한 내용은 IoC와 DI에 대해서 공부하였다.

우선 IoC와 DI에 대해 간략하게 설명한 후에 실습한 내용을 작성하겠다.

IoC - 스프링에서는 일반적인 Java 객체를 new로 생성하여 개발자가 관리하는 것이 아닌 Spring Container에 모두 맡긴다.

즉 개발자에서 → 프레임워크로 제어의 객체 관리의 권한이 넘어 갔음 으로 “제어의 역전” 이라고 한다.

DI - IoC는 개발자가 객체를 관리하는 것이 아니기 때문에 개발자는 어떻게 객체를 사용하여야 하는지 문제이다.

개발자가 Spring Container의 객체를 사용하기 위해 외부로 부터 주입을 하는것이 DI라고 할 수 있다.

DI의 장점으로는 총 4가지가 있다.

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

이렇게 장점은 4가지로 볼 수 있고 다음으로는 IoC와 DI에 대해 실습한 내용을 작성하겠다.

DI먼저 작성하겠다. 이번 실습은 임의의 URL을 사용하여 Base64Encoder과 urlEncoder을 출력하는 예제이다.

저번에 했던 예제지만 이번 예제는 다르다 DI를 활용하여 객체를 생성하고 IoC에 어떻게 주입을 할 것인지에 대한 예제이다. 즉 개발자가 직접 관리하지 않고 Spring Container가 직접 관리하게 끔 하기 위한 예제이다.

Base64Encoder

package com.company.ioc;

import java.util.Base64;

public class Base64Encoder implements IEncoder{
    public String encode(String message) {
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}

Encoder

package com.company.ioc;

public class Encoder {
    private IEncoder iEncoder;

    public Encoder(IEncoder iEncoder) {
        this.iEncoder = iEncoder;
    }

    public String encode(String message) {
        return iEncoder.encode(message);
    }
}

IEncoder

package com.company.ioc;

public interface IEncoder {
    String encode(String message);
}

Main

package com.company.ioc;

public class Main {
    public static void main(String[] args) {
        String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";

        Encoder encoder = new Encoder(new UrlEncoder());
        String result = encoder.encode(url);
        System.out.println(result);
    }
}

UrlEncoder

package com.company.ioc;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class UrlEncoder implements IEncoder{
    public String encode(String message) {
        try {
            return URLEncoder.encode(message, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Base64Encoder 결과
UrlEncoder 결과

다음은 IoC에 대해 설명하겠다. IoC는 객체를 개발자가 직접 관리하는 것이 아니기 때문에 어떻게 객체를 가져와서 사용하여야 하는지 문제이다. 이런 상황일 때 DI를 사용하여 외부에서 주입받아 사용하면 된다.

즉 DI에서 작성한 객체를 IoC에 주입을 받아 객체를 사용하는 것이다. 실습에 대해 작성하겠다.

ApplicationContextProvider

package com.example.ioc_ioc;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}

Base64Encoder

package com.example.ioc_ioc;

import org.springframework.stereotype.Component;

import java.util.Base64;

@Component("base74Encoder")
public class Base64Encoder implements IEncoder{
    public String encode(String message) {

        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}

Encoder

package com.example.ioc_ioc;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;


public class Encoder {
    private IEncoder iEncoder;

    public Encoder(IEncoder iEncoder) {
        this.iEncoder = iEncoder;
    }

    public void setIEncoder(IEncoder iEncoder) {
        this.iEncoder = iEncoder;
    }

    public String encode(String message) {
        return iEncoder.encode(message);
    }
}

IEncoder

package com.example.ioc_ioc;

public interface IEncoder {
    String encode(String message);
}

IocIocApplication

package com.example.ioc_ioc;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Base64;

@SpringBootApplication
public class IocIocApplication {

    public static void main(String[] args) {
        SpringApplication.run(IocIocApplication.class, args);

        ApplicationContext context = ApplicationContextProvider.getContext();

        // Base64Encoder base64Encoder = context.getBean(Base64Encoder.class);
        // UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);

        Encoder encoder = context.getBean("base64Encode",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);
    }

}

@Configuration
class AppConfig {

    @Bean("base64Encode")
    public Encoder encoder(Base64Encoder base64Encoder) {
        return new Encoder(base64Encoder);
    }

    @Bean("urlEncode")
    public Encoder encoder(UrlEncoder urlEncoder) {
        return new Encoder(urlEncoder);
    }
}

UrlEncoder

package com.example.ioc_ioc;

import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Component
public class UrlEncoder implements IEncoder{
    public String encode(String message) {
        try {
            return URLEncoder.encode(message, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Base64Encoder 결과
UrlEncoder 결과

오늘 공부한 내용은 여기 까지이다. 다음시간에는 AOP에 대해 배우고 AOP실무 사례에 대해 실습을 하겠다.

그럼 다음시간에 오겠다. 수고.

'Spring Boot' 카테고리의 다른 글

AI 검증 비즈니스 프로젝트  (0) 2024.08.23
Object Mapper에 모범사례 실습  (0) 2023.04.22
PUT, DELETE, Response내려주기 실습  (0) 2023.04.22
GET(QueryParame ter), POST  (0) 2023.04.22
GET API 실습  (0) 2023.04.22