PHpullh
학습 라이브러리/Java/DI(의존성 주입) 원리

JAVA · 디자인패턴

DI(의존성 주입) 원리

Spring의 핵심 원리인 의존성 주입을 직접 구현하여 이해합니다.

디자인패턴고급DI의존성주입Spring원리IoC

핵심 설명

Spring의 핵심 원리인 의존성 주입을 직접 구현하여 이해합니다.

Java code

import java.util.*;

// 간단한 DI 컨테이너 구현
class DIContainer {
    private final Map<Class<?>, Object> instances = new HashMap<>();
    private final Map<Class<?>, Class<?>> bindings = new HashMap<>();

    // 인터페이스 -> 구현체 바인딩
    <T> void bind(Class<T> iface, Class<? extends T> impl) {
        bindings.put(iface, impl);
    }

    // 싱글턴 등록
    <T> void singleton(Class<T> type, T instance) {
        instances.put(type, instance);
    }

    // 의존성 해결
    @SuppressWarnings("unchecked")
    <T> T resolve(Class<T> type) {
        if (instances.containsKey(type)) {
            return (T) instances.get(type);
        }
        Class<?> impl = bindings.getOrDefault(type, type);
        try {
            var ctors = impl.getConstructors();
            if (ctors.length == 0) return (T) impl.getDeclaredConstructor().newInstance();
            var ctor = ctors[0];
            Object[] params = Arrays.stream(ctor.getParameterTypes())
                .map(this::resolve)
                .toArray();
            T instance = (T) ctor.newInstance(params);
            instances.put(type, instance);
            return instance;
        } catch (Exception e) {
            throw new RuntimeException("DI 실패: " + type.getName(), e);
        }
    }
}

interface GreetService { String greet(String name); }
class GreetServiceImpl implements GreetService {
    public String greet(String name) { return "Hello, " + name; }
}

class AppController {
    private final GreetService service;
    AppController(GreetService service) { this.service = service; }
    String handle(String name) { return service.greet(name); }
}

class Main {
    public static void main(String[] args) {
        DIContainer di = new DIContainer();
        di.bind(GreetService.class, GreetServiceImpl.class);
        AppController ctrl = di.resolve(AppController.class);
        System.out.println(ctrl.handle("Java"));
    }
}

학습 팁

생성자 주입이 가장 권장됩니다. 의존성이 명시적이고, 불변 필드로 만들 수 있으며, 테스트 시 Mock을 쉽게 주입할 수 있습니다.

주의할 점

필드 주입(@Autowired 필드)은 테스트가 어렵고 의존성이 숨겨집니다. 생성자 주입을 사용하세요.

자주 묻는 질문

DI(의존성 주입) 원리란 무엇인가요?

Spring의 핵심 원리인 의존성 주입을 직접 구현하여 이해합니다.

DI(의존성 주입) 원리 학습 시 주의할 점은 무엇인가요?

필드 주입( @Autowired 필드)은 테스트가 어렵고 의존성이 숨겨집니다. 생성자 주입을 사용하세요.